batframework 1.0.9a11__py3-none-any.whl → 1.0.10__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.
- batFramework/__init__.py +53 -76
- batFramework/action.py +99 -126
- batFramework/actionContainer.py +9 -53
- batFramework/animatedSprite.py +114 -56
- batFramework/audioManager.py +36 -82
- batFramework/camera.py +69 -263
- batFramework/constants.py +53 -29
- batFramework/cutscene.py +109 -243
- batFramework/cutsceneBlocks.py +176 -0
- batFramework/debugger.py +48 -0
- batFramework/dynamicEntity.py +9 -16
- batFramework/easing.py +71 -0
- batFramework/entity.py +85 -92
- batFramework/gui/__init__.py +3 -14
- batFramework/gui/button.py +78 -12
- batFramework/gui/constraints.py +204 -0
- batFramework/gui/container.py +31 -188
- batFramework/gui/debugger.py +43 -126
- batFramework/gui/frame.py +19 -0
- batFramework/gui/image.py +20 -55
- batFramework/gui/indicator.py +22 -95
- batFramework/gui/interactiveWidget.py +12 -229
- batFramework/gui/label.py +77 -311
- batFramework/gui/layout.py +66 -414
- batFramework/gui/root.py +35 -203
- batFramework/gui/shape.py +57 -247
- batFramework/gui/toggle.py +48 -114
- batFramework/gui/widget.py +243 -457
- batFramework/manager.py +29 -113
- batFramework/particles.py +77 -0
- batFramework/scene.py +217 -22
- batFramework/sceneManager.py +129 -161
- batFramework/stateMachine.py +8 -11
- batFramework/time.py +75 -0
- batFramework/transition.py +124 -129
- batFramework/transitionManager.py +0 -0
- batFramework/triggerZone.py +4 -4
- batFramework/utils.py +144 -266
- {batframework-1.0.9a11.dist-info → batframework-1.0.10.dist-info}/METADATA +24 -17
- batframework-1.0.10.dist-info/RECORD +43 -0
- batFramework/animation.py +0 -77
- batFramework/baseScene.py +0 -240
- batFramework/cutsceneManager.py +0 -34
- batFramework/drawable.py +0 -77
- batFramework/easingController.py +0 -58
- batFramework/enums.py +0 -135
- batFramework/fontManager.py +0 -65
- batFramework/gui/animatedLabel.py +0 -89
- batFramework/gui/clickableWidget.py +0 -244
- batFramework/gui/constraints/__init__.py +0 -1
- batFramework/gui/constraints/constraints.py +0 -980
- batFramework/gui/draggableWidget.py +0 -44
- batFramework/gui/meter.py +0 -96
- batFramework/gui/radioButton.py +0 -35
- batFramework/gui/selector.py +0 -250
- batFramework/gui/slider.py +0 -397
- batFramework/gui/style.py +0 -10
- batFramework/gui/styleManager.py +0 -54
- batFramework/gui/syncedVar.py +0 -49
- batFramework/gui/textInput.py +0 -306
- batFramework/gui/tooltip.py +0 -30
- batFramework/particle.py +0 -118
- batFramework/propertyEaser.py +0 -79
- batFramework/renderGroup.py +0 -34
- batFramework/resourceManager.py +0 -130
- batFramework/sceneLayer.py +0 -138
- batFramework/scrollingSprite.py +0 -115
- batFramework/sprite.py +0 -51
- batFramework/templates/__init__.py +0 -1
- batFramework/templates/controller.py +0 -97
- batFramework/tileset.py +0 -46
- batFramework/timeManager.py +0 -213
- batframework-1.0.9a11.dist-info/RECORD +0 -67
- {batframework-1.0.9a11.dist-info → batframework-1.0.10.dist-info}/LICENSE +0 -0
- {batframework-1.0.9a11.dist-info → batframework-1.0.10.dist-info}/WHEEL +0 -0
- {batframework-1.0.9a11.dist-info → batframework-1.0.10.dist-info}/top_level.txt +0 -0
batFramework/gui/slider.py
DELETED
@@ -1,397 +0,0 @@
|
|
1
|
-
import batFramework as bf
|
2
|
-
from .meter import BarMeter
|
3
|
-
from .button import Button
|
4
|
-
from .indicator import *
|
5
|
-
from .meter import BarMeter
|
6
|
-
from .shape import Shape
|
7
|
-
from .interactiveWidget import InteractiveWidget
|
8
|
-
|
9
|
-
class SliderHandle(Indicator, DraggableWidget):
|
10
|
-
def __init__(self):
|
11
|
-
super().__init__()
|
12
|
-
self.set_color(bf.color.CLOUD_SHADE)
|
13
|
-
self.old_key_repeat: tuple = (0, 0)
|
14
|
-
self.parent : bf.ClickableWidget = self.parent
|
15
|
-
self.set_click_mask(1)
|
16
|
-
def __str__(self) -> str:
|
17
|
-
return "SliderHandle"
|
18
|
-
|
19
|
-
def on_click_down(self, button: int) -> bool:
|
20
|
-
if not self.parent.is_enabled:
|
21
|
-
return True
|
22
|
-
res = super().on_click_down(button)
|
23
|
-
if res :
|
24
|
-
self.parent.get_focus()
|
25
|
-
return res
|
26
|
-
|
27
|
-
def on_exit(self):
|
28
|
-
before = self.is_clicked_down
|
29
|
-
super().on_exit()
|
30
|
-
self.is_clicked_down = before
|
31
|
-
|
32
|
-
def do_on_drag(
|
33
|
-
self, drag_start: tuple[float, float], drag_end: tuple[float, float]
|
34
|
-
) -> None:
|
35
|
-
if not self.parent.is_enabled:
|
36
|
-
return
|
37
|
-
super().do_on_drag(drag_start, drag_end)
|
38
|
-
m: BarMeter = self.parent.meter
|
39
|
-
r = m.get_inner_rect()
|
40
|
-
|
41
|
-
position = self.rect.centerx if self.parent.axis == bf.axis.HORIZONTAL else self.rect.centery
|
42
|
-
self.rect.clamp_ip(r)
|
43
|
-
# Adjust handle position to value
|
44
|
-
new_value = self.parent.position_to_value(position)
|
45
|
-
self.parent.set_value(new_value)
|
46
|
-
if self.parent.axis == bf.axis.HORIZONTAL:
|
47
|
-
self.rect.centerx = self.parent.value_to_position(new_value)
|
48
|
-
else:
|
49
|
-
self.rect.centery = self.parent.value_to_position(new_value)
|
50
|
-
|
51
|
-
def top_at(self, x, y):
|
52
|
-
return Widget.top_at(self, x, y)
|
53
|
-
|
54
|
-
class SliderMeter(BarMeter, InteractiveWidget):
|
55
|
-
def __str__(self) -> str:
|
56
|
-
return "SliderMeter"
|
57
|
-
|
58
|
-
def __init__(self, min_value = 0, max_value = 1, step = 0.1):
|
59
|
-
super().__init__(min_value, max_value, step)
|
60
|
-
self.set_padding(0)
|
61
|
-
|
62
|
-
def get_min_required_size(self):
|
63
|
-
size = list(super().get_min_required_size())
|
64
|
-
if self.parent.axis == bf.axis.HORIZONTAL:
|
65
|
-
size[0] = size[1]*3
|
66
|
-
else:
|
67
|
-
size[1] = size[0]*3
|
68
|
-
return self.resolve_size(size)
|
69
|
-
|
70
|
-
def on_click_down(self, button: int) -> bool:
|
71
|
-
if not self.parent.is_enabled:
|
72
|
-
return False
|
73
|
-
if button != 1:
|
74
|
-
return False
|
75
|
-
|
76
|
-
self.parent.get_focus()
|
77
|
-
pos = self.parent_layer.camera.screen_to_world(pygame.mouse.get_pos())
|
78
|
-
if self.parent.axis == bf.axis.HORIZONTAL:
|
79
|
-
pos = pos[0]
|
80
|
-
else:
|
81
|
-
pos = pos[1]
|
82
|
-
new_value = self.parent.position_to_value(pos)
|
83
|
-
self.parent.set_value(new_value)
|
84
|
-
self.do_on_click_down(button)
|
85
|
-
return True
|
86
|
-
|
87
|
-
class Slider(Button):
|
88
|
-
|
89
|
-
def __init__(self, text: str, default_value: float = 1.0) -> None:
|
90
|
-
super().__init__(text, None)
|
91
|
-
self.axis : bf.axis = bf.axis.HORIZONTAL
|
92
|
-
self.gap: float | int = 0
|
93
|
-
self.spacing: bf.spacing = bf.spacing.MANUAL
|
94
|
-
self.modified_callback : Callable[[float],Any] = None
|
95
|
-
self.meter: SliderMeter = SliderMeter()
|
96
|
-
self.handle = SliderHandle()
|
97
|
-
self.add(self.meter, self.handle)
|
98
|
-
self.meter.set_debug_color(bf.color.RED)
|
99
|
-
self.set_value(default_value, True)
|
100
|
-
|
101
|
-
def set_tooltip_text(self, text):
|
102
|
-
return super().set_tooltip_text(text)
|
103
|
-
|
104
|
-
def set_fill_color(self,color)->Self:
|
105
|
-
self.meter.content.set_color(color)
|
106
|
-
return self
|
107
|
-
|
108
|
-
def set_axis(self,axis:bf.axis)->Self:
|
109
|
-
self.axis = axis
|
110
|
-
self.meter.set_axis(axis)
|
111
|
-
self.dirty_shape = True
|
112
|
-
return self
|
113
|
-
|
114
|
-
def set_visible(self, value: bool) -> Self:
|
115
|
-
self.handle.set_visible(value)
|
116
|
-
self.meter.set_visible(value)
|
117
|
-
return super().set_visible(value)
|
118
|
-
|
119
|
-
def __str__(self) -> str:
|
120
|
-
return "Slider"
|
121
|
-
|
122
|
-
def set_gap(self, value: int | float) -> Self:
|
123
|
-
value = max(0, value)
|
124
|
-
self.gap = value
|
125
|
-
return self
|
126
|
-
|
127
|
-
def do_on_get_focus(self) -> None:
|
128
|
-
super().do_on_get_focus()
|
129
|
-
self.old_key_repeat = pygame.key.get_repeat()
|
130
|
-
pygame.key.set_repeat(200, 50)
|
131
|
-
|
132
|
-
def do_on_lose_focus(self) -> None:
|
133
|
-
super().do_on_lose_focus()
|
134
|
-
pygame.key.set_repeat(*self.old_key_repeat)
|
135
|
-
|
136
|
-
def set_spacing(self, spacing: bf.spacing) -> Self:
|
137
|
-
if spacing == self.spacing:
|
138
|
-
return self
|
139
|
-
self.spacing = spacing
|
140
|
-
self.dirty_shape = True
|
141
|
-
return self
|
142
|
-
|
143
|
-
def set_modify_callback(self, callback : Callable[[float],Any]) -> Self:
|
144
|
-
self.modified_callback = callback
|
145
|
-
return self
|
146
|
-
|
147
|
-
def set_range(self, range_min: float, range_max: float) -> Self:
|
148
|
-
self.meter.set_range(range_min, range_max)
|
149
|
-
self.dirty_shape = True
|
150
|
-
return self
|
151
|
-
|
152
|
-
def set_step(self, step: float) -> Self:
|
153
|
-
self.meter.set_step(step)
|
154
|
-
self.dirty_shape = True
|
155
|
-
return self
|
156
|
-
|
157
|
-
def set_value(self, value, no_callback: bool = False) -> Self:
|
158
|
-
if self.meter.value != value:
|
159
|
-
self.meter.set_value(value)
|
160
|
-
self.dirty_shape = True
|
161
|
-
if self.modified_callback and (not no_callback):
|
162
|
-
self.modified_callback(self.meter.value)
|
163
|
-
self.handle.set_tooltip_text(str(self.get_value()))
|
164
|
-
self.meter.set_tooltip_text(str(self.get_value()))
|
165
|
-
|
166
|
-
return self
|
167
|
-
|
168
|
-
def get_value(self) -> float:
|
169
|
-
return self.meter.get_value()
|
170
|
-
|
171
|
-
def on_key_down(self, key):
|
172
|
-
if super().on_key_down(key):
|
173
|
-
return True
|
174
|
-
if not self.is_enabled:
|
175
|
-
return False
|
176
|
-
if self.axis == bf.axis.HORIZONTAL:
|
177
|
-
if key == pygame.K_RIGHT:
|
178
|
-
self.set_value(self.meter.get_value() + self.meter.step)
|
179
|
-
elif key == pygame.K_LEFT:
|
180
|
-
self.set_value(self.meter.get_value() - self.meter.step)
|
181
|
-
else:
|
182
|
-
return False
|
183
|
-
return True
|
184
|
-
else:
|
185
|
-
if key == pygame.K_UP:
|
186
|
-
self.set_value(self.meter.get_value() + self.meter.step)
|
187
|
-
elif key == pygame.K_DOWN:
|
188
|
-
self.set_value(self.meter.get_value() - self.meter.step)
|
189
|
-
else:
|
190
|
-
return False
|
191
|
-
|
192
|
-
return True
|
193
|
-
|
194
|
-
def do_on_click_down(self, button) -> None:
|
195
|
-
if not self.is_enabled:
|
196
|
-
return
|
197
|
-
if button == 1:
|
198
|
-
self.get_focus()
|
199
|
-
|
200
|
-
def value_to_position(self, value: float) -> float:
|
201
|
-
"""
|
202
|
-
Converts a value to a position on the meter, considering the step size.
|
203
|
-
"""
|
204
|
-
rect = self.meter.get_inner_rect()
|
205
|
-
value_range = self.meter.get_range()
|
206
|
-
value = round(value / self.meter.step) * self.meter.step
|
207
|
-
position_ratio = (value - self.meter.min_value) / value_range
|
208
|
-
if self.axis == bf.axis.HORIZONTAL:
|
209
|
-
return (
|
210
|
-
rect.left
|
211
|
-
+ (self.handle.rect.w / 2)
|
212
|
-
+ position_ratio * (rect.width - self.handle.rect.w)
|
213
|
-
)
|
214
|
-
else:
|
215
|
-
return (
|
216
|
-
rect.bottom
|
217
|
-
- (self.handle.rect.h / 2)
|
218
|
-
- position_ratio * (rect.height - self.handle.rect.h)
|
219
|
-
)
|
220
|
-
|
221
|
-
def position_to_value(self, position: float) -> float:
|
222
|
-
"""
|
223
|
-
Converts a position on the meter to a value, considering the step size.
|
224
|
-
"""
|
225
|
-
rect = self.meter.get_inner_rect()
|
226
|
-
if self.axis == bf.axis.HORIZONTAL:
|
227
|
-
if self.rect.w == self.handle.rect.w:
|
228
|
-
position_ratio = 0
|
229
|
-
else:
|
230
|
-
handle_half = self.handle.rect.w // 2
|
231
|
-
position = max(rect.left + handle_half, min(position, rect.right - handle_half))
|
232
|
-
position_ratio = (position - rect.left - handle_half) / (
|
233
|
-
rect.width - self.handle.rect.w
|
234
|
-
)
|
235
|
-
else:
|
236
|
-
if self.rect.h == self.handle.rect.h:
|
237
|
-
position_ratio = 0
|
238
|
-
else:
|
239
|
-
handle_half = self.handle.rect.h // 2
|
240
|
-
position = max(rect.top + handle_half, min(position, rect.bottom - handle_half))
|
241
|
-
# Flip ratio vertically: bottom is min, top is max
|
242
|
-
position_ratio = (rect.bottom - position - handle_half) / (
|
243
|
-
rect.height - self.handle.rect.h
|
244
|
-
)
|
245
|
-
|
246
|
-
value_range = self.meter.get_range()
|
247
|
-
value = self.meter.min_value + position_ratio * value_range
|
248
|
-
return round(value / self.meter.step) * self.meter.step
|
249
|
-
|
250
|
-
def get_min_required_size(self) -> tuple[float, float]:
|
251
|
-
"""
|
252
|
-
Calculates the minimum required size for the slider, considering the text, meter, and axis.
|
253
|
-
|
254
|
-
Returns:
|
255
|
-
tuple[float, float]: The width and height of the minimum required size.
|
256
|
-
"""
|
257
|
-
gap = self.gap if self.text else 0
|
258
|
-
text_width, text_height = self._get_text_rect_required_size() if self.text else (0, 0)
|
259
|
-
meter_width, meter_height = self.meter.resolve_size(self.meter.get_min_required_size())
|
260
|
-
|
261
|
-
if self.axis == bf.axis.HORIZONTAL:
|
262
|
-
width = text_width + gap + meter_width
|
263
|
-
height = max(text_height, meter_height)
|
264
|
-
else:
|
265
|
-
width = max(text_width, meter_width)
|
266
|
-
height = text_height + gap + meter_height
|
267
|
-
|
268
|
-
height += self.unpressed_relief
|
269
|
-
return self.expand_rect_with_padding((0, 0, width, height)).size
|
270
|
-
|
271
|
-
def _build_composed_layout(self) -> None:
|
272
|
-
"""
|
273
|
-
Builds the composed layout for the slider, including the meter and handle.
|
274
|
-
This method adjusts the sizes and positions of the meter and handle based on the slider's axis,
|
275
|
-
autoresize conditions, and spacing settings. It ensures the slider's components are properly aligned
|
276
|
-
and sized within the slider's padded rectangle.
|
277
|
-
"""
|
278
|
-
self.text_rect.size = self._get_text_rect_required_size()
|
279
|
-
|
280
|
-
size_changed = False
|
281
|
-
gap = self.gap if self.text else 0
|
282
|
-
|
283
|
-
full_rect = self.text_rect.copy()
|
284
|
-
|
285
|
-
|
286
|
-
# Resolve the meter's size based on the axis and autoresize conditions
|
287
|
-
if self.axis == bf.axis.HORIZONTAL:
|
288
|
-
meter_width,meter_height = self.meter.get_min_required_size()
|
289
|
-
if not self.autoresize_w:
|
290
|
-
meter_width = self.get_inner_width() - gap - self.text_rect.w
|
291
|
-
meter_width,meter_height = self.meter.resolve_size((meter_width,meter_height))
|
292
|
-
|
293
|
-
full_rect.w = max(self.get_inner_width(), meter_width + (gap + self.text_rect.w if self.text else 0))
|
294
|
-
self.meter.set_size((meter_width, meter_height))
|
295
|
-
full_rect.h = max(meter_height, self.text_rect.h if self.text else meter_height)
|
296
|
-
|
297
|
-
else: # VERTICAL
|
298
|
-
meter_width, meter_height = self.meter.get_min_required_size()
|
299
|
-
if not self.autoresize_h:
|
300
|
-
meter_height = self.get_inner_height() - gap - self.text_rect.h
|
301
|
-
meter_width, meter_height = self.meter.resolve_size((meter_width, meter_height))
|
302
|
-
|
303
|
-
full_rect.h = meter_height + (gap + self.text_rect.h if self.text else 0)
|
304
|
-
self.meter.set_size((meter_width, meter_height))
|
305
|
-
full_rect.w = max(meter_width, self.text_rect.w if self.text else meter_width)
|
306
|
-
|
307
|
-
|
308
|
-
# Inflate the rect by padding and resolve the target size
|
309
|
-
full_rect.h += self.unpressed_relief
|
310
|
-
inflated = self.expand_rect_with_padding((0, 0, *full_rect.size)).size
|
311
|
-
|
312
|
-
target_size = self.resolve_size(inflated)
|
313
|
-
|
314
|
-
|
315
|
-
# Update the slider's size if it doesn't match the target size
|
316
|
-
if self.rect.size != target_size:
|
317
|
-
self.set_size(target_size)
|
318
|
-
size_changed = True
|
319
|
-
|
320
|
-
# Adjust the handle size based on the meter's size
|
321
|
-
if self.axis == bf.axis.HORIZONTAL:
|
322
|
-
handle_size = self.meter.get_inner_height()
|
323
|
-
self.handle.set_size(self.handle.resolve_size((handle_size, handle_size)))
|
324
|
-
else:
|
325
|
-
handle_size = self.meter.get_inner_width()
|
326
|
-
self.handle.set_size(self.handle.resolve_size((handle_size, handle_size)))
|
327
|
-
|
328
|
-
self._align_composed()
|
329
|
-
return size_changed
|
330
|
-
|
331
|
-
def _align_composed(self):
|
332
|
-
|
333
|
-
if not self.text:
|
334
|
-
self.text_rect.size = (0,0)
|
335
|
-
full_rect = self.get_local_inner_rect()
|
336
|
-
left_rect = self.text_rect
|
337
|
-
right_rect = self.meter.rect.copy()
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
if self.axis == bf.axis.HORIZONTAL:
|
342
|
-
gap = {
|
343
|
-
bf.spacing.MIN: 0,
|
344
|
-
bf.spacing.HALF: (full_rect.width - left_rect.width - right_rect.width) // 2,
|
345
|
-
bf.spacing.MAX: full_rect.width - left_rect.width - right_rect.width,
|
346
|
-
bf.spacing.MANUAL: self.gap
|
347
|
-
}.get(self.spacing, 0)
|
348
|
-
|
349
|
-
gap = max(0, gap)
|
350
|
-
combined_width = left_rect.width + right_rect.width + gap
|
351
|
-
|
352
|
-
group_x = {
|
353
|
-
bf.alignment.LEFT: full_rect.left,
|
354
|
-
bf.alignment.MIDLEFT: full_rect.left,
|
355
|
-
bf.alignment.RIGHT: full_rect.right - combined_width,
|
356
|
-
bf.alignment.MIDRIGHT: full_rect.right - combined_width,
|
357
|
-
bf.alignment.CENTER: full_rect.centerx - combined_width // 2
|
358
|
-
}.get(self.alignment, full_rect.left)
|
359
|
-
|
360
|
-
left_rect.x, right_rect.x = group_x, group_x + left_rect.width + gap
|
361
|
-
left_rect.centery = right_rect.centery = full_rect.centery
|
362
|
-
|
363
|
-
else: # VERTICAL
|
364
|
-
gap = {
|
365
|
-
bf.spacing.MIN: 0,
|
366
|
-
bf.spacing.HALF: (full_rect.height - left_rect.height - right_rect.height) // 2,
|
367
|
-
bf.spacing.MAX: full_rect.height - left_rect.height - right_rect.height,
|
368
|
-
bf.spacing.MANUAL: self.gap
|
369
|
-
}.get(self.spacing, 0)
|
370
|
-
|
371
|
-
gap = max(0, gap)
|
372
|
-
combined_height = left_rect.height + right_rect.height + gap
|
373
|
-
|
374
|
-
group_y = {
|
375
|
-
bf.alignment.TOP: full_rect.top,
|
376
|
-
bf.alignment.MIDTOP: full_rect.top,
|
377
|
-
bf.alignment.BOTTOM: full_rect.bottom - combined_height,
|
378
|
-
bf.alignment.MIDBOTTOM: full_rect.bottom - combined_height,
|
379
|
-
bf.alignment.CENTER: full_rect.centery - combined_height // 2
|
380
|
-
}.get(self.alignment, full_rect.top)
|
381
|
-
|
382
|
-
left_rect.y, right_rect.y = group_y, group_y + left_rect.height + gap
|
383
|
-
left_rect.centerx = right_rect.centerx = full_rect.centerx
|
384
|
-
|
385
|
-
# Push text to local, push shape to world
|
386
|
-
self.text_rect = left_rect
|
387
|
-
right_rect.move_ip(*self.rect.topleft)
|
388
|
-
self.meter.set_position(*right_rect.topleft)
|
389
|
-
|
390
|
-
# Position the handle based on the current value
|
391
|
-
if self.axis == bf.axis.HORIZONTAL:
|
392
|
-
self.handle.set_center(self.value_to_position(self.meter.value), self.meter.rect.centery)
|
393
|
-
else:
|
394
|
-
self.handle.set_center(self.meter.rect.centerx, self.value_to_position(self.meter.value))
|
395
|
-
|
396
|
-
def _build_layout(self) -> None:
|
397
|
-
return self._build_composed_layout()
|
batFramework/gui/style.py
DELETED
batFramework/gui/styleManager.py
DELETED
@@ -1,54 +0,0 @@
|
|
1
|
-
from ..utils import Singleton
|
2
|
-
from .widget import Widget
|
3
|
-
|
4
|
-
|
5
|
-
class Style:
|
6
|
-
def __init__(self):
|
7
|
-
pass
|
8
|
-
|
9
|
-
def apply(self, widget: Widget):
|
10
|
-
pass
|
11
|
-
|
12
|
-
|
13
|
-
class StyleManager(metaclass=Singleton):
|
14
|
-
def __init__(self):
|
15
|
-
self.styles: list[Style] = []
|
16
|
-
self.widgets: set[Widget] = set()
|
17
|
-
self.lookup: dict[Widget, bool] = {}
|
18
|
-
|
19
|
-
def register_widget(self, widget: Widget):
|
20
|
-
if widget in self.widgets:
|
21
|
-
return
|
22
|
-
self.widgets.add(widget)
|
23
|
-
self.lookup[widget] = False
|
24
|
-
self.update()
|
25
|
-
|
26
|
-
def refresh_widget(self, widget: Widget):
|
27
|
-
if widget in self.widgets:
|
28
|
-
self.lookup[widget] = False
|
29
|
-
self.update()
|
30
|
-
|
31
|
-
def remove_widget(self, widget: Widget):
|
32
|
-
if widget not in self.widgets:
|
33
|
-
return
|
34
|
-
self.widgets.remove(widget)
|
35
|
-
self.lookup.pop(widget)
|
36
|
-
|
37
|
-
def add(self, style: Style):
|
38
|
-
self.styles.append(style)
|
39
|
-
self.lookup = {key: False for key in self.lookup}
|
40
|
-
self.update()
|
41
|
-
|
42
|
-
def update_forced(self):
|
43
|
-
for widget in self.widgets:
|
44
|
-
for style in self.styles:
|
45
|
-
style.apply(widget)
|
46
|
-
self.lookup[widget] = True
|
47
|
-
|
48
|
-
def update(self):
|
49
|
-
for widget in self.widgets:
|
50
|
-
if self.lookup[widget]:
|
51
|
-
continue
|
52
|
-
for style in self.styles:
|
53
|
-
style.apply(widget)
|
54
|
-
self.lookup[widget] = True
|
batFramework/gui/syncedVar.py
DELETED
@@ -1,49 +0,0 @@
|
|
1
|
-
from .widget import Widget
|
2
|
-
from typing import Callable, Any, Self
|
3
|
-
|
4
|
-
class SyncedVar:
|
5
|
-
def __init__(self, value=None):
|
6
|
-
self._value: Any = value
|
7
|
-
self.modify_callback: Callable[[Any], Any] | None = None
|
8
|
-
self._bound_widgets: set[tuple[Widget, Callable[[Any], Any]]] = set()
|
9
|
-
|
10
|
-
def set_modify_callback(self, callback : Callable[[Any], Any]) -> Self:
|
11
|
-
self.modify_callback = callback
|
12
|
-
return self
|
13
|
-
|
14
|
-
def bind_widget(self, widget: Widget, update_callback: Callable[[Any], Any]) -> Self:
|
15
|
-
"""
|
16
|
-
Binds a widget to the SyncedVar. The widget must provide an update_callback
|
17
|
-
function that will be called whenever the value changes.
|
18
|
-
"""
|
19
|
-
self._bound_widgets.add((widget, update_callback))
|
20
|
-
self._update_widgets()
|
21
|
-
return self
|
22
|
-
|
23
|
-
def unbind_widget(self, widget: Widget)->Self:
|
24
|
-
"""
|
25
|
-
Unbinds a widget from the SyncedVar.
|
26
|
-
"""
|
27
|
-
self._bound_widgets = {
|
28
|
-
(w, cb) for w, cb in self._bound_widgets if w != widget
|
29
|
-
}
|
30
|
-
return self
|
31
|
-
|
32
|
-
@property
|
33
|
-
def value(self):
|
34
|
-
return self._value
|
35
|
-
|
36
|
-
@value.setter
|
37
|
-
def value(self, new_value):
|
38
|
-
if self._value != new_value:
|
39
|
-
self._value = new_value
|
40
|
-
self._update_widgets()
|
41
|
-
if self.modify_callback is not None:
|
42
|
-
self.modify_callback(new_value)
|
43
|
-
|
44
|
-
def _update_widgets(self):
|
45
|
-
"""
|
46
|
-
Calls the update callback for all bound widgets.
|
47
|
-
"""
|
48
|
-
for _, update_callback in self._bound_widgets:
|
49
|
-
update_callback(self._value)
|