batframework 1.0.9a11__py3-none-any.whl → 1.0.9a12__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 +2 -0
- batFramework/action.py +280 -279
- batFramework/actionContainer.py +105 -82
- batFramework/animatedSprite.py +80 -58
- batFramework/animation.py +91 -77
- batFramework/audioManager.py +156 -131
- batFramework/baseScene.py +249 -240
- batFramework/camera.py +245 -317
- batFramework/constants.py +57 -51
- batFramework/cutscene.py +239 -253
- batFramework/cutsceneManager.py +34 -34
- batFramework/drawable.py +107 -77
- batFramework/dynamicEntity.py +30 -30
- batFramework/easingController.py +58 -58
- batFramework/entity.py +130 -130
- batFramework/enums.py +171 -135
- batFramework/fontManager.py +65 -65
- batFramework/gui/__init__.py +28 -25
- batFramework/gui/animatedLabel.py +90 -89
- batFramework/gui/button.py +17 -17
- batFramework/gui/clickableWidget.py +244 -244
- batFramework/gui/collapseContainer.py +98 -0
- batFramework/gui/constraints/__init__.py +1 -1
- batFramework/gui/constraints/constraints.py +1066 -980
- batFramework/gui/container.py +220 -206
- batFramework/gui/debugger.py +140 -130
- batFramework/gui/draggableWidget.py +63 -44
- batFramework/gui/image.py +61 -58
- batFramework/gui/indicator.py +116 -113
- batFramework/gui/interactiveWidget.py +243 -239
- batFramework/gui/label.py +147 -344
- batFramework/gui/layout.py +442 -429
- batFramework/gui/meter.py +155 -96
- batFramework/gui/radioButton.py +43 -35
- batFramework/gui/root.py +228 -228
- batFramework/gui/scrollingContainer.py +282 -0
- batFramework/gui/selector.py +232 -250
- batFramework/gui/shape.py +286 -276
- batFramework/gui/slider.py +353 -397
- batFramework/gui/style.py +10 -10
- batFramework/gui/styleManager.py +49 -54
- batFramework/gui/syncedVar.py +43 -49
- batFramework/gui/textInput.py +331 -306
- batFramework/gui/textWidget.py +308 -0
- batFramework/gui/toggle.py +140 -128
- batFramework/gui/tooltip.py +35 -30
- batFramework/gui/widget.py +546 -521
- batFramework/manager.py +131 -134
- batFramework/particle.py +118 -118
- batFramework/propertyEaser.py +79 -79
- batFramework/renderGroup.py +34 -34
- batFramework/resourceManager.py +130 -130
- batFramework/scene.py +31 -31
- batFramework/sceneLayer.py +134 -138
- batFramework/sceneManager.py +200 -197
- batFramework/scrollingSprite.py +115 -115
- batFramework/sprite.py +46 -51
- batFramework/stateMachine.py +49 -54
- batFramework/templates/__init__.py +2 -1
- batFramework/templates/character.py +15 -0
- batFramework/templates/controller.py +158 -97
- batFramework/templates/stateMachine.py +39 -0
- batFramework/tileset.py +46 -46
- batFramework/timeManager.py +213 -213
- batFramework/transition.py +162 -162
- batFramework/triggerZone.py +22 -22
- batFramework/utils.py +306 -306
- {batframework-1.0.9a11.dist-info → batframework-1.0.9a12.dist-info}/LICENSE +20 -20
- {batframework-1.0.9a11.dist-info → batframework-1.0.9a12.dist-info}/METADATA +24 -17
- batframework-1.0.9a12.dist-info/RECORD +72 -0
- batframework-1.0.9a11.dist-info/RECORD +0 -67
- {batframework-1.0.9a11.dist-info → batframework-1.0.9a12.dist-info}/WHEEL +0 -0
- {batframework-1.0.9a11.dist-info → batframework-1.0.9a12.dist-info}/top_level.txt +0 -0
batFramework/gui/layout.py
CHANGED
@@ -1,429 +1,442 @@
|
|
1
|
-
import batFramework as bf
|
2
|
-
from .widget import Widget
|
3
|
-
from .constraints.constraints import *
|
4
|
-
from typing import Self, TYPE_CHECKING
|
5
|
-
from abc import ABC,abstractmethod
|
6
|
-
import pygame
|
7
|
-
from .interactiveWidget import InteractiveWidget
|
8
|
-
|
9
|
-
if TYPE_CHECKING:
|
10
|
-
from .container import Container
|
11
|
-
|
12
|
-
|
13
|
-
class Layout(ABC):
|
14
|
-
def __init__(self, parent: "Container" = None):
|
15
|
-
self.parent = parent
|
16
|
-
self.child_constraints: list[Constraint] = []
|
17
|
-
self.children_rect = pygame.FRect(0, 0, 0, 0)
|
18
|
-
|
19
|
-
def get_free_space(self)->tuple[float,float]:
|
20
|
-
"""
|
21
|
-
return the space available for Growing widgets to use
|
22
|
-
"""
|
23
|
-
return self.parent.get_inner_rect()
|
24
|
-
|
25
|
-
def set_child_constraints(self, *constraints) -> Self:
|
26
|
-
self.child_constraints = list(constraints)
|
27
|
-
self.update_child_constraints()
|
28
|
-
self.notify_parent()
|
29
|
-
return self
|
30
|
-
|
31
|
-
def set_parent(self, parent: Widget):
|
32
|
-
self.parent = parent
|
33
|
-
self.notify_parent()
|
34
|
-
|
35
|
-
def notify_parent(self) -> None:
|
36
|
-
if self.parent:
|
37
|
-
self.parent.dirty_layout = True
|
38
|
-
|
39
|
-
def update_children_rect(self):
|
40
|
-
if self.parent.get_layout_children():
|
41
|
-
self.children_rect = pygame.FRect(*self.parent.get_inner_rect().topleft,*self.parent.get_layout_children()[0].get_min_required_size())
|
42
|
-
|
43
|
-
self.children_rect.unionall(
|
44
|
-
[pygame.FRect(0,0,*c.get_min_required_size()) for c in self.parent.get_layout_children()[1:]]
|
45
|
-
)
|
46
|
-
else:
|
47
|
-
self.children_rect = pygame.FRect(*self.parent.get_inner_rect().topleft, 0, 0)
|
48
|
-
self.children_rect.move_ip(-self.parent.scroll.x,-self.parent.scroll.y)
|
49
|
-
|
50
|
-
def update_child_constraints(self):
|
51
|
-
if self.parent:
|
52
|
-
for child in self.parent.get_layout_children():
|
53
|
-
child.add_constraints(*self.child_constraints)
|
54
|
-
|
55
|
-
def arrange(self) -> None:
|
56
|
-
"""
|
57
|
-
updates the position of children in the parent
|
58
|
-
"""
|
59
|
-
return
|
60
|
-
|
61
|
-
def
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
if
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
"""
|
87
|
-
|
88
|
-
container
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
if
|
102
|
-
|
103
|
-
elif
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
def
|
144
|
-
l = self.parent.get_interactive_children()
|
145
|
-
self.parent.focused_index =
|
146
|
-
focused = l[self.parent.focused_index]
|
147
|
-
focused.get_focus()
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
def
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
self.children_rect = pygame.FRect(*self.parent.get_inner_rect().topleft,
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
self.
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
self.
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
self.parent.
|
346
|
-
|
347
|
-
|
348
|
-
def
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
def
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
if
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
if self.parent.get_layout_children():
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
self.children_rect = pygame.FRect(*self.parent.get_inner_rect().topleft,
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
self.
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
for i, child in enumerate(
|
424
|
-
row = i // self.cols
|
425
|
-
col = i % self.cols
|
426
|
-
x =
|
427
|
-
y =
|
428
|
-
child.
|
429
|
-
|
1
|
+
import batFramework as bf
|
2
|
+
from .widget import Widget
|
3
|
+
from .constraints.constraints import *
|
4
|
+
from typing import Self, TYPE_CHECKING
|
5
|
+
from abc import ABC,abstractmethod
|
6
|
+
import pygame
|
7
|
+
from .interactiveWidget import InteractiveWidget
|
8
|
+
|
9
|
+
if TYPE_CHECKING:
|
10
|
+
from .container import Container
|
11
|
+
|
12
|
+
|
13
|
+
class Layout(ABC):
|
14
|
+
def __init__(self, parent: "Container" = None):
|
15
|
+
self.parent = parent
|
16
|
+
self.child_constraints: list[Constraint] = []
|
17
|
+
self.children_rect = pygame.FRect(0, 0, 0, 0)
|
18
|
+
|
19
|
+
def get_free_space(self)->tuple[float,float]:
|
20
|
+
"""
|
21
|
+
return the space available for Growing widgets to use
|
22
|
+
"""
|
23
|
+
return self.parent.get_inner_rect()
|
24
|
+
|
25
|
+
def set_child_constraints(self, *constraints) -> Self:
|
26
|
+
self.child_constraints = list(constraints)
|
27
|
+
self.update_child_constraints()
|
28
|
+
self.notify_parent()
|
29
|
+
return self
|
30
|
+
|
31
|
+
def set_parent(self, parent: Widget):
|
32
|
+
self.parent = parent
|
33
|
+
self.notify_parent()
|
34
|
+
|
35
|
+
def notify_parent(self) -> None:
|
36
|
+
if self.parent:
|
37
|
+
self.parent.dirty_layout = True
|
38
|
+
|
39
|
+
def update_children_rect(self):
|
40
|
+
if self.parent.get_layout_children():
|
41
|
+
self.children_rect = pygame.FRect(*self.parent.get_inner_rect().topleft,*self.parent.get_layout_children()[0].get_min_required_size())
|
42
|
+
|
43
|
+
self.children_rect.unionall(
|
44
|
+
[pygame.FRect(0,0,*c.get_min_required_size()) for c in self.parent.get_layout_children()[1:]]
|
45
|
+
)
|
46
|
+
else:
|
47
|
+
self.children_rect = pygame.FRect(*self.parent.get_inner_rect().topleft, 0, 0)
|
48
|
+
self.children_rect.move_ip(-self.parent.scroll.x,-self.parent.scroll.y)
|
49
|
+
|
50
|
+
def update_child_constraints(self):
|
51
|
+
if self.parent:
|
52
|
+
for child in self.parent.get_layout_children():
|
53
|
+
child.add_constraints(*self.child_constraints)
|
54
|
+
|
55
|
+
def arrange(self) -> None:
|
56
|
+
"""
|
57
|
+
updates the position of children in the parent
|
58
|
+
"""
|
59
|
+
return
|
60
|
+
|
61
|
+
def scroll_children(self)->None:
|
62
|
+
return
|
63
|
+
|
64
|
+
def get_raw_size(self):
|
65
|
+
"""
|
66
|
+
Returns the size the container should have to encapsulate perfectly all of its widgets
|
67
|
+
"""
|
68
|
+
# print(self,self.parent,len(self.parent.get_layout_children()))
|
69
|
+
self.update_children_rect() # TODO: find a way to call this fewer times
|
70
|
+
return self.children_rect.size
|
71
|
+
|
72
|
+
def get_auto_size(self) -> tuple[float, float]:
|
73
|
+
"""
|
74
|
+
Returns the final size the container should have (while keeping the width and height if they are non-resizable)
|
75
|
+
"""
|
76
|
+
target_size = list(self.get_raw_size())
|
77
|
+
if not self.parent.autoresize_w:
|
78
|
+
target_size[0] = self.parent.get_inner_width()
|
79
|
+
if not self.parent.autoresize_h:
|
80
|
+
target_size[1] = self.parent.get_inner_height()
|
81
|
+
|
82
|
+
return self.parent.expand_rect_with_padding((0,0,*target_size)).size
|
83
|
+
# return target_size
|
84
|
+
|
85
|
+
def scroll_to_widget(self, widget: "Widget"):
|
86
|
+
"""
|
87
|
+
Scrolls parent container so that the widget becomes visible.
|
88
|
+
If the widget is bigger than the container, aligns top/left.
|
89
|
+
"""
|
90
|
+
inner = self.parent.get_inner_rect()
|
91
|
+
|
92
|
+
if self.parent.clip_children and not inner.contains(widget.rect):
|
93
|
+
scroll = pygame.Vector2(0, 0)
|
94
|
+
|
95
|
+
# Horizontal
|
96
|
+
if widget.rect.w > inner.w:
|
97
|
+
# Widget is too wide: just align left
|
98
|
+
if widget.rect.left < inner.left:
|
99
|
+
scroll.x = inner.left - widget.rect.left
|
100
|
+
else:
|
101
|
+
if widget.rect.left < inner.left:
|
102
|
+
scroll.x = inner.left - widget.rect.left
|
103
|
+
elif widget.rect.right > inner.right:
|
104
|
+
scroll.x = inner.right - widget.rect.right
|
105
|
+
|
106
|
+
# Vertical
|
107
|
+
if widget.rect.h > inner.h:
|
108
|
+
# Widget is too tall: just align top
|
109
|
+
if widget.rect.top < inner.top:
|
110
|
+
scroll.y = inner.top - widget.rect.top
|
111
|
+
else:
|
112
|
+
if widget.rect.top < inner.top:
|
113
|
+
scroll.y = inner.top - widget.rect.top
|
114
|
+
elif widget.rect.bottom > inner.bottom:
|
115
|
+
scroll.y = inner.bottom - widget.rect.bottom
|
116
|
+
|
117
|
+
# Apply
|
118
|
+
self.parent.scroll_by(-scroll)
|
119
|
+
|
120
|
+
# stop at root
|
121
|
+
if self.parent.is_root:
|
122
|
+
return
|
123
|
+
|
124
|
+
# recurse upwards if parent has a layout
|
125
|
+
if hasattr(self.parent.parent, "layout"):
|
126
|
+
self.parent.parent.layout.scroll_to_widget(widget)
|
127
|
+
def handle_event(self, event):
|
128
|
+
pass
|
129
|
+
|
130
|
+
class FreeLayout(Layout):...
|
131
|
+
|
132
|
+
class SingleAxisLayout(Layout):
|
133
|
+
|
134
|
+
def __init__(self, parent = None):
|
135
|
+
super().__init__(parent)
|
136
|
+
|
137
|
+
def focus_next_child(self) -> None:
|
138
|
+
l = self.parent.get_interactive_children()
|
139
|
+
self.parent.focused_index = min(self.parent.focused_index + 1, len(l) - 1)
|
140
|
+
focused = l[self.parent.focused_index]
|
141
|
+
focused.get_focus()
|
142
|
+
|
143
|
+
def focus_prev_child(self) -> None:
|
144
|
+
l = self.parent.get_interactive_children()
|
145
|
+
self.parent.focused_index = max(self.parent.focused_index - 1, 0)
|
146
|
+
focused = l[self.parent.focused_index]
|
147
|
+
focused.get_focus()
|
148
|
+
|
149
|
+
class DoubleAxisLayout(Layout):
|
150
|
+
"""Abstract layout class for layouts that arrange widgets in two dimensions."""
|
151
|
+
|
152
|
+
def focus_up_child(self) -> None:...
|
153
|
+
def focus_down_child(self) -> None:...
|
154
|
+
def focus_right_child(self) -> None:...
|
155
|
+
def focus_left_child(self) -> None:...
|
156
|
+
|
157
|
+
class Column(SingleAxisLayout):
|
158
|
+
def __init__(self, gap: int = 0):
|
159
|
+
super().__init__()
|
160
|
+
self.gap = gap
|
161
|
+
|
162
|
+
def handle_event(self, event):
|
163
|
+
if not self.parent.get_layout_children() or not self.parent.children_has_focus():
|
164
|
+
return
|
165
|
+
|
166
|
+
if event.type == pygame.KEYDOWN:
|
167
|
+
if event.key in (pygame.K_DOWN, pygame.K_UP):
|
168
|
+
self.focus_next_child() if event.key == pygame.K_DOWN else self.focus_prev_child()
|
169
|
+
event.consumed = True
|
170
|
+
|
171
|
+
def update_children_rect(self):
|
172
|
+
print("Update children rect")
|
173
|
+
layout_children = self.parent.get_layout_children()
|
174
|
+
if layout_children:
|
175
|
+
width = max(child.get_min_required_size()[0] if child.autoresize_h else child.rect.w for child in layout_children )
|
176
|
+
height = sum(child.get_min_required_size()[1]if child.autoresize_w else child.rect.h for child in layout_children) + self.gap * (len(layout_children) - 1)
|
177
|
+
self.children_rect = pygame.FRect(*self.parent.get_inner_rect().topleft, width, height)
|
178
|
+
else:
|
179
|
+
self.children_rect = pygame.FRect(*self.parent.get_inner_rect().topleft, 10, 10)
|
180
|
+
self.children_rect.move_ip(-self.parent.scroll.x,-self.parent.scroll.y)
|
181
|
+
|
182
|
+
def scroll_children(self):
|
183
|
+
topleft = list(self.parent.get_inner_rect().topleft)
|
184
|
+
topleft[0] -= round(self.parent.scroll.x)
|
185
|
+
topleft[1] -= round(self.parent.scroll.y)
|
186
|
+
layout_children = self.parent.get_layout_children()
|
187
|
+
for child in layout_children:
|
188
|
+
child.set_position(*topleft)
|
189
|
+
topleft[1] += child.rect.height + self.gap
|
190
|
+
|
191
|
+
def arrange(self) -> None:
|
192
|
+
self.update_children_rect()
|
193
|
+
self.scroll_children()
|
194
|
+
|
195
|
+
class Row(SingleAxisLayout):
|
196
|
+
def __init__(self, gap: int = 0):
|
197
|
+
super().__init__()
|
198
|
+
self.gap = gap
|
199
|
+
|
200
|
+
def handle_event(self, event):
|
201
|
+
if not self.parent.get_layout_children() or not self.parent.children_has_focus():
|
202
|
+
return
|
203
|
+
|
204
|
+
if event.type == pygame.KEYDOWN:
|
205
|
+
if event.key in (pygame.K_RIGHT, pygame.K_LEFT):
|
206
|
+
self.focus_next_child() if event.key == pygame.K_RIGHT else self.focus_prev_child()
|
207
|
+
event.consumed = True
|
208
|
+
|
209
|
+
def update_children_rect(self):
|
210
|
+
layout_children = self.parent.get_layout_children()
|
211
|
+
if layout_children:
|
212
|
+
width = sum(child.get_min_required_size()[0] if child.autoresize_w else child.rect.w for child in layout_children ) + self.gap * (len(layout_children) - 1)
|
213
|
+
height = max(child.get_min_required_size()[1] if child.autoresize_h else child.rect.h for child in layout_children )
|
214
|
+
self.children_rect = pygame.FRect(*self.parent.get_inner_rect().topleft, width, height)
|
215
|
+
else:
|
216
|
+
self.children_rect = pygame.FRect(*self.parent.get_inner_rect().topleft, 10,10)
|
217
|
+
self.children_rect.move_ip(-self.parent.scroll.x,-self.parent.scroll.y)
|
218
|
+
|
219
|
+
def scroll_children(self):
|
220
|
+
topleft = list(self.parent.get_inner_rect().topleft)
|
221
|
+
topleft[0] -= round(self.parent.scroll.x)
|
222
|
+
topleft[1] -= round(self.parent.scroll.y)
|
223
|
+
layout_children = self.parent.get_layout_children()
|
224
|
+
for child in layout_children:
|
225
|
+
child.set_position(*topleft)
|
226
|
+
topleft[0] += child.rect.width + self.gap
|
227
|
+
|
228
|
+
def arrange(self) -> None:
|
229
|
+
self.update_children_rect()
|
230
|
+
self.scroll_children()
|
231
|
+
|
232
|
+
class Grid(DoubleAxisLayout):
|
233
|
+
def __init__(self, rows: int, cols: int, gap: int = 0):
|
234
|
+
super().__init__()
|
235
|
+
self.rows = rows
|
236
|
+
self.cols = cols
|
237
|
+
self.gap = gap
|
238
|
+
|
239
|
+
def focus_up_child(self) -> None:
|
240
|
+
l = self.parent.get_interactive_children()
|
241
|
+
if not l:
|
242
|
+
return
|
243
|
+
current_index = self.parent.focused_index
|
244
|
+
if current_index == -1:
|
245
|
+
return
|
246
|
+
current_row = current_index // self.cols
|
247
|
+
target_index = max(0, current_index - self.cols)
|
248
|
+
if target_index // self.cols < current_row:
|
249
|
+
self.parent.focused_index = target_index
|
250
|
+
l[target_index].get_focus()
|
251
|
+
|
252
|
+
def focus_down_child(self) -> None:
|
253
|
+
l = self.parent.get_interactive_children()
|
254
|
+
if not l:
|
255
|
+
return
|
256
|
+
current_index = self.parent.focused_index
|
257
|
+
if current_index == -1:
|
258
|
+
return
|
259
|
+
current_row = current_index // self.cols
|
260
|
+
target_index = min(len(l) - 1, current_index + self.cols)
|
261
|
+
if target_index // self.cols > current_row:
|
262
|
+
self.parent.focused_index = target_index
|
263
|
+
l[target_index].get_focus()
|
264
|
+
|
265
|
+
def focus_left_child(self) -> None:
|
266
|
+
l = self.parent.get_interactive_children()
|
267
|
+
if not l:
|
268
|
+
return
|
269
|
+
current_index = self.parent.focused_index
|
270
|
+
if current_index == -1:
|
271
|
+
return
|
272
|
+
target_index = max(0, current_index - 1)
|
273
|
+
if target_index // self.cols == current_index // self.cols:
|
274
|
+
self.parent.focused_index = target_index
|
275
|
+
l[target_index].get_focus()
|
276
|
+
|
277
|
+
def focus_right_child(self) -> None:
|
278
|
+
l = self.parent.get_interactive_children()
|
279
|
+
if not l:
|
280
|
+
return
|
281
|
+
current_index = self.parent.focused_index
|
282
|
+
if current_index == -1:
|
283
|
+
return
|
284
|
+
target_index = min(len(l) - 1, current_index + 1)
|
285
|
+
if target_index // self.cols == current_index // self.cols:
|
286
|
+
self.parent.focused_index = target_index
|
287
|
+
l[target_index].get_focus()
|
288
|
+
|
289
|
+
def handle_event(self, event):
|
290
|
+
if not self.parent.get_layout_children() or not self.parent.children_has_focus():
|
291
|
+
return
|
292
|
+
|
293
|
+
if event.type == pygame.KEYDOWN:
|
294
|
+
if event.key in (pygame.K_RIGHT, pygame.K_LEFT, pygame.K_UP, pygame.K_DOWN):
|
295
|
+
if event.key == pygame.K_RIGHT:
|
296
|
+
self.focus_right_child()
|
297
|
+
elif event.key == pygame.K_LEFT:
|
298
|
+
self.focus_left_child()
|
299
|
+
elif event.key == pygame.K_UP:
|
300
|
+
self.focus_up_child()
|
301
|
+
elif event.key == pygame.K_DOWN:
|
302
|
+
self.focus_down_child()
|
303
|
+
|
304
|
+
event.consumed = True
|
305
|
+
|
306
|
+
def update_children_rect(self):
|
307
|
+
layout_children = self.parent.get_layout_children()
|
308
|
+
if layout_children:
|
309
|
+
cell_width = max(child.get_min_required_size()[0] for child in layout_children)
|
310
|
+
cell_height = max(child.get_min_required_size()[1] for child in layout_children)
|
311
|
+
width = self.cols * cell_width + self.gap * (self.cols - 1)
|
312
|
+
height = self.rows * cell_height + self.gap * (self.rows - 1)
|
313
|
+
self.children_rect = pygame.FRect(*self.parent.get_inner_rect().topleft, width, height)
|
314
|
+
else:
|
315
|
+
self.children_rect = pygame.FRect(*self.parent.get_inner_rect().topleft, 10, 10)
|
316
|
+
self.children_rect.move_ip(-self.parent.scroll.x, -self.parent.scroll.y)
|
317
|
+
|
318
|
+
def scroll_children(self):
|
319
|
+
topleft = list(self.parent.get_inner_rect().topleft)
|
320
|
+
topleft[0] -= round(self.parent.scroll.x)
|
321
|
+
topleft[1] -= round(self.parent.scroll.y)
|
322
|
+
layout_children = self.parent.get_layout_children()
|
323
|
+
cell_width = (self.children_rect.width - self.gap * (self.cols - 1)) / self.cols if self.cols else 0
|
324
|
+
cell_height = (self.children_rect.height - self.gap * (self.rows - 1)) / self.rows if self.rows else 0
|
325
|
+
for i, child in enumerate(layout_children):
|
326
|
+
row = i // self.cols
|
327
|
+
col = i % self.cols
|
328
|
+
x = topleft[0] + col * (cell_width + self.gap)
|
329
|
+
y = topleft[1] + row * (cell_height + self.gap)
|
330
|
+
child.set_position(x, y)
|
331
|
+
|
332
|
+
def arrange(self) -> None:
|
333
|
+
self.update_children_rect()
|
334
|
+
self.scroll_children()
|
335
|
+
|
336
|
+
class RowFill(Row):
|
337
|
+
|
338
|
+
def update_children_rect(self):
|
339
|
+
parent_width = self.parent.get_inner_width()
|
340
|
+
if self.parent.get_layout_children():
|
341
|
+
height = max(child.get_min_required_size()[1] for child in self.parent.get_layout_children())
|
342
|
+
width = parent_width
|
343
|
+
self.children_rect = pygame.FRect(*self.parent.get_inner_rect().topleft, width, height)
|
344
|
+
else:
|
345
|
+
self.children_rect = pygame.FRect(*self.parent.get_inner_rect().topleft, parent_width,10)
|
346
|
+
self.children_rect.move_ip(-self.parent.scroll.x,-self.parent.scroll.y)
|
347
|
+
|
348
|
+
def scroll_children(self):
|
349
|
+
topleft = list(self.parent.get_inner_rect().topleft)
|
350
|
+
topleft[0] -= round(self.parent.scroll.x)
|
351
|
+
topleft[1] -= round(self.parent.scroll.y)
|
352
|
+
layout_children = self.parent.get_layout_children()
|
353
|
+
total_gap = self.gap * (len(layout_children) - 1)
|
354
|
+
available_width = max(0, self.children_rect.width - total_gap)
|
355
|
+
child_width = available_width / len(layout_children) if layout_children else 0
|
356
|
+
for child in layout_children:
|
357
|
+
child.set_position(*topleft)
|
358
|
+
topleft[0] += child_width + self.gap
|
359
|
+
|
360
|
+
def resize_children(self):
|
361
|
+
layout_children = self.parent.get_layout_children()
|
362
|
+
total_gap = self.gap * (len(layout_children) - 1)
|
363
|
+
available_width = max(0, self.children_rect.width - total_gap)
|
364
|
+
child_width = available_width / len(layout_children) if layout_children else 0
|
365
|
+
for child in layout_children:
|
366
|
+
child.set_autoresize_w(False)
|
367
|
+
child.set_size((child_width, None))
|
368
|
+
|
369
|
+
def arrange(self) -> None:
|
370
|
+
self.update_children_rect()
|
371
|
+
self.resize_children()
|
372
|
+
self.scroll_children()
|
373
|
+
|
374
|
+
class ColumnFill(Column):
|
375
|
+
|
376
|
+
def update_children_rect(self):
|
377
|
+
parent_height = self.parent.get_inner_height()
|
378
|
+
if self.parent.get_layout_children():
|
379
|
+
width = max(child.get_min_required_size()[0] for child in self.parent.get_layout_children())
|
380
|
+
height = parent_height
|
381
|
+
self.children_rect = pygame.FRect(*self.parent.get_inner_rect().topleft, width, height)
|
382
|
+
else:
|
383
|
+
self.children_rect = pygame.FRect(*self.parent.get_inner_rect().topleft, 10, parent_height)
|
384
|
+
self.children_rect.move_ip(-self.parent.scroll.x, -self.parent.scroll.y)
|
385
|
+
|
386
|
+
def scroll_children(self):
|
387
|
+
topleft = list(self.parent.get_inner_rect().topleft)
|
388
|
+
topleft[0] -= round(self.parent.scroll.x)
|
389
|
+
topleft[1] -= round(self.parent.scroll.y)
|
390
|
+
layout_children = self.parent.get_layout_children()
|
391
|
+
total_gap = self.gap * (len(layout_children) - 1)
|
392
|
+
available_height = max(0, self.children_rect.height - total_gap)
|
393
|
+
child_height = available_height / len(layout_children) if layout_children else 0
|
394
|
+
for child in layout_children:
|
395
|
+
child.set_position(*topleft)
|
396
|
+
topleft[1] += child_height + self.gap
|
397
|
+
|
398
|
+
def resize_children(self):
|
399
|
+
layout_children = self.parent.get_layout_children()
|
400
|
+
total_gap = self.gap * (len(layout_children) - 1)
|
401
|
+
available_height = max(0, self.children_rect.height - total_gap)
|
402
|
+
child_height = available_height / len(layout_children) if layout_children else 0
|
403
|
+
for child in layout_children:
|
404
|
+
child.set_autoresize_h(False)
|
405
|
+
child.set_size((None, child_height))
|
406
|
+
|
407
|
+
def arrange(self) -> None:
|
408
|
+
self.update_children_rect()
|
409
|
+
self.resize_children()
|
410
|
+
self.scroll_children()
|
411
|
+
|
412
|
+
class GridFill(Grid):
|
413
|
+
def update_children_rect(self):
|
414
|
+
self.children_rect = self.parent.get_inner_rect()
|
415
|
+
|
416
|
+
def scroll_children(self):
|
417
|
+
topleft = list(self.parent.get_inner_rect().topleft)
|
418
|
+
topleft[0] -= round(self.parent.scroll.x)
|
419
|
+
topleft[1] -= round(self.parent.scroll.y)
|
420
|
+
layout_children = self.parent.get_layout_children()
|
421
|
+
cell_width = (self.children_rect.width - self.gap * (self.cols - 1)) / self.cols if self.cols else 0
|
422
|
+
cell_height = (self.children_rect.height - self.gap * (self.rows - 1)) / self.rows if self.rows else 0
|
423
|
+
for i, child in enumerate(layout_children):
|
424
|
+
row = i // self.cols
|
425
|
+
col = i % self.cols
|
426
|
+
x = round(topleft[0] + col * (cell_width + self.gap))
|
427
|
+
y = round(topleft[1] + row * (cell_height + self.gap))
|
428
|
+
child.set_position(x, y)
|
429
|
+
|
430
|
+
def resize_children(self):
|
431
|
+
layout_children = self.parent.get_layout_children()
|
432
|
+
cell_width = (self.children_rect.width - self.gap * (self.cols - 1)) / self.cols if self.cols else 0
|
433
|
+
cell_height = (self.children_rect.height - self.gap * (self.rows - 1)) / self.rows if self.rows else 0
|
434
|
+
for child in layout_children:
|
435
|
+
child.set_autoresize(False)
|
436
|
+
child.set_size((cell_width, cell_height))
|
437
|
+
|
438
|
+
def arrange(self) -> None:
|
439
|
+
print("arrange grid fill")
|
440
|
+
self.update_children_rect()
|
441
|
+
self.resize_children()
|
442
|
+
self.scroll_children()
|