pywargame 0.3.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. pywargame/__init__.py +2 -0
  2. pywargame/common/__init__.py +3 -0
  3. pywargame/common/collector.py +87 -0
  4. pywargame/common/dicedraw.py +363 -0
  5. pywargame/common/drawdice.py +40 -0
  6. pywargame/common/singleton.py +22 -0
  7. pywargame/common/test.py +25 -0
  8. pywargame/common/verbose.py +59 -0
  9. pywargame/common/verboseguard.py +53 -0
  10. pywargame/cyberboard/__init__.py +18 -0
  11. pywargame/cyberboard/archive.py +283 -0
  12. pywargame/cyberboard/base.py +63 -0
  13. pywargame/cyberboard/board.py +462 -0
  14. pywargame/cyberboard/cell.py +200 -0
  15. pywargame/cyberboard/collect.py +49 -0
  16. pywargame/cyberboard/collectgbx0pwd.py +30 -0
  17. pywargame/cyberboard/collectgbxext.py +30 -0
  18. pywargame/cyberboard/collectgsnexp.py +32 -0
  19. pywargame/cyberboard/collectgsnext.py +30 -0
  20. pywargame/cyberboard/draw.py +396 -0
  21. pywargame/cyberboard/exporter.py +1132 -0
  22. pywargame/cyberboard/extractor.py +240 -0
  23. pywargame/cyberboard/features.py +17 -0
  24. pywargame/cyberboard/gamebox.py +81 -0
  25. pywargame/cyberboard/gbxexp.py +76 -0
  26. pywargame/cyberboard/gbxext.py +64 -0
  27. pywargame/cyberboard/gsnexp.py +147 -0
  28. pywargame/cyberboard/gsnext.py +59 -0
  29. pywargame/cyberboard/head.py +111 -0
  30. pywargame/cyberboard/image.py +76 -0
  31. pywargame/cyberboard/main.py +47 -0
  32. pywargame/cyberboard/mark.py +102 -0
  33. pywargame/cyberboard/palette.py +36 -0
  34. pywargame/cyberboard/piece.py +169 -0
  35. pywargame/cyberboard/player.py +36 -0
  36. pywargame/cyberboard/scenario.py +115 -0
  37. pywargame/cyberboard/testgrid.py +156 -0
  38. pywargame/cyberboard/tile.py +121 -0
  39. pywargame/cyberboard/tray.py +68 -0
  40. pywargame/cyberboard/windows.py +41 -0
  41. pywargame/cyberboard/zeropwd.py +45 -0
  42. pywargame/cyberboard.py +2728 -0
  43. pywargame/gbx0pwd.py +2776 -0
  44. pywargame/gbxextract.py +2795 -0
  45. pywargame/gsnexport.py +16499 -0
  46. pywargame/gsnextract.py +2790 -0
  47. pywargame/latex/__init__.py +2 -0
  48. pywargame/latex/collect.py +34 -0
  49. pywargame/latex/latexexporter.py +4010 -0
  50. pywargame/latex/main.py +184 -0
  51. pywargame/vassal/__init__.py +66 -0
  52. pywargame/vassal/base.py +139 -0
  53. pywargame/vassal/board.py +243 -0
  54. pywargame/vassal/buildfile.py +60 -0
  55. pywargame/vassal/chart.py +79 -0
  56. pywargame/vassal/chessclock.py +197 -0
  57. pywargame/vassal/collect.py +98 -0
  58. pywargame/vassal/collectpatch.py +28 -0
  59. pywargame/vassal/command.py +21 -0
  60. pywargame/vassal/documentation.py +322 -0
  61. pywargame/vassal/dumpcollect.py +28 -0
  62. pywargame/vassal/dumpvsav.py +28 -0
  63. pywargame/vassal/element.py +439 -0
  64. pywargame/vassal/exporter.py +89 -0
  65. pywargame/vassal/extension.py +101 -0
  66. pywargame/vassal/folder.py +103 -0
  67. pywargame/vassal/game.py +940 -0
  68. pywargame/vassal/gameelements.py +1091 -0
  69. pywargame/vassal/globalkey.py +127 -0
  70. pywargame/vassal/globalproperty.py +433 -0
  71. pywargame/vassal/grid.py +573 -0
  72. pywargame/vassal/map.py +1061 -0
  73. pywargame/vassal/mapelements.py +1020 -0
  74. pywargame/vassal/merge.py +57 -0
  75. pywargame/vassal/merger.py +460 -0
  76. pywargame/vassal/moduledata.py +275 -0
  77. pywargame/vassal/mrgcollect.py +31 -0
  78. pywargame/vassal/patch.py +44 -0
  79. pywargame/vassal/patchcollect.py +28 -0
  80. pywargame/vassal/player.py +83 -0
  81. pywargame/vassal/save.py +495 -0
  82. pywargame/vassal/skel.py +380 -0
  83. pywargame/vassal/trait.py +224 -0
  84. pywargame/vassal/traits/__init__.py +36 -0
  85. pywargame/vassal/traits/area.py +50 -0
  86. pywargame/vassal/traits/basic.py +35 -0
  87. pywargame/vassal/traits/calculatedproperty.py +22 -0
  88. pywargame/vassal/traits/cargo.py +29 -0
  89. pywargame/vassal/traits/click.py +41 -0
  90. pywargame/vassal/traits/clone.py +28 -0
  91. pywargame/vassal/traits/delete.py +24 -0
  92. pywargame/vassal/traits/deselect.py +32 -0
  93. pywargame/vassal/traits/dynamicproperty.py +112 -0
  94. pywargame/vassal/traits/globalcommand.py +55 -0
  95. pywargame/vassal/traits/globalhotkey.py +26 -0
  96. pywargame/vassal/traits/globalproperty.py +54 -0
  97. pywargame/vassal/traits/hide.py +67 -0
  98. pywargame/vassal/traits/label.py +76 -0
  99. pywargame/vassal/traits/layer.py +105 -0
  100. pywargame/vassal/traits/mark.py +20 -0
  101. pywargame/vassal/traits/mask.py +85 -0
  102. pywargame/vassal/traits/mat.py +26 -0
  103. pywargame/vassal/traits/moved.py +35 -0
  104. pywargame/vassal/traits/movefixed.py +51 -0
  105. pywargame/vassal/traits/nonrect.py +95 -0
  106. pywargame/vassal/traits/nostack.py +55 -0
  107. pywargame/vassal/traits/place.py +104 -0
  108. pywargame/vassal/traits/prototype.py +20 -0
  109. pywargame/vassal/traits/report.py +34 -0
  110. pywargame/vassal/traits/restrictaccess.py +28 -0
  111. pywargame/vassal/traits/restrictcommand.py +32 -0
  112. pywargame/vassal/traits/return.py +40 -0
  113. pywargame/vassal/traits/rotate.py +62 -0
  114. pywargame/vassal/traits/sendto.py +59 -0
  115. pywargame/vassal/traits/sheet.py +129 -0
  116. pywargame/vassal/traits/skel.py +9 -0
  117. pywargame/vassal/traits/stack.py +28 -0
  118. pywargame/vassal/traits/submenu.py +27 -0
  119. pywargame/vassal/traits/trail.py +61 -0
  120. pywargame/vassal/traits/trigger.py +72 -0
  121. pywargame/vassal/turn.py +272 -0
  122. pywargame/vassal/upgrade.py +191 -0
  123. pywargame/vassal/vmod.py +323 -0
  124. pywargame/vassal/vsav.py +100 -0
  125. pywargame/vassal/widget.py +358 -0
  126. pywargame/vassal/withtraits.py +634 -0
  127. pywargame/vassal/xml.py +4 -0
  128. pywargame/vassal/zone.py +399 -0
  129. pywargame/vassal.py +12500 -0
  130. pywargame/vmodpatch.py +12548 -0
  131. pywargame/vsavdump.py +12533 -0
  132. pywargame/vslmerge.py +13015 -0
  133. pywargame/wgexport.py +16689 -0
  134. pywargame/ztexport.py +14351 -0
  135. pywargame/zuntzu/__init__.py +5 -0
  136. pywargame/zuntzu/base.py +82 -0
  137. pywargame/zuntzu/collect.py +38 -0
  138. pywargame/zuntzu/countersheet.py +250 -0
  139. pywargame/zuntzu/dicehand.py +48 -0
  140. pywargame/zuntzu/exporter.py +936 -0
  141. pywargame/zuntzu/gamebox.py +154 -0
  142. pywargame/zuntzu/map.py +36 -0
  143. pywargame/zuntzu/piece.py +37 -0
  144. pywargame/zuntzu/scenario.py +208 -0
  145. pywargame/zuntzu/ztexp.py +115 -0
  146. pywargame-0.3.1.dist-info/METADATA +353 -0
  147. pywargame-0.3.1.dist-info/RECORD +150 -0
  148. pywargame-0.3.1.dist-info/WHEEL +5 -0
  149. pywargame-0.3.1.dist-info/licenses/LICENSE +5 -0
  150. pywargame-0.3.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,1020 @@
1
+ ## BEGIN_IMPORT
2
+ from common import VerboseGuard
3
+ from . base import *
4
+ from . element import Element
5
+ from . withtraits import *
6
+ from . globalkey import *
7
+ ## END_IMPORT
8
+
9
+ # --------------------------------------------------------------------
10
+ class MapElementService:
11
+ def getMap(self):
12
+ '''Get map - either a Map or WidgetMap'''
13
+ ## BEGIN_IMPORT
14
+ from . map import WidgetMap, Map
15
+ ## END_IMPORT
16
+ return self.getParentOfClass([WidgetMap,Map])
17
+ # if self._parent is None:
18
+ # return None
19
+ #
20
+ # if 'WidgetMap' in self._parent.tagName:
21
+ # return self.getParent(WidgetMap)
22
+ #
23
+ # return self.getParent(Map)
24
+ def getGame(self):
25
+ m = self.getMap()
26
+ if m is not None: return m.getGame()
27
+ return None
28
+
29
+ # --------------------------------------------------------------------
30
+ class MapElement(Element,MapElementService):
31
+ def __init__(self,map,tag,node=None,**kwargs):
32
+ super(MapElement,self).__init__(map,tag,node=node,**kwargs)
33
+
34
+
35
+ # --------------------------------------------------------------------
36
+ class PieceLayers(MapElement):
37
+ TAG=Element.MAP+'LayeredPieceCollection'
38
+ UNIQUE = ['property']
39
+ def __init__(self,map,node=None,
40
+ property = 'PieceLayer',
41
+ description = '',
42
+ layerOrder = []):
43
+ super(PieceLayers,self).__init__(map,self.TAG,node=node,
44
+ property = property,
45
+ description = description,
46
+ layerOrder = ','.join(layerOrder))
47
+
48
+ def addControl(self,**kwargs):
49
+ '''Add `LayerControl` element to this
50
+
51
+ Parameters
52
+ ----------
53
+ kwargs : dict
54
+ Dictionary of attribute key-value pairs
55
+
56
+ Returns
57
+ -------
58
+ element : LayerControl
59
+ The added element
60
+ '''
61
+ return self.add(LayerControl,**kwargs)
62
+ def getControls(self,asdict=True):
63
+ '''Get all `LayerControl` element(s) from this
64
+
65
+ Parameters
66
+ ----------
67
+ asdict : bool
68
+ If `True`, return a dictonary that maps name to
69
+ `LayerControl` elements. If `False`, return a list of all
70
+ `LayerControl` children.
71
+
72
+ Returns
73
+ -------
74
+ children : dict or list
75
+ Dictionary or list of `LayerControl` children
76
+
77
+ '''
78
+ return self.getElementsByKey(LayerControl,'name',asdict)
79
+
80
+ registerElement(PieceLayers)
81
+
82
+ # --------------------------------------------------------------------
83
+ class LayerControl(MapElement):
84
+ TAG=Element.MAP+'LayerControl'
85
+ CYCLE_UP='Rotate Layer Order Up'
86
+ CYCLE_DOWN='Rotate Layer Order Down'
87
+ ENABLE='Make Layer Active'
88
+ DISABLE='Make Layer Inactive'
89
+ TOGGLE='Switch Layer between Active and Inactive'
90
+ RESET='Reset All Layers'
91
+ UNIQUE = ['name']
92
+ def __init__(self,col,node=None,
93
+ name = '',
94
+ tooltip = '',
95
+ text = '',
96
+ hotkey = '',
97
+ icon = '',
98
+ canDisable = False,
99
+ propertyGate = '', #Property name, disable when property false
100
+ disabledIcon = '',
101
+ command = TOGGLE,
102
+ skip = False,
103
+ layers = [],
104
+ description = ''):
105
+ super(LayerControl,self).__init__(col,self.TAG,node=node,
106
+ name = name,
107
+ tooltip = tooltip,
108
+ text = text,
109
+ buttonText = text,
110
+ hotkey = hotkey,
111
+ icon = icon,
112
+ canDisable = canDisable,
113
+ propertyGate = propertyGate,
114
+ disabledIcon = disabledIcon,
115
+ command = command,
116
+ skip = skip,
117
+ layers = ','.join(layers),
118
+ description = description)
119
+
120
+ def getLayers(self):
121
+ '''Get map - either a Map or WidgetMap'''
122
+ return self.getParentOfClass([PieceLayers])
123
+
124
+ registerElement(LayerControl)
125
+
126
+
127
+ # --------------------------------------------------------------------
128
+ class LineOfSight(MapElement):
129
+ TAG=Element.MAP+'LOS_Thread'
130
+ ROUND_UP = 'Up'
131
+ ROUND_DOWN = 'Down'
132
+ ROUND_NEAREST = 'Nearest whole number'
133
+ FROM_LOCATION = 'FromLocation'
134
+ TO_LOCATION = 'ToLocation'
135
+ CHECK_COUNT = 'NumberOfLocationsChecked'
136
+ CHECK_LIST = 'AllLocationsChecked'
137
+ RANGE = 'Range'
138
+ NEVER = 'Never'
139
+ ALWAYS = 'Always'
140
+ WHEN_PERSISTENT = 'When persistent'
141
+ CTRL_CLICK = 'Cltr-Click & Drag'
142
+ UNIQUE = ['threadName']
143
+
144
+ def __init__(self,map,
145
+ node=None,
146
+ threadName = 'LOS',
147
+ hotkey = key('L',ALT),
148
+ tooltip = 'Trace line of sight',
149
+ iconName = '/images/thread.gif', #'los-icon.png',
150
+ label = '',
151
+ snapLOS = False,
152
+ snapStart = True,
153
+ snapEnd = True,
154
+ report = (f'{{"Range from "+{FROM_LOCATION}'
155
+ f'+" to "+{TO_LOCATION}+" is "'
156
+ f'+{RANGE}+" (via "+{CHECK_LIST}+")"}}'),
157
+ persistent = CTRL_CLICK,
158
+ persistentIconName = '/images/thread.gif',
159
+ globl = ALWAYS,
160
+ losThickness = 3,
161
+ threadColor = rgb(255,0,0),
162
+ drawRange = True,
163
+ # rangeBg = rgb(255,255,255),
164
+ # rangeFg = rgb(0,0,0),
165
+ rangeScale = 0,
166
+ hideCounters = True,
167
+ hideOpacity = 50,
168
+ round = ROUND_UP,
169
+ canDisable = False,
170
+ propertyGate = '',
171
+ disabledIcon = ''):
172
+ '''Make Line of Sight interface
173
+
174
+ Parameters
175
+ ----------
176
+ threadName : str
177
+ Name of interface
178
+ hotkey : str
179
+ Start LOS key
180
+ tooltip : str
181
+ Tool tip text
182
+ iconName : str
183
+ Path to button icon
184
+ label : str
185
+ Button text
186
+ snapLOS : bool
187
+ Wether to snap both ends
188
+ snapStart : bool
189
+ Snap to start
190
+ snapEnd: bool
191
+ Snap to end
192
+ report : str
193
+ Report format
194
+ persistent : str
195
+ When persistent
196
+ persistentIconName : str
197
+ Icon when persistent(?)
198
+ globl : str
199
+ Visisble to opponents
200
+ losThickness : int
201
+ Thickness in pixels
202
+ losColor : str
203
+ Colour of line
204
+ drawRange : bool
205
+ Draw the range next to LOST thread
206
+ rangeBg : str
207
+ Range backgroung colour
208
+ rangeFg : str
209
+ Range foregrond colour
210
+ rangeScale : int
211
+ Scale of range - pixels per unit
212
+ round : str
213
+ How to round range
214
+ hideCounters :bool
215
+ If true, hide counters while making thread
216
+ hideOpacity : int
217
+ Opacity of hidden counters (percent)
218
+ canDisable : bool
219
+ IF true, then can be hidden
220
+ propertyGate : str
221
+ Name of property. When that property is TRUE, then the
222
+ interface is disabled. Must be a property name, not an expression.
223
+ disabledIcon : str
224
+ Icon to use when disabled
225
+ '''
226
+ super(LineOfSight,self).__init__(map,self.TAG,
227
+ node = node,
228
+ threadName = threadName,
229
+ hotkey = hotkey,
230
+ tooltip = tooltip,
231
+ iconName = iconName,
232
+ label = label,
233
+ snapLOS = snapLOS,
234
+ snapStart = snapStart,
235
+ snapEnd = snapEnd,
236
+ report = report,
237
+ persistent = persistent,
238
+ persistentIconName = persistentIconName,
239
+ losThickness = losThickness,
240
+ threadColor = threadColor,
241
+ drawRange = drawRange,
242
+ #rangeBg = rangeBg,
243
+ #rangeFg = rangeFg,
244
+ rangeScale = rangeScale,
245
+ hideCounters = hideCounters,
246
+ hideOpacity = hideOpacity,
247
+ round = round,
248
+ canDisable = canDisable,
249
+ propertyGate = propertyGate,
250
+ disabledIcon = disabledIcon)
251
+ self.setAttribute('global',globl)
252
+
253
+
254
+ registerElement(LineOfSight)
255
+
256
+ # --------------------------------------------------------------------
257
+ class StackMetrics(MapElement):
258
+ TAG=Element.MAP+'StackMetrics'
259
+ def __init__(self,map,node=None,
260
+ bottom = key('(',0),
261
+ down = key('%',0),
262
+ top = key('&',0),
263
+ up = key("'",0),
264
+ disabled = False,
265
+ exSepX = 6, # Expanded (after double click)
266
+ exSepY = 18, # Expanded (after double click)
267
+ unexSepX = 8, # Compact
268
+ unexSepY = 16): # Compact
269
+ super(StackMetrics,self).__init__(map,self.TAG,node=node,
270
+ bottom = bottom,
271
+ disabled = disabled,
272
+ down = down,
273
+ exSepX = exSepX,
274
+ exSepY = exSepY,
275
+ top = top,
276
+ unexSepX = unexSepX,
277
+ unexSepY = unexSepY,
278
+ up = up)
279
+
280
+ registerElement(StackMetrics)
281
+
282
+ # --------------------------------------------------------------------
283
+ class ImageSaver(MapElement):
284
+ TAG=Element.MAP+'ImageSaver'
285
+ def __init__(self,map,node=None,
286
+ buttonText = '',
287
+ canDisable = False,
288
+ hotkey = '',
289
+ icon = '/images/camera.gif',
290
+ propertyGate = '',
291
+ tooltip = 'Save map as PNG image'):
292
+ super(ImageSaver,self).__init__(map,self.TAG,node=node,
293
+ buttonText = buttonText,
294
+ canDisable = canDisable,
295
+ hotkey = hotkey,
296
+ icon = icon,
297
+ propertyGate = propertyGate,
298
+ tooltip = tooltip)
299
+
300
+ registerElement(ImageSaver)
301
+
302
+ # --------------------------------------------------------------------
303
+ class TextSaver(MapElement):
304
+ TAG=Element.MAP+'TextSaver'
305
+ def __init__(self,map,node=None,
306
+ buttonText = '',
307
+ canDisable = False,
308
+ hotkey = '',
309
+ icon = '/images/camera.gif',
310
+ propertyGate = '',
311
+ tooltip = 'Save map as text'):
312
+ super(TextSaver,self).__init__(map,self.TAG,node=node,
313
+ buttonText = buttonText,
314
+ canDisable = canDisable,
315
+ hotkey = hotkey,
316
+ icon = icon,
317
+ propertyGate = propertyGate,
318
+ tooltip = tooltip)
319
+
320
+ registerElement(TextSaver)
321
+
322
+ # --------------------------------------------------------------------
323
+ class ForwardToChatter(MapElement):
324
+ TAG=Element.MAP+'ForwardToChatter'
325
+ def __init__(self,map,node=None,**kwargs):
326
+ super(ForwardToChatter,self).__init__(map,self.TAG,node=node,**kwargs)
327
+
328
+ registerElement(ForwardToChatter)
329
+
330
+ # --------------------------------------------------------------------
331
+ class MenuDisplayer(MapElement):
332
+ TAG=Element.MAP+'MenuDisplayer'
333
+ def __init__(self,map,node=None,**kwargs):
334
+ super(MenuDisplayer,self).__init__(map,self.TAG,node=node,**kwargs)
335
+
336
+ registerElement(MenuDisplayer)
337
+
338
+ # --------------------------------------------------------------------
339
+ class MapCenterer(MapElement):
340
+ TAG=Element.MAP+'MapCenterer'
341
+ def __init__(self,map,node=None,**kwargs):
342
+ super(MapCenterer,self).__init__(map,self.TAG,node=node,**kwargs)
343
+
344
+ registerElement(MapCenterer)
345
+
346
+ # --------------------------------------------------------------------
347
+ class StackExpander(MapElement):
348
+ TAG=Element.MAP+'StackExpander'
349
+ def __init__(self,map,node=None,**kwargs):
350
+ super(StackExpander,self).__init__(map,self.TAG,node=node,**kwargs)
351
+
352
+ registerElement(StackExpander)
353
+
354
+ # --------------------------------------------------------------------
355
+ class PieceMover(MapElement):
356
+ TAG=Element.MAP+'PieceMover'
357
+ def __init__(self,map,node=None,**kwargs):
358
+ super(PieceMover,self).__init__(map,self.TAG,node=node,**kwargs)
359
+
360
+ registerElement(PieceMover)
361
+
362
+ # --------------------------------------------------------------------
363
+ class SelectionHighlighters(MapElement):
364
+ TAG=Element.MAP+'SelectionHighlighters'
365
+ def __init__(self,map,node=None,**kwargs):
366
+ super(SelectionHighlighters,self).\
367
+ __init__(map,self.TAG,node=node,**kwargs)
368
+
369
+ registerElement(SelectionHighlighters)
370
+
371
+ # --------------------------------------------------------------------
372
+ class KeyBufferer(MapElement):
373
+ TAG=Element.MAP+'KeyBufferer'
374
+ def __init__(self,map,node=None,**kwargs):
375
+ super(KeyBufferer,self).__init__(map,self.TAG,node=node,**kwargs)
376
+
377
+ registerElement(KeyBufferer)
378
+
379
+ # --------------------------------------------------------------------
380
+ class HighlightLastMoved(MapElement):
381
+ TAG=Element.MAP+'HighlightLastMoved'
382
+ def __init__(self,map,node=None,
383
+ color = rgb(255,0,0),
384
+ enabled = True,
385
+ thickness = 2):
386
+ super(HighlightLastMoved,self).__init__(map,self.TAG,node=node,
387
+ color = color,
388
+ enabled = enabled,
389
+ thickness = thickness)
390
+
391
+ registerElement(HighlightLastMoved)
392
+
393
+ # --------------------------------------------------------------------
394
+ class CounterDetailViewer(MapElement):
395
+ TAG=Element.MAP+'CounterDetailViewer'
396
+ TOP_LAYER = 'from top-most layer only'
397
+ ALL_LAYERS = 'from all layers'
398
+ INC_LAYERS = 'from listed layers only'
399
+ EXC_LAYERS = 'from layers other than those listed'
400
+ FILTER = 'by using a property filter'
401
+ ALWAYS = 'always'
402
+ NEVER = 'never'
403
+ IF_ONE = 'ifOne'
404
+ UNIQUE = ['description']
405
+ def __init__(self,map,node=None,
406
+ borderWidth = 0, # Horizontal padding between pieces
407
+ borderThickness = 2, # Outer border thickness
408
+ borderInnerThickness = 2, # Inner borders thickness
409
+ borderColor = None,
410
+ centerAll = False,
411
+ centerText = False,
412
+ centerPiecesVertically = True,
413
+ combineCounterSummary = False,
414
+ counterReportFormat = '',
415
+ delay = 700,
416
+ description = '',
417
+ display = TOP_LAYER,
418
+ emptyHexReportForma = '$LocationName$',
419
+ enableHTML = True,
420
+ extraTextPadding = 0,
421
+ bgColor = None,
422
+ fgColor = rgb(0,0,0),
423
+ fontSize = 11,
424
+ graphicsZoom = 1.0,# Zoom on counters
425
+ hotkey = key('\n'),
426
+ layerList = [],
427
+ minDisplayPieces = 2,
428
+ propertyFilter = '',
429
+ showDeck = False,
430
+ showDeckDepth = 1,
431
+ showDeckMasked = False,
432
+ showMoveSelected = False,
433
+ showNoStack = False,
434
+ showNonMovable = False,
435
+ showOverlap = False,
436
+ showgraph = True,
437
+ showgraphsingle = False,
438
+ showtext = True,
439
+ showtextsingle = False,
440
+ stretchWidthSummary = False,
441
+ summaryReportFormat = '$LocationName$',
442
+ unrotatePieces = False,
443
+ version = 4,
444
+ verticalOffset = 2,
445
+ verticalTopText = 0,
446
+ zoomlevel = 1.0,
447
+ stopAfterShowing = False,
448
+ showTerrainBeneath = NEVER,
449
+ showTerrainSnappy = True,
450
+ showTerrainWidth = 120,
451
+ showTerrainHeight = 120,
452
+ showTerrainZoom = None,
453
+ showTerrainText = ''
454
+ ): # showTerrain attributes
455
+
456
+ bg = '' if bgColor is None else bgColor
457
+ fg = '' if fgColor is None else fgColor
458
+ bc = '' if borderColor is None else borderColor
459
+ ll = ','.join(layerList)
460
+ showTerrainZoom = zoomlevel if showTerrainZoom == None else showTerrainZoom
461
+ super(CounterDetailViewer,self)\
462
+ .__init__(map,self.TAG,node=node,
463
+ borderWidth = borderWidth,
464
+ borderThickness = borderThickness,
465
+ borderInnerThickness = borderInnerThickness,
466
+ borderColor = bc,
467
+ centerAll = centerAll,
468
+ centerText = centerText,
469
+ centerPiecesVertically = centerPiecesVertically,
470
+ combineCounterSummary = combineCounterSummary,
471
+ counterReportFormat = counterReportFormat,
472
+ delay = delay,
473
+ description = description,
474
+ display = display, # How to show from layers
475
+ emptyHexReportForma = emptyHexReportForma,
476
+ enableHTML = enableHTML,
477
+ extraTextPadding = extraTextPadding,
478
+ bgColor = bg,
479
+ fgColor = fg,
480
+ fontSize = fontSize,
481
+ graphicsZoom = graphicsZoom, # pieces at zoom
482
+ hotkey = hotkey,
483
+ layerList = ll,
484
+ minDisplayPieces = minDisplayPieces,
485
+ propertyFilter = propertyFilter,
486
+ showDeck = showDeck,
487
+ showDeckDepth = showDeckDepth,
488
+ showDeckMasked = showDeckMasked,
489
+ showMoveSelectde = showMoveSelected,
490
+ showNoStack = showNoStack,
491
+ showNonMovable = showNonMovable,
492
+ showOverlap = showOverlap,
493
+ showgraph = showgraph,
494
+ showgraphsingle = showgraphsingle,
495
+ showtext = showtext,
496
+ showtextsingle = showtextsingle,
497
+ stretchWidthSummary = stretchWidthSummary,
498
+ summaryReportFormat = summaryReportFormat,
499
+ unrotatePieces = unrotatePieces,
500
+ version = version,
501
+ verticalOffset = verticalOffset,
502
+ verticalTopText = verticalTopText,
503
+ zoomlevel = zoomlevel,
504
+ stopAfterShowing = stopAfterShowing,
505
+ showTerrainBeneath = showTerrainBeneath,
506
+ showTerrainSnappy = showTerrainSnappy,
507
+ showTerrainWidth = showTerrainWidth,
508
+ showTerrainHeight = showTerrainHeight,
509
+ showTerrainZoom = showTerrainZoom,
510
+ showTerrainText = showTerrainText)
511
+
512
+ registerElement(CounterDetailViewer)
513
+
514
+ # --------------------------------------------------------------------
515
+ class GlobalMap(MapElement):
516
+ TAG=Element.MAP+'GlobalMap'
517
+ def __init__(self,map,node=None,
518
+ buttonText = '',
519
+ color = rgb(255,0,0),
520
+ hotkey = key('O',CTRL_SHIFT),
521
+ icon = '/images/overview.gif',
522
+ scale = 0.2,
523
+ tooltip = 'Show/Hide overview window'):
524
+ super(GlobalMap,self).\
525
+ __init__(map,self.TAG,node=node,
526
+ buttonText = buttonText,
527
+ color = color,
528
+ hotkey = hotkey,
529
+ icon = icon,
530
+ scale = scale,
531
+ tooltip = 'Show/Hide overview window')
532
+
533
+ registerElement(GlobalMap)
534
+
535
+ # --------------------------------------------------------------------
536
+ class Zoomer(MapElement):
537
+ TAG = Element.MAP+'Zoomer'
538
+ def __init__(self,map,node=None,
539
+ inButtonText = '',
540
+ inIconName = '/images/zoomIn.gif',
541
+ inTooltip = 'Zoom in',
542
+ outButtonText = '',
543
+ outIconName = '/images/zoomOut.gif',
544
+ outTooltip = 'Zoom out',
545
+ pickButtonText = '',
546
+ pickIconName = '/images/zoom.png',
547
+ pickTooltip = 'Select Zoom',
548
+ zoomInKey = key('=',CTRL_SHIFT),
549
+ zoomLevels = [0.2,0.25,0.333,0.4,0.5,
550
+ 0.555,0.625,0.75,1.0,1.25,1.6],
551
+ zoomOutKey = key('-'),
552
+ zoomPickKey = key('='),
553
+ zoomStart = 3):
554
+
555
+ '''Zoom start is counting from the back (with default zoom levels,
556
+ and zoom start, the default zoom is 1'''
557
+ lvls = ','.join([str(z) for z in zoomLevels])
558
+ super(Zoomer,self).\
559
+ __init__(map,self.TAG,node=node,
560
+ inButtonText = inButtonText,
561
+ inIconName = inIconName,
562
+ inTooltip = inTooltip,
563
+ outButtonText = outButtonText,
564
+ outIconName = outIconName,
565
+ outTooltip = outTooltip,
566
+ pickButtonText = pickButtonText,
567
+ pickIconName = pickIconName,
568
+ pickTooltip = pickTooltip,
569
+ zoomInKey = zoomInKey,
570
+ zoomLevels = lvls,
571
+ zoomOutKey = zoomOutKey,
572
+ zoomPickKey = zoomPickKey,
573
+ zoomStart = zoomStart)
574
+
575
+ registerElement(Zoomer)
576
+
577
+ # --------------------------------------------------------------------
578
+ class HidePiecesButton(MapElement):
579
+ TAG=Element.MAP+'HidePiecesButton'
580
+ def __init__(self,map,node=None,
581
+ buttonText = '',
582
+ hiddenIcon = '/images/globe_selected.gif',
583
+ hotkey = key('O'),
584
+ showingIcon = '/images/globe_unselected.gif',
585
+ tooltip = 'Hide all pieces on this map'):
586
+ super(HidePiecesButton,self).\
587
+ __init__(map,self.TAG,node=node,
588
+ buttonText = buttonText,
589
+ hiddenIcon = hiddenIcon,
590
+ hotkey = hotkey,
591
+ showingIcon = showingIcon,
592
+ tooltip = tooltip)
593
+
594
+ registerElement(HidePiecesButton)
595
+
596
+ # --------------------------------------------------------------------
597
+ class MassKey(GlobalKey,MapElementService):
598
+ TAG = Element.MAP+'MassKeyCommand'
599
+ UNIQUE = ['name']
600
+ def __init__(self,map,node=None,
601
+ name = '',
602
+ buttonHotkey = '',
603
+ hotkey = '',
604
+ buttonText = '',
605
+ canDisable = False,
606
+ deckCount = '-1',
607
+ filter = '',
608
+ propertyGate = '',
609
+ reportFormat = '',
610
+ reportSingle = False,
611
+ singleMap = True,
612
+ target = GlobalKey.SELECTED,
613
+ tooltip = '',
614
+ icon = ''):
615
+ '''Default targets are selected units'''
616
+ super(MassKey,self).\
617
+ __init__(map,self.TAG,node=node,
618
+ name = name,
619
+ buttonHotkey = buttonHotkey, # This hot key
620
+ hotkey = hotkey, # Target hot key
621
+ buttonText = buttonText,
622
+ canDisable = canDisable,
623
+ deckCount = deckCount,
624
+ filter = filter,
625
+ propertyGate = propertyGate,
626
+ reportFormat = reportFormat,
627
+ reportSingle = reportSingle,
628
+ singleMap = singleMap,
629
+ target = target,
630
+ tooltip = tooltip,
631
+ icon = icon)
632
+
633
+ registerElement(MassKey)
634
+
635
+ # --------------------------------------------------------------------
636
+ class Flare(MapElement):
637
+ TAG=Element.MAP+'Flare'
638
+ def __init__(self,map,node=None,
639
+ circleColor = rgb(255,0,0),
640
+ circleScale = True,
641
+ circleSize = 100,
642
+ flareKey = 'keyAlt',
643
+ flareName = 'Map Flare',
644
+ flarePulses = 6,
645
+ flarePulsesPerSec = 3,
646
+ reportFormat = ''):
647
+ super(Flare,self).__init__(map,self.TAG,node=node,
648
+ circleColor = circleColor,
649
+ circleScale = circleScale,
650
+ circleSize = circleSize,
651
+ flareKey = flareKey,
652
+ flareName = flareName,
653
+ flarePulses = flarePulses,
654
+ flarePulsesPerSec = flarePulsesPerSec,
655
+ reportFormat = '')
656
+
657
+ registerElement(Flare)
658
+
659
+ # --------------------------------------------------------------------
660
+ class Deck(MapElement):
661
+ TAG = Element.MODULE+'map.DrawPile'
662
+ ALWAYS = 'Always'
663
+ NEVER = 'Never',
664
+ VIA_MOUSE2 = 'Via right-click Menu'
665
+ UNIQUE = ['name','owningBoard']
666
+ def __init__(self,map,
667
+ node = None,
668
+ name = 'deckName',
669
+ owningBoard = '',
670
+ x = 0, # int
671
+ y = 0, # int
672
+ width = 200, # int
673
+ height = 200, # int
674
+ #
675
+ allowMultiple = False,
676
+ drawMultipleMessage = 'Draw multiple cards',
677
+ #
678
+ allowSelect = False,
679
+ drawSpecificMessage = 'Draw specific cards',
680
+ selectDisplayProperty = '$BasicName$',
681
+ selectSortProperty = 'BasicName',
682
+ #
683
+ faceDown = ALWAYS,#ALWAYS,VIA_MOUSE2
684
+ faceFlipHotkey = key('F'),
685
+ faceDownFormat = '',
686
+ faceDownHotkey = '',
687
+ faceDownMessage = 'Face down',
688
+ faceUpHotkey = '',
689
+ faceUpMessage = 'Face up',
690
+ faceUpReportFormat = '',
691
+ drawFaceUp = False,
692
+ #
693
+ shuffle = VIA_MOUSE2,#ALWAYS,NEVER
694
+ shuffleCommand = 'Shuffle',
695
+ shuffleFormat = '$playerSide$ shuffles $deckName$',
696
+ shuffleHotkey = key('S',ALT),
697
+ #
698
+ reversible = False,
699
+ reverseCommand = 'Reverse',
700
+ reverseFormat = '',
701
+ reverseHotkey = '',
702
+ #
703
+ draw = True,
704
+ color = rgb(255,51,51),
705
+ hotkeyOnEmpty = False,
706
+ emptyHotkey = key(NONE,0)+',DeckEmpty',
707
+ #
708
+ reshufflable = False,
709
+ reshuffleCommand = '',
710
+ reshuffleHotkey = '',
711
+ reshuffleMessage = '',
712
+ reshuffleTarget = '',
713
+ #
714
+ canSave = False,
715
+ saveHotkey = '',
716
+ saveMessage = 'Save Deck',
717
+ saveReportFormat = 'Deck Saved',
718
+ loadHotkey = '',
719
+ loadMessage = 'Load Deck',
720
+ loadReportFormat = 'Deck Loaded',
721
+ #
722
+ maxStack = 15,
723
+ #
724
+ expressionCounting = False,
725
+ countExpressions = '',
726
+ #
727
+ restrictExpression = '',
728
+ restrictOption = False,
729
+ #
730
+ deckOwners = '',
731
+ deckRestrictAccess = False
732
+ ): # int
733
+ pass
734
+ super(Deck,self).\
735
+ __init__(map,self.TAG,node=node,
736
+ name = name,
737
+ owningBoard = owningBoard,
738
+ x = int(x), # int
739
+ y = int(y), # int
740
+ width = int(width), # int
741
+ height = int(height), # int
742
+ #
743
+ allowMultiple = allowMultiple,
744
+ drawMultipleMessage = drawMultipleMessage,
745
+ #
746
+ allowSelect = allowSelect,
747
+ drawSpecificMessage = drawSpecificMessage,
748
+ selectDisplayProperty = selectDisplayProperty,
749
+ selectSortProperty = selectSortProperty,
750
+ #
751
+ faceDown = faceDown,
752
+ faceFlipHotkey = faceFlipHotkey,
753
+ faceDownFormat = faceDownFormat,
754
+ faceDownHotkey = faceDownHotkey,
755
+ faceDownMessage = faceDownMessage,
756
+ faceUpHotkey = faceUpHotkey,
757
+ faceUpMessage = faceUpMessage,
758
+ faceUpReportFormat = faceUpReportFormat,
759
+ drawFaceUp = drawFaceUp,
760
+ #
761
+ shuffle = shuffle,
762
+ shuffleCommand = shuffleCommand,
763
+ shuffleFormat = shuffleFormat,
764
+ shuffleHotkey = shuffleHotkey,
765
+ #
766
+ reversible = reversible,
767
+ reverseCommand = reverseCommand,
768
+ reverseFormat = reverseFormat,
769
+ reverseHotkey = reverseHotkey,
770
+ #
771
+ draw = draw,
772
+ color = color,
773
+ hotkeyOnEmpty = hotkeyOnEmpty,
774
+ emptyHotkey = emptyHotkey,
775
+ #
776
+ reshufflable = reshufflable,
777
+ reshuffleCommand = reshuffleCommand,
778
+ reshuffleHotkey = reshuffleHotkey,
779
+ reshuffleMessage = reshuffleMessage,
780
+ reshuffleTarget = reshuffleTarget,
781
+ #
782
+ canSave = canSave,
783
+ saveHotkey = saveHotkey,
784
+ saveMessage = saveMessage,
785
+ saveReportFormat = saveReportFormat,
786
+ loadHotkey = loadHotkey,
787
+ loadMessage = loadMessage,
788
+ loadReportFormat = loadReportFormat,
789
+ #
790
+ maxStack = maxStack,
791
+ #
792
+ expressionCounting = expressionCounting,
793
+ countExpressions = countExpressions,
794
+ #
795
+ restrictExpression = restrictExpression,
796
+ restrictOption = restrictOption,
797
+ #
798
+ deckOwners = deckOwners,
799
+ deckRestrictAccess = deckRestrictAccess
800
+ )
801
+
802
+ def addCard(self,**kwargs):
803
+ '''Add a `Card` element to this
804
+
805
+ Parameters
806
+ ----------
807
+ kwargs : dict
808
+ Dictionary of attribute key-value pairs
809
+
810
+ Returns
811
+ -------
812
+ element : Card
813
+ The added element
814
+ '''
815
+ if not isinstance(card,CardSlot):
816
+ print(f'Trying to add {type(card)} to Deck')
817
+ return None
818
+
819
+ p = card.clone(self)
820
+ # self._node.appendChild(p._node)
821
+ return p
822
+ def addFolder(self,**kwargs):
823
+ '''Add a `ModuleFolder` element to this
824
+
825
+ Parameters
826
+ ----------
827
+ kwargs : dict
828
+ Dictionary of attribute key-value pairs
829
+
830
+ Returns
831
+ -------
832
+ element : ModuleFolder
833
+ The added element
834
+ '''
835
+ return self.add(DeckFolder,**kwargs)
836
+
837
+ def getCards(self,asdict=True):
838
+ '''Get all Card element(s) from this
839
+
840
+ Parameters
841
+ ----------
842
+ asdict : bool
843
+ If `True`, return a dictonary that maps key to `Card`
844
+ elements. If `False`, return a list of all Card`
845
+ children.
846
+
847
+ Returns
848
+ -------
849
+ children : dict or list
850
+ Dictionary or list of `Card` children
851
+
852
+ '''
853
+ return self.getElementsByKey(CardSlot,'entryName',asdict)
854
+ def getFolders(self,asdict=True):
855
+ '''Get all Menu element(s) from this
856
+
857
+ Parameters
858
+ ----------
859
+ asdict : bool
860
+ If `True`, return a dictonary that maps key to `Folder`
861
+ elements. If `False`, return a list of all `Folder`
862
+ children.
863
+
864
+ Returns
865
+ -------
866
+ children : dict or list
867
+ Dictionary or list of `Folder` children
868
+
869
+ '''
870
+ return self.getElementsByKey(DeckFolder,'name',asdict)
871
+
872
+
873
+ registerElement(Deck)
874
+
875
+
876
+ # --------------------------------------------------------------------
877
+ class AtStart(MapElement):
878
+ TAG = Element.MODULE+'map.SetupStack'
879
+ UNIQUE = ['name','location','owningBoard']
880
+ def __init__(self,map,
881
+ node = None,
882
+ name = '',
883
+ location = '',
884
+ useGridLocation = True,
885
+ owningBoard = '',
886
+ x = 0,
887
+ y = 0):
888
+ '''Pieces are existing PieceSlot elements
889
+
890
+
891
+ Parameters
892
+ ----------
893
+ node : xml.minidom.Node
894
+ Existing node or None
895
+ name : str
896
+ Name of node
897
+ location : str
898
+ Where the at-start element is put if `useGridLocation`
899
+ useGridLocation : bool
900
+ If true, use maps grid
901
+ owningBoard : str
902
+ Board that owns the at-start (can be empty)
903
+ x : float
904
+ Coordinate (ignored if `useGridLocation`)
905
+ y : float
906
+ Coordinate (ignored if `useGridLocation`)
907
+ '''
908
+ super(AtStart,self).\
909
+ __init__(map,self.TAG,node=node,
910
+ name = name,
911
+ location = location,
912
+ owningBoard = owningBoard,
913
+ useGridLocation = useGridLocation,
914
+ x = x,
915
+ y = y)
916
+
917
+ def addPieces(self,*pieces):
918
+ '''Add a `Pieces` element to this
919
+
920
+ Parameters
921
+ ----------
922
+ kwargs : dict
923
+ Dictionary of attribute key-value pairs
924
+
925
+ Returns
926
+ -------
927
+ element : Pieces
928
+ The added element
929
+ '''
930
+ # copy pieces here
931
+ copies = []
932
+ for p in pieces:
933
+ c = self.addPiece(p)
934
+ if c is not None:
935
+ copies.append(c)
936
+ return copies
937
+
938
+ def addPiece(self,piece):
939
+ '''Add a `Piece` element to this
940
+
941
+ Parameters
942
+ ----------
943
+ kwargs : dict
944
+ Dictionary of attribute key-value pairs
945
+
946
+ Returns
947
+ -------
948
+ element : Piece
949
+ The added element
950
+ '''
951
+ if not isinstance(piece,WithTraitsSlot):
952
+ # Next is a bit of a hack - not nice
953
+ if piece.__class__.__name__ not in ['PieceSlot','CardSlot']:
954
+ print(f'Trying to add {type(piece)} to AtStart, '
955
+ f'not a {isinstance(piece,WithTraitsSlot)}')
956
+ return None
957
+
958
+ p = piece.clone(self)
959
+ # self._node.appendChild(p._node)
960
+ return p
961
+
962
+ def getPieces(self,asdict=True):
963
+ '''Get all Piece element(s) from this
964
+
965
+ Parameters
966
+ ----------
967
+ asdict : bool
968
+ If `True`, return a dictonary that maps key to `Piece`
969
+ elements. If `False`, return a list of all Piece`
970
+ children.
971
+
972
+ Returns
973
+ -------
974
+ children : dict or list
975
+ Dictionary or list of `Piece` children
976
+
977
+ '''
978
+ return self.getElementsByKey(PieceSlot,'entryName',asdict)
979
+
980
+ registerElement(AtStart)
981
+
982
+ # --------------------------------------------------------------------
983
+ class ForwardKeys(MapElement):
984
+ TAG = Element.MODULE+'map.ForwardToKeyBuffer'
985
+ def __init__(self,map,
986
+ node = None):
987
+ '''Forward keys to key buffer from where it is distributed to
988
+ selected pieces. Don't know how I missed this!
989
+
990
+ '''
991
+
992
+ super(ForwardKeys,self).\
993
+ __init__(map,self.TAG,node=node)
994
+
995
+ registerElement(ForwardKeys)
996
+
997
+ # --------------------------------------------------------------------
998
+ class Scroller(MapElement):
999
+ TAG = Element.MODULE+'map.Scroller'
1000
+ ALWAYS = 'always'
1001
+ NEVER = 'never'
1002
+ PROMPT = 'prompt'
1003
+ def __init__(self,map,
1004
+ node = None,
1005
+ useArrows = PROMPT):
1006
+ '''This component listens to key events on a Map window and
1007
+ scrolls the map. Depending on the useArrows attribute, will
1008
+ use number keypad or arrow keys, or will offer a preferences
1009
+ setting for the user to choose
1010
+ '''
1011
+
1012
+ super(Scroller,self).\
1013
+ __init__(map,self.TAG,node=node,
1014
+ useArrows = useArrows)
1015
+
1016
+ registerElement(Scroller)
1017
+
1018
+ #
1019
+ # EOF
1020
+ #