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/layout.py
CHANGED
@@ -1,429 +1,81 @@
|
|
1
1
|
import batFramework as bf
|
2
2
|
from .widget import Widget
|
3
|
-
from .constraints
|
4
|
-
from typing import Self
|
5
|
-
from abc import ABC,abstractmethod
|
6
|
-
import pygame
|
7
|
-
from .interactiveWidget import InteractiveWidget
|
3
|
+
from .constraints import *
|
4
|
+
from typing import Self
|
8
5
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
class Layout(ABC):
|
14
|
-
def __init__(self, parent: "Container" = None):
|
6
|
+
class Layout:
|
7
|
+
def __init__(self, parent: Widget=None):
|
15
8
|
self.parent = parent
|
16
|
-
self.child_constraints: list[Constraint] = []
|
17
|
-
|
18
|
-
|
19
|
-
|
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()
|
9
|
+
self.child_constraints : list[Constraint] = []
|
10
|
+
|
11
|
+
def set_child_constraints(self,*constraints)->Self:
|
12
|
+
self.child_constraints = constraints
|
13
|
+
self.arrange()
|
29
14
|
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 get_raw_size(self):
|
62
|
-
"""
|
63
|
-
Returns the size the container should have to encapsulate perfectly all of its widgets
|
64
|
-
"""
|
65
|
-
# print(self,self.parent,len(self.parent.get_layout_children()))
|
66
|
-
self.update_children_rect()
|
67
|
-
return self.children_rect.size
|
68
|
-
|
69
|
-
def get_auto_size(self) -> tuple[float, float]:
|
70
|
-
"""
|
71
|
-
Returns the final size the container should have (while keeping the width and height if they are non-resizable)
|
72
|
-
"""
|
73
|
-
target_size = list(self.get_raw_size())
|
74
|
-
if not self.parent.autoresize_w:
|
75
|
-
target_size[0] = self.parent.get_inner_width()
|
76
|
-
if not self.parent.autoresize_h:
|
77
|
-
target_size[1] = self.parent.get_inner_height()
|
78
15
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
def scroll_to_widget(self, widget: "Widget"):
|
83
|
-
"""
|
84
|
-
Scrolls parent containers so that the widget becomes visible.
|
85
|
-
Handles deeply nested widgets and large widgets gracefully.
|
86
|
-
"""
|
87
|
-
target = widget
|
88
|
-
container = self.parent
|
89
|
-
|
90
|
-
while container and not container.is_root:
|
91
|
-
if not hasattr(container,"scroll"):
|
92
|
-
container = container.parent
|
93
|
-
continue
|
94
|
-
target_rect = target.rect # global
|
95
|
-
padded_rect = container.get_inner_rect() # global
|
96
|
-
|
97
|
-
dx = dy = 0
|
98
|
-
|
99
|
-
# --- Horizontal ---
|
100
|
-
if target_rect.width <= padded_rect.width:
|
101
|
-
if target_rect.left < padded_rect.left:
|
102
|
-
dx = target_rect.left - padded_rect.left
|
103
|
-
elif target_rect.right > padded_rect.right:
|
104
|
-
dx = target_rect.right - padded_rect.right
|
105
|
-
else:
|
106
|
-
# Widget is wider than viewport: align left side
|
107
|
-
if target_rect.left < padded_rect.left:
|
108
|
-
dx = target_rect.left - padded_rect.left
|
109
|
-
elif target_rect.right > padded_rect.right:
|
110
|
-
dx = target_rect.right - padded_rect.right
|
111
|
-
|
112
|
-
# --- Vertical ---
|
113
|
-
if target_rect.height <= padded_rect.height:
|
114
|
-
if target_rect.top < padded_rect.top:
|
115
|
-
dy = target_rect.top - padded_rect.top
|
116
|
-
elif target_rect.bottom > padded_rect.bottom:
|
117
|
-
dy = target_rect.bottom - padded_rect.bottom
|
118
|
-
else:
|
119
|
-
# Widget is taller than viewport: align top side
|
120
|
-
if target_rect.top < padded_rect.top:
|
121
|
-
dy = target_rect.top - padded_rect.top
|
122
|
-
elif target_rect.bottom > padded_rect.bottom:
|
123
|
-
dy = target_rect.bottom - padded_rect.bottom
|
124
|
-
|
125
|
-
# Convert global delta into local scroll delta for container
|
126
|
-
container.scroll_by((dx, dy))
|
127
|
-
|
128
|
-
# Now the target for the next iteration is the container itself
|
129
|
-
target = container
|
130
|
-
container = container.parent
|
131
|
-
|
132
|
-
|
133
|
-
def handle_event(self, event):
|
134
|
-
pass
|
135
|
-
|
136
|
-
class FreeLayout(Layout):...
|
137
|
-
|
138
|
-
class SingleAxisLayout(Layout):
|
139
|
-
|
140
|
-
def __init__(self, parent = None):
|
141
|
-
super().__init__(parent)
|
142
|
-
|
143
|
-
def focus_next_child(self) -> None:
|
144
|
-
l = self.parent.get_interactive_children()
|
145
|
-
self.parent.focused_index = min(self.parent.focused_index + 1, len(l) - 1)
|
146
|
-
focused = l[self.parent.focused_index]
|
147
|
-
focused.get_focus()
|
148
|
-
|
149
|
-
def focus_prev_child(self) -> None:
|
150
|
-
l = self.parent.get_interactive_children()
|
151
|
-
self.parent.focused_index = max(self.parent.focused_index - 1, 0)
|
152
|
-
focused = l[self.parent.focused_index]
|
153
|
-
focused.get_focus()
|
154
|
-
|
155
|
-
|
156
|
-
class DoubleAxisLayout(Layout):
|
157
|
-
"""Abstract layout class for layouts that arrange widgets in two dimensions."""
|
158
|
-
|
159
|
-
def focus_up_child(self) -> None:...
|
160
|
-
def focus_down_child(self) -> None:...
|
161
|
-
def focus_right_child(self) -> None:...
|
162
|
-
def focus_left_child(self) -> None:...
|
163
|
-
|
164
|
-
|
165
|
-
class Column(SingleAxisLayout):
|
166
|
-
def __init__(self, gap: int = 0):
|
167
|
-
super().__init__()
|
168
|
-
self.gap = gap
|
169
|
-
|
170
|
-
def update_children_rect(self):
|
171
|
-
if self.parent.get_layout_children():
|
172
|
-
width = max(child.get_min_required_size()[0] for child in self.parent.get_layout_children() )
|
173
|
-
height = sum(child.get_min_required_size()[1] for child in self.parent.get_layout_children()) + self.gap * (len(self.parent.get_layout_children()) - 1)
|
174
|
-
|
175
|
-
# width = max(child.rect.w for child in self.parent.get_layout_children() )
|
176
|
-
# height = sum(child.rect.h for child in self.parent.get_layout_children()) + self.gap * (len(self.parent.get_layout_children()) - 1)
|
177
|
-
|
178
|
-
|
179
|
-
self.children_rect = pygame.FRect(*self.parent.get_inner_rect().topleft, width, height)
|
180
|
-
else:
|
181
|
-
self.children_rect = pygame.FRect(*self.parent.get_inner_rect().topleft, 10, 10)
|
182
|
-
self.children_rect.move_ip(-self.parent.scroll.x,-self.parent.scroll.y)
|
183
|
-
|
184
|
-
def handle_event(self, event):
|
185
|
-
if not self.parent.get_layout_children() or not self.parent.children_has_focus():
|
186
|
-
return
|
187
|
-
|
188
|
-
if event.type == pygame.KEYDOWN:
|
189
|
-
if event.key in (pygame.K_DOWN, pygame.K_UP):
|
190
|
-
self.focus_next_child() if event.key == pygame.K_DOWN else self.focus_prev_child()
|
191
|
-
event.consumed = True
|
192
|
-
event.consumed = True
|
193
|
-
|
16
|
+
def set_parent(self,parent:Widget):
|
17
|
+
self.parent = parent
|
18
|
+
self.arrange()
|
194
19
|
|
195
|
-
def arrange(self)
|
196
|
-
|
197
|
-
y = self.children_rect.y
|
198
|
-
for child in self.parent.get_layout_children():
|
199
|
-
child.set_position(self.children_rect.x, y)
|
200
|
-
y += child.rect.height + self.gap
|
20
|
+
def arrange(self)->None:
|
21
|
+
raise NotImplementedError("Subclasses must implement arrange method")
|
201
22
|
|
202
|
-
class
|
203
|
-
def __init__(self,
|
23
|
+
class Column(Layout):
|
24
|
+
def __init__(self,gap:int=0,shrink:bool=False):
|
204
25
|
super().__init__()
|
205
26
|
self.gap = gap
|
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
|
-
class RowFill(Row):
|
236
|
-
|
237
|
-
def update_children_rect(self):
|
238
|
-
parent_width = self.parent.get_inner_width()
|
239
|
-
if self.parent.get_layout_children():
|
240
|
-
height = max(child.get_min_required_size()[1] for child in self.parent.get_layout_children())
|
241
|
-
width = parent_width
|
242
|
-
self.children_rect = pygame.FRect(*self.parent.get_inner_rect().topleft, width, height)
|
243
|
-
else:
|
244
|
-
self.children_rect = pygame.FRect(*self.parent.get_inner_rect().topleft, parent_width,10)
|
245
|
-
self.children_rect.move_ip(-self.parent.scroll.x,-self.parent.scroll.y)
|
246
|
-
|
247
|
-
|
248
|
-
def arrange(self) -> None:
|
249
|
-
"""
|
250
|
-
Arranges children in a row and resizes them to fill the parent's height,
|
251
|
-
accounting for the gap between children.
|
252
|
-
"""
|
253
|
-
self.update_children_rect()
|
254
|
-
for child in self.parent.get_layout_children():
|
255
|
-
child.set_autoresize_w(False)
|
256
|
-
x = self.children_rect.x
|
257
|
-
# available_height = self.children_rect.height
|
258
|
-
|
259
|
-
# Calculate the width available for each child
|
260
|
-
total_gap = self.gap * (len(self.parent.get_layout_children()) - 1)
|
261
|
-
available_width = max(0, self.children_rect.width - total_gap)
|
262
|
-
child_width = available_width / len(self.parent.get_layout_children()) if self.parent.get_layout_children() else 0
|
263
|
-
|
264
|
-
for child in self.parent.get_layout_children():
|
265
|
-
child.set_size((child_width, None)) # Resize child to fill height
|
266
|
-
child.set_position(x, self.children_rect.y) # Position child
|
267
|
-
x += child_width + self.gap
|
268
|
-
|
269
|
-
|
270
|
-
class ColumnFill(Column):
|
271
|
-
|
272
|
-
def update_children_rect(self):
|
273
|
-
parent_height = self.parent.get_inner_height()
|
274
|
-
if self.parent.get_layout_children():
|
275
|
-
width = max(child.get_min_required_size()[0] for child in self.parent.get_layout_children())
|
276
|
-
height = parent_height
|
277
|
-
self.children_rect = pygame.FRect(*self.parent.get_inner_rect().topleft, width, height)
|
278
|
-
else:
|
279
|
-
self.children_rect = pygame.FRect(*self.parent.get_inner_rect().topleft, 10, parent_height)
|
280
|
-
self.children_rect.move_ip(-self.parent.scroll.x, -self.parent.scroll.y)
|
281
|
-
|
282
|
-
def arrange(self) -> None:
|
283
|
-
"""
|
284
|
-
Arranges children in a column and resizes them to fill the parent's width,
|
285
|
-
accounting for the gap between children.
|
286
|
-
"""
|
287
|
-
self.update_children_rect()
|
288
|
-
for child in self.parent.get_layout_children():
|
289
|
-
child.set_autoresize_h(False)
|
290
|
-
y = self.children_rect.y
|
291
|
-
|
292
|
-
# Calculate the height available for each child
|
293
|
-
total_gap = self.gap * (len(self.parent.get_layout_children()) - 1)
|
294
|
-
available_height = max(0, self.children_rect.height - total_gap)
|
295
|
-
child_height = available_height / len(self.parent.get_layout_children()) if self.parent.get_layout_children() else 0
|
296
|
-
|
297
|
-
for child in self.parent.get_layout_children():
|
298
|
-
child.set_size((None, child_height)) # Resize child to fill width
|
299
|
-
child.set_position(self.children_rect.x, y) # Position child
|
300
|
-
y += child_height + self.gap
|
301
|
-
|
302
|
-
|
303
|
-
class Grid(DoubleAxisLayout):
|
304
|
-
def __init__(self, rows: int, cols: int, gap: int = 0):
|
27
|
+
self.shrink :bool = shrink
|
28
|
+
|
29
|
+
def arrange(self)->None:
|
30
|
+
if not self.parent or not self.parent.children : return
|
31
|
+
if self.shrink:
|
32
|
+
len_children = len(self.parent.children)
|
33
|
+
parent_height = sum(c.rect.h for c in self.parent.children)
|
34
|
+
parent_width = max(c.rect.w for c in self.parent.children)
|
35
|
+
if self.gap : parent_height += (len_children-1) * self.gap
|
36
|
+
# print(self.parent.to_string(),len_children,parent_height)
|
37
|
+
c = self.parent.get_constraint("height")
|
38
|
+
if not c or c.height != parent_height :
|
39
|
+
self.parent.add_constraint(ConstraintHeight(parent_height))
|
40
|
+
c = self.parent.get_constraint("width")
|
41
|
+
if not c or c.width != parent_width :
|
42
|
+
self.parent.add_constraint(ConstraintWidth(parent_width))
|
43
|
+
current_y = self.parent.rect.top
|
44
|
+
|
45
|
+
for child in self.parent.children:
|
46
|
+
child.set_position(self.parent.rect.x,current_y)
|
47
|
+
current_y += child.rect.h + self.gap
|
48
|
+
for c in self.child_constraints:
|
49
|
+
if not child.has_constraint(c.name):
|
50
|
+
child.add_constraint(c)
|
51
|
+
|
52
|
+
class Row(Layout):
|
53
|
+
def __init__(self, gap: int = 0, shrink: bool = False):
|
305
54
|
super().__init__()
|
306
|
-
self.rows = rows
|
307
|
-
self.cols = cols
|
308
55
|
self.gap = gap
|
56
|
+
self.shrink = shrink
|
309
57
|
|
310
|
-
def focus_up_child(self) -> None:
|
311
|
-
l = self.parent.get_interactive_children()
|
312
|
-
if not l:
|
313
|
-
return
|
314
|
-
current_index = self.parent.focused_index
|
315
|
-
if current_index == -1:
|
316
|
-
return
|
317
|
-
current_row = current_index // self.cols
|
318
|
-
target_index = max(0, current_index - self.cols)
|
319
|
-
if target_index // self.cols < current_row:
|
320
|
-
self.parent.focused_index = target_index
|
321
|
-
l[target_index].get_focus()
|
322
|
-
|
323
|
-
def focus_down_child(self) -> None:
|
324
|
-
l = self.parent.get_interactive_children()
|
325
|
-
if not l:
|
326
|
-
return
|
327
|
-
current_index = self.parent.focused_index
|
328
|
-
if current_index == -1:
|
329
|
-
return
|
330
|
-
current_row = current_index // self.cols
|
331
|
-
target_index = min(len(l) - 1, current_index + self.cols)
|
332
|
-
if target_index // self.cols > current_row:
|
333
|
-
self.parent.focused_index = target_index
|
334
|
-
l[target_index].get_focus()
|
335
|
-
|
336
|
-
def focus_left_child(self) -> None:
|
337
|
-
l = self.parent.get_interactive_children()
|
338
|
-
if not l:
|
339
|
-
return
|
340
|
-
current_index = self.parent.focused_index
|
341
|
-
if current_index == -1:
|
342
|
-
return
|
343
|
-
target_index = max(0, current_index - 1)
|
344
|
-
if target_index // self.cols == current_index // self.cols:
|
345
|
-
self.parent.focused_index = target_index
|
346
|
-
l[target_index].get_focus()
|
347
|
-
|
348
|
-
def focus_right_child(self) -> None:
|
349
|
-
l = self.parent.get_interactive_children()
|
350
|
-
if not l:
|
351
|
-
return
|
352
|
-
current_index = self.parent.focused_index
|
353
|
-
if current_index == -1:
|
354
|
-
return
|
355
|
-
target_index = min(len(l) - 1, current_index + 1)
|
356
|
-
if target_index // self.cols == current_index // self.cols:
|
357
|
-
self.parent.focused_index = target_index
|
358
|
-
l[target_index].get_focus()
|
359
|
-
|
360
|
-
def handle_event(self, event):
|
361
|
-
if not self.parent.get_layout_children() or not self.parent.children_has_focus():
|
362
|
-
return
|
363
|
-
|
364
|
-
if event.type == pygame.KEYDOWN:
|
365
|
-
if event.key in (pygame.K_RIGHT, pygame.K_LEFT, pygame.K_UP, pygame.K_DOWN):
|
366
|
-
if event.key == pygame.K_RIGHT:
|
367
|
-
self.focus_right_child()
|
368
|
-
elif event.key == pygame.K_LEFT:
|
369
|
-
self.focus_left_child()
|
370
|
-
elif event.key == pygame.K_UP:
|
371
|
-
self.focus_up_child()
|
372
|
-
elif event.key == pygame.K_DOWN:
|
373
|
-
self.focus_down_child()
|
374
|
-
|
375
|
-
event.consumed = True
|
376
|
-
|
377
|
-
def update_children_rect(self):
|
378
|
-
if self.parent.get_layout_children():
|
379
|
-
cell_width = max(child.get_min_required_size()[0] for child in self.parent.get_layout_children())
|
380
|
-
cell_height = max(child.get_min_required_size()[1] for child in self.parent.get_layout_children())
|
381
|
-
width = self.cols * cell_width + self.gap * (self.cols - 1)
|
382
|
-
height = self.rows * cell_height + self.gap * (self.rows - 1)
|
383
|
-
self.children_rect = pygame.FRect(*self.parent.get_inner_rect().topleft, width, height)
|
384
|
-
else:
|
385
|
-
self.children_rect = pygame.FRect(*self.parent.get_inner_rect().topleft, 10, 10)
|
386
|
-
self.children_rect.move_ip(-self.parent.scroll.x, -self.parent.scroll.y)
|
387
|
-
|
388
|
-
def arrange(self) -> None:
|
389
|
-
self.update_children_rect()
|
390
|
-
if not self.parent.get_layout_children():
|
391
|
-
return
|
392
|
-
|
393
|
-
cell_width = (self.children_rect.width - self.gap * (self.cols - 1)) / self.cols
|
394
|
-
cell_height = (self.children_rect.height - self.gap * (self.rows - 1)) / self.rows
|
395
|
-
|
396
|
-
for i, child in enumerate(self.parent.get_layout_children()):
|
397
|
-
row = i // self.cols
|
398
|
-
col = i % self.cols
|
399
|
-
x = self.children_rect.x + col * (cell_width + self.gap)
|
400
|
-
y = self.children_rect.y + row * (cell_height + self.gap)
|
401
|
-
child.set_size((cell_width, cell_height))
|
402
|
-
child.set_position(x, y)
|
403
|
-
|
404
|
-
|
405
|
-
class GridFill(Grid):
|
406
|
-
def update_children_rect(self):
|
407
|
-
self.children_rect = self.parent.get_inner_rect()
|
408
58
|
def arrange(self) -> None:
|
409
|
-
|
410
|
-
Arranges children in a grid and resizes them to fill the parent's available space,
|
411
|
-
accounting for the gap between children.
|
412
|
-
"""
|
413
|
-
self.update_children_rect()
|
414
|
-
|
415
|
-
if not self.parent.get_layout_children():
|
59
|
+
if not self.parent:
|
416
60
|
return
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
61
|
+
if self.shrink and self.parent.children:
|
62
|
+
len_children = len(self.parent.children)
|
63
|
+
parent_width = sum(c.rect.w for c in self.parent.children)
|
64
|
+
parent_height = max(c.rect.h for c in self.parent.children)
|
65
|
+
if self.gap:
|
66
|
+
parent_width += (len_children - 1) * self.gap
|
67
|
+
|
68
|
+
c = self.parent.get_constraint("width")
|
69
|
+
if not c or c.width != parent_width:
|
70
|
+
self.parent.add_constraint(ConstraintWidth(parent_width))
|
71
|
+
c = self.parent.get_constraint("height")
|
72
|
+
if not c or c.height != parent_height:
|
73
|
+
self.parent.add_constraint(ConstraintHeight(parent_height))
|
74
|
+
|
75
|
+
current_x = self.parent.rect.left
|
76
|
+
for child in self.parent.children:
|
77
|
+
child.set_position(current_x,self.parent.rect.y)
|
78
|
+
current_x += child.rect.w + self.gap
|
79
|
+
for c in self.child_constraints:
|
80
|
+
if not child.has_constraint(c.name):
|
81
|
+
child.add_constraint(c)
|