batframework 1.0.9a7__py3-none-any.whl → 1.0.9a9__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 (62) hide show
  1. batFramework/__init__.py +20 -11
  2. batFramework/action.py +1 -1
  3. batFramework/animatedSprite.py +47 -116
  4. batFramework/animation.py +30 -5
  5. batFramework/audioManager.py +8 -5
  6. batFramework/baseScene.py +240 -0
  7. batFramework/camera.py +4 -0
  8. batFramework/constants.py +6 -2
  9. batFramework/cutscene.py +221 -21
  10. batFramework/cutsceneManager.py +5 -2
  11. batFramework/drawable.py +7 -5
  12. batFramework/easingController.py +10 -11
  13. batFramework/entity.py +21 -2
  14. batFramework/enums.py +48 -33
  15. batFramework/gui/__init__.py +6 -3
  16. batFramework/gui/animatedLabel.py +10 -2
  17. batFramework/gui/button.py +4 -31
  18. batFramework/gui/clickableWidget.py +63 -50
  19. batFramework/gui/constraints/constraints.py +212 -136
  20. batFramework/gui/container.py +77 -58
  21. batFramework/gui/debugger.py +12 -17
  22. batFramework/gui/draggableWidget.py +21 -17
  23. batFramework/gui/image.py +3 -10
  24. batFramework/gui/indicator.py +56 -1
  25. batFramework/gui/interactiveWidget.py +127 -108
  26. batFramework/gui/label.py +73 -64
  27. batFramework/gui/layout.py +286 -445
  28. batFramework/gui/meter.py +42 -20
  29. batFramework/gui/radioButton.py +20 -69
  30. batFramework/gui/root.py +99 -29
  31. batFramework/gui/selector.py +250 -0
  32. batFramework/gui/shape.py +13 -5
  33. batFramework/gui/slider.py +262 -107
  34. batFramework/gui/syncedVar.py +49 -0
  35. batFramework/gui/textInput.py +46 -22
  36. batFramework/gui/toggle.py +70 -52
  37. batFramework/gui/tooltip.py +30 -0
  38. batFramework/gui/widget.py +222 -135
  39. batFramework/manager.py +7 -8
  40. batFramework/particle.py +4 -1
  41. batFramework/propertyEaser.py +79 -0
  42. batFramework/renderGroup.py +17 -50
  43. batFramework/resourceManager.py +43 -13
  44. batFramework/scene.py +15 -335
  45. batFramework/sceneLayer.py +138 -0
  46. batFramework/sceneManager.py +31 -36
  47. batFramework/scrollingSprite.py +8 -3
  48. batFramework/sprite.py +1 -1
  49. batFramework/templates/__init__.py +1 -2
  50. batFramework/templates/controller.py +97 -0
  51. batFramework/timeManager.py +76 -22
  52. batFramework/transition.py +37 -103
  53. batFramework/utils.py +125 -66
  54. {batframework-1.0.9a7.dist-info → batframework-1.0.9a9.dist-info}/METADATA +24 -3
  55. batframework-1.0.9a9.dist-info/RECORD +67 -0
  56. {batframework-1.0.9a7.dist-info → batframework-1.0.9a9.dist-info}/WHEEL +1 -1
  57. batFramework/character.py +0 -27
  58. batFramework/templates/character.py +0 -43
  59. batFramework/templates/states.py +0 -166
  60. batframework-1.0.9a7.dist-info/RECORD +0 -63
  61. /batframework-1.0.9a7.dist-info/LICENCE → /batframework-1.0.9a9.dist-info/LICENSE +0 -0
  62. {batframework-1.0.9a7.dist-info → batframework-1.0.9a9.dist-info}/top_level.txt +0 -0
@@ -1,3 +1,4 @@
1
+ from abc import ABC, abstractmethod
1
2
  from ..widget import Widget
2
3
  import batFramework as bf
3
4
  import pygame
@@ -7,11 +8,22 @@ class Constraint:
7
8
  def __init__(self, name:str|None=None, priority=0):
8
9
  self.priority = priority
9
10
  self.name = name if name is not None else self.__class__.__name__
11
+ self.old_autoresize_w = None
12
+ self.old_autoresize_h = None
13
+ self.affects_size : bool = False
14
+ self.affects_position : bool = False
15
+
10
16
 
11
17
  def on_removal(self,child_widget: Widget)->None:
12
- pass
18
+ child_widget.set_autoresize_h(self.old_autoresize_h)
19
+ child_widget.set_autoresize_w(self.old_autoresize_w)
20
+
13
21
 
14
22
  def set_priority(self, priority) -> "Constraint":
23
+ """
24
+ Highest priority is used if 2 constraints are in conflict
25
+ Default is 0
26
+ """
15
27
  self.priority = priority
16
28
  return self
17
29
 
@@ -22,6 +34,11 @@ class Constraint:
22
34
  raise NotImplementedError("Subclasses must implement evaluate method")
23
35
 
24
36
  def apply(self, parent_widget: Widget, child_widget: Widget = None) -> bool:
37
+ if self.old_autoresize_h is None:
38
+ self.old_autoresize_h = child_widget.autoresize_h
39
+ if self.old_autoresize_w is None:
40
+ self.old_autoresize_w = child_widget.autoresize_w
41
+
25
42
  if not self.evaluate(parent_widget, child_widget):
26
43
  self.apply_constraint(parent_widget, child_widget)
27
44
  return False
@@ -39,18 +56,14 @@ class MinWidth(Constraint):
39
56
  def __init__(self, width: float):
40
57
  super().__init__()
41
58
  self.min_width = width
59
+ self.affects_size = True
42
60
 
43
- def on_removal(self, child_widget: Widget) -> None:
44
- return
45
- # child_widget.set_autoresize_w(False)
46
61
 
47
62
  def evaluate(self, parent_widget, child_widget):
48
- res = child_widget.rect.width >= self.min_width
49
- # if not res:
50
- # child_widget.set_autoresize_w(False)
51
- return res
63
+ return child_widget.rect.width >= self.min_width
52
64
 
53
65
  def apply_constraint(self, parent_widget, child_widget):
66
+ child_widget.set_autoresize_w(False)
54
67
  child_widget.set_size((self.min_width, None))
55
68
 
56
69
  def __eq__(self,other:"Constraint")->bool:
@@ -65,17 +78,15 @@ class MinHeight(Constraint):
65
78
  def __init__(self, height: float):
66
79
  super().__init__()
67
80
  self.min_height = height
81
+ self.affects_size = True
68
82
 
69
- def on_removal(self, child_widget: Widget) -> None:
70
- child_widget.set_autoresize_h(False)
71
83
 
72
84
  def evaluate(self, parent_widget, child_widget):
73
- res = child_widget.rect.h >= self.min_height
74
- if not res:
75
- child_widget.set_autoresize_w(False)
76
- return res
85
+ return child_widget.rect.h >= self.min_height
86
+
77
87
 
78
88
  def apply_constraint(self, parent_widget, child_widget):
89
+ child_widget.set_autoresize_h(False)
79
90
  child_widget.set_size((None, self.min_height))
80
91
 
81
92
  def __eq__(self,other:"Constraint")->bool:
@@ -90,6 +101,7 @@ class MaxWidth(Constraint):
90
101
  def __init__(self, width: float):
91
102
  super().__init__()
92
103
  self.max_width = width
104
+ self.affects_size = True
93
105
 
94
106
  def on_removal(self, child_widget: Widget) -> None:
95
107
  child_widget.set_autoresize_w(False)
@@ -115,6 +127,7 @@ class MaxHeight(Constraint):
115
127
  def __init__(self, height: float):
116
128
  super().__init__()
117
129
  self.max_height = height
130
+ self.affects_size = True
118
131
 
119
132
  def on_removal(self, child_widget: Widget) -> None:
120
133
  child_widget.set_autoresize_h(False)
@@ -140,76 +153,69 @@ class MaxHeight(Constraint):
140
153
  class CenterX(Constraint):
141
154
  def __init__(self):
142
155
  super().__init__()
156
+ self.affects_position = True
143
157
 
144
158
  def evaluate(self, parent_widget, child_widget):
145
159
  return (
146
- int(child_widget.rect.centerx - parent_widget.get_padded_center()[0]) == 0
160
+ child_widget.rect.centerx - parent_widget.get_inner_center()[0] == 0
147
161
  )
148
162
 
149
163
  def apply_constraint(self, parent_widget, child_widget):
150
164
  child_widget.set_center(
151
- parent_widget.get_padded_center()[0], child_widget.rect.centery
165
+ parent_widget.get_inner_center()[0], child_widget.rect.centery
152
166
  )
153
167
 
154
168
 
155
169
  class CenterY(Constraint):
156
170
  def __init__(self):
157
171
  super().__init__()
172
+ self.affects_position = True
158
173
 
159
174
  def evaluate(self, parent_widget, child_widget):
160
175
  return (
161
- int(child_widget.rect.centery - parent_widget.get_padded_center()[1]) == 0
176
+ child_widget.rect.centery - parent_widget.get_inner_center()[1] == 0
162
177
  )
163
178
 
164
179
  def apply_constraint(self, parent_widget, child_widget):
165
180
  child_widget.set_center(
166
- child_widget.rect.centerx, parent_widget.get_padded_center()[1]
181
+ child_widget.rect.centerx, parent_widget.get_inner_center()[1]
167
182
  )
168
183
 
169
184
 
170
185
  class Center(Constraint):
171
186
  def __init__(self):
172
187
  super().__init__()
188
+ self.affects_position = True
173
189
 
174
190
  def evaluate(self, parent_widget, child_widget):
175
191
  return (
176
- int(child_widget.rect.centerx - parent_widget.get_padded_center()[0]) == 0
177
- and int(child_widget.rect.centery - parent_widget.get_padded_center()[1])
178
- == 0
192
+ child_widget.rect.centerx - parent_widget.get_inner_center()[0] == 0
193
+ and child_widget.rect.centery - parent_widget.get_inner_center()[1] == 0
179
194
  )
180
195
 
181
196
  def apply_constraint(self, parent_widget, child_widget):
182
- child_widget.set_center(*parent_widget.get_padded_center())
197
+ child_widget.set_center(*parent_widget.get_inner_center())
183
198
 
184
199
 
185
200
  class PercentageWidth(Constraint):
186
- def __init__(self, percentage: float, keep_autoresize: bool = False):
201
+ def __init__(self, percentage: float):
187
202
  super().__init__()
188
203
  self.percentage: float = percentage
189
- self.keep_autoresize: bool = keep_autoresize
190
-
191
- def on_removal(self, child_widget: Widget) -> None:
192
- child_widget.set_autoresize_w(True)
204
+ self.affects_size = True
193
205
 
194
206
  def __str__(self) -> str:
195
- return f"{super().__str__()}.[{self.percentage*100}%,keep_autoresize={self.keep_autoresize}]"
207
+ return f"{super().__str__()}.[{self.percentage*100}%]"
196
208
 
197
209
  def evaluate(self, parent_widget, child_widget):
198
210
  return child_widget.rect.width == round(
199
- parent_widget.get_padded_width() * self.percentage
211
+ parent_widget.get_inner_width() * self.percentage
200
212
  )
201
213
 
202
214
  def apply_constraint(self, parent_widget, child_widget):
203
215
  if child_widget.autoresize_w:
204
- if self.keep_autoresize:
205
- print(
206
- f"WARNING: Constraint on {child_widget.__str__()} can't resize, autoresize set to True"
207
- )
208
- return
209
216
  child_widget.set_autoresize_w(False)
210
-
211
217
  child_widget.set_size(
212
- (round(parent_widget.get_padded_width() * self.percentage), None)
218
+ (round(parent_widget.get_inner_width() * self.percentage), None)
213
219
  )
214
220
 
215
221
  def __eq__(self,other:"Constraint")->bool:
@@ -222,32 +228,25 @@ class PercentageWidth(Constraint):
222
228
 
223
229
 
224
230
  class PercentageHeight(Constraint):
225
- def __init__(self, percentage: float, keep_autoresize: bool = False):
231
+ def __init__(self, percentage: float):
226
232
  super().__init__()
227
233
  self.percentage: float = percentage
228
- self.keep_autoresize: bool = keep_autoresize
234
+ self.affects_size = True
229
235
 
230
- def on_removal(self, child_widget: Widget) -> None:
231
- child_widget.set_autoresize_h(True)
232
236
 
233
237
  def evaluate(self, parent_widget, child_widget):
234
238
  return child_widget.rect.height == round(
235
- parent_widget.get_padded_height() * self.percentage
239
+ parent_widget.get_inner_height() * self.percentage
236
240
  )
237
241
 
238
242
  def __str__(self) -> str:
239
- return f"{super().__str__()}.[{self.percentage*100}%,keep_autoresize={self.keep_autoresize}]"
243
+ return f"{super().__str__()}.[{self.percentage*100}%]"
240
244
 
241
245
  def apply_constraint(self, parent_widget, child_widget):
242
246
  if child_widget.autoresize_h:
243
- if self.keep_autoresize:
244
- print(
245
- f"WARNING: Constraint on {child_widget} can't resize, autoresize set to True"
246
- )
247
- return
248
247
  child_widget.set_autoresize_h(False)
249
248
  child_widget.set_size(
250
- (None, round(parent_widget.get_padded_height() * self.percentage))
249
+ (None, round(parent_widget.get_inner_height() * self.percentage))
251
250
  )
252
251
 
253
252
  def __eq__(self,other:"Constraint")->bool:
@@ -259,30 +258,29 @@ class PercentageHeight(Constraint):
259
258
  )
260
259
 
261
260
  class FillX(PercentageWidth):
262
- def __init__(self, keep_autoresize: bool = False):
263
- super().__init__(1, keep_autoresize)
261
+ def __init__(self):
262
+ super().__init__(1)
264
263
  self.name = "FillX"
264
+ self.affects_size = True
265
265
 
266
266
  def __eq__(self, other: Constraint) -> bool:
267
267
  return Constraint.__eq__(self,other)
268
268
 
269
269
  class FillY(PercentageHeight):
270
- def __init__(self, keep_autoresize: bool = False):
271
- super().__init__(1, keep_autoresize)
270
+ def __init__(self):
271
+ super().__init__(1)
272
272
  self.name = "FillY"
273
+ self.affects_size = True
273
274
 
274
275
  def __eq__(self, other: Constraint) -> bool:
275
276
  return Constraint.__eq__(self,other)
276
277
 
277
278
 
278
279
  class PercentageRectHeight(Constraint):
279
- def __init__(self, percentage: float, keep_autoresize: bool = False):
280
+ def __init__(self, percentage: float):
280
281
  super().__init__()
281
282
  self.percentage: float = percentage
282
- self.keep_autoresize: bool = keep_autoresize
283
-
284
- def on_removal(self, child_widget: Widget) -> None:
285
- child_widget.set_autoresize_h(True)
283
+ self.affects_size = True
286
284
 
287
285
  def evaluate(self, parent_widget, child_widget):
288
286
  return child_widget.rect.height == round(
@@ -290,15 +288,10 @@ class PercentageRectHeight(Constraint):
290
288
  )
291
289
 
292
290
  def __str__(self) -> str:
293
- return f"{super().__str__()}.[{self.percentage*100}%, keep_autoresize={self.keep_autoresize}]"
291
+ return f"{super().__str__()}.[{self.percentage*100}%]"
294
292
 
295
293
  def apply_constraint(self, parent_widget, child_widget):
296
294
  if child_widget.autoresize_h:
297
- if self.keep_autoresize:
298
- print(
299
- f"WARNING: Constraint on {child_widget} can't resize, autoresize set to True"
300
- )
301
- return
302
295
  child_widget.set_autoresize_h(False)
303
296
  child_widget.set_size(
304
297
  (None, round(parent_widget.rect.height * self.percentage))
@@ -313,10 +306,10 @@ class PercentageRectHeight(Constraint):
313
306
  )
314
307
 
315
308
  class PercentageRectWidth(Constraint):
316
- def __init__(self, percentage: float, keep_autoresize: bool = False):
309
+ def __init__(self, percentage: float):
317
310
  super().__init__()
318
311
  self.percentage: float = percentage
319
- self.keep_autoresize: bool = keep_autoresize
312
+ self.affects_size = True
320
313
 
321
314
  def on_removal(self, child_widget: Widget) -> None:
322
315
  child_widget.set_autoresize_w(True)
@@ -327,15 +320,10 @@ class PercentageRectWidth(Constraint):
327
320
  )
328
321
 
329
322
  def __str__(self) -> str:
330
- return f"{super().__str__()}.[{self.percentage*100}%, keep_autoresize={self.keep_autoresize}]"
323
+ return f"{super().__str__()}.[{self.percentage*100}%]"
331
324
 
332
325
  def apply_constraint(self, parent_widget, child_widget):
333
326
  if child_widget.autoresize_w:
334
- if self.keep_autoresize:
335
- print(
336
- f"WARNING: Constraint on {child_widget} can't resize, autoresize set to True"
337
- )
338
- return
339
327
  child_widget.set_autoresize_w(False)
340
328
  child_widget.set_size((round(parent_widget.rect.width * self.percentage), None))
341
329
 
@@ -348,15 +336,17 @@ class PercentageRectWidth(Constraint):
348
336
  )
349
337
 
350
338
  class FillRectX(PercentageRectWidth):
351
- def __init__(self, keep_autoresize: bool = False):
352
- super().__init__(1, keep_autoresize)
339
+ def __init__(self):
340
+ super().__init__(1)
353
341
  self.name = "fill_rect_x"
342
+ self.affects_size = True
354
343
 
355
344
 
356
345
  class FillRectY(PercentageRectHeight):
357
- def __init__(self, keep_autoresize: bool = False):
358
- super().__init__(1, keep_autoresize)
346
+ def __init__(self):
347
+ super().__init__(1)
359
348
  self.name = "fill_rect_y"
349
+ self.affects_size = True
360
350
 
361
351
 
362
352
  class AspectRatio(Constraint):
@@ -364,57 +354,48 @@ class AspectRatio(Constraint):
364
354
  self,
365
355
  ratio: int | float | pygame.rect.FRectType = 1,
366
356
  reference_axis: bf.axis = bf.axis.HORIZONTAL,
367
- keep_autoresize=False,
368
357
  ):
369
358
  super().__init__()
370
359
  self.ref_axis: bf.axis = reference_axis
371
- self.keep_autoresize: bool = keep_autoresize
360
+ self.affects_size = True
372
361
 
373
362
  if isinstance(ratio, float | int):
374
363
  self.ratio = ratio
375
364
  elif isinstance(ratio, pygame.rect.FRect):
376
365
  self.ratio = (
377
- (ratio.w / ratio.h)
366
+ round(ratio.w / ratio.h,2)
378
367
  if reference_axis == bf.axis.HORIZONTAL
379
- else (ratio.h / ratio.w)
368
+ else round(ratio.h / ratio.w,2)
380
369
  )
381
370
  else:
382
371
  raise TypeError(f"Ratio must be float or FRect")
383
372
 
384
- def on_removal(self, child_widget: Widget) -> None:
385
- child_widget.set_autoresize(True)
386
373
 
387
374
 
388
375
  def evaluate(self, parent_widget, child_widget):
389
376
  if self.ref_axis == bf.axis.HORIZONTAL:
390
- return self.ratio == child_widget.rect.h / child_widget.rect.w
377
+ return self.ratio == round(child_widget.rect.h / child_widget.rect.w,2)
391
378
  if self.ref_axis == bf.axis.VERTICAL:
392
- return self.ratio == child_widget.rect.w / child_widget.rect.h
379
+ return self.ratio == round(child_widget.rect.w / child_widget.rect.h,2)
393
380
 
394
381
 
395
382
  def apply_constraint(self, parent_widget, child_widget):
396
383
 
397
384
  if self.ref_axis == bf.axis.VERTICAL:
398
385
  if child_widget.autoresize_w:
399
- if self.keep_autoresize:
400
- print(
401
- f"WARNING: Constraint on {str(child_widget)} can't resize, autoresize set to True"
402
- )
403
- return
404
386
  child_widget.set_autoresize_w(False)
405
387
  child_widget.set_size((child_widget.rect.h * self.ratio, None))
406
388
 
407
389
  if self.ref_axis == bf.axis.HORIZONTAL:
408
390
  if child_widget.autoresize_h:
409
- if self.keep_autoresize:
410
- print(
411
- f"WARNING: Constraint on {str(child_widget)} can't resize, autoresize set to True"
412
- )
413
- return
414
391
  child_widget.set_autoresize_h(False)
415
392
 
416
393
  child_widget.set_size((None, child_widget.rect.w * self.ratio))
417
394
 
395
+ def __str__(self) -> str:
396
+ return f"{self.name.upper()}[ratio = {self.ratio}, ref = {'Vertical' if self.ref_axis == bf.axis.VERTICAL else 'Horizontal'}]"
397
+
398
+
418
399
  def __eq__(self,other:"Constraint")->bool:
419
400
  if not isinstance(other,self.__class__):
420
401
  return False
@@ -427,54 +408,69 @@ class AspectRatio(Constraint):
427
408
  class AnchorBottom(Constraint):
428
409
  def __init__(self):
429
410
  super().__init__()
411
+ self.affects_position = True
430
412
 
431
413
  def evaluate(self, parent_widget, child_widget):
432
414
  return (
433
415
  child_widget.rect.bottom
434
- == parent_widget.get_padded_bottom()
416
+ == parent_widget.get_inner_bottom()
435
417
  )
436
418
 
437
419
  def apply_constraint(self, parent_widget, child_widget):
438
420
  child_widget.set_position(
439
- child_widget.rect.x, parent_widget.get_padded_bottom() - child_widget.rect.h
421
+ child_widget.rect.x, parent_widget.get_inner_bottom() - child_widget.rect.h
440
422
  )
441
423
 
442
424
  class AnchorTop(Constraint):
443
425
  def __init__(self):
444
426
  super().__init__()
427
+ self.affects_position = True
445
428
 
446
429
  def evaluate(self, parent_widget, child_widget):
447
- return (child_widget.rect.top == parent_widget.get_padded_top())
430
+ return (child_widget.rect.top == parent_widget.get_inner_top())
448
431
 
449
432
  def apply_constraint(self, parent_widget, child_widget):
450
- child_widget.set_position(child_widget.rect.x, parent_widget.get_padded_top())
433
+ child_widget.set_position(child_widget.rect.x, parent_widget.get_inner_top())
451
434
 
452
435
 
453
436
  class AnchorTopRight(Constraint):
454
437
  def __init__(self):
455
438
  super().__init__()
439
+ self.affects_position = True
456
440
 
457
441
  def evaluate(self, parent_widget, child_widget):
458
- return child_widget.rect.topright == parent_widget.get_padded_rect().topright
442
+ return child_widget.rect.topright == parent_widget.get_inner_rect().topright
459
443
 
460
444
  def apply_constraint(self, parent_widget, child_widget):
461
- # print("before",child_widget.rect.topright, parent_widget.get_padded_rect().topright)
462
- topright = parent_widget.get_padded_rect().topright
445
+ # print("before",child_widget.rect.topright, parent_widget.get_inner_rect().topright)
446
+ topright = parent_widget.get_inner_rect().topright
463
447
  child_widget.set_position(topright[0] - child_widget.rect.w,topright[1])
464
- # print("after",child_widget.rect.topright, parent_widget.get_padded_rect().topright)
448
+ # print("after",child_widget.rect.topright, parent_widget.get_inner_rect().topright)
449
+
450
+ class AnchorTopLeft(Constraint):
451
+ def __init__(self):
452
+ super().__init__()
453
+ self.affects_position = True
454
+
455
+ def evaluate(self, parent_widget, child_widget):
456
+ return child_widget.rect.topleft == parent_widget.get_inner_rect().topleft
457
+
458
+ def apply_constraint(self, parent_widget, child_widget):
459
+ child_widget.set_position(*parent_widget.get_inner_rect().topleft)
465
460
 
466
461
 
467
462
  class AnchorBottomRight(Constraint):
468
463
  def __init__(self):
469
464
  super().__init__()
465
+ self.affects_position = True
470
466
 
471
467
  def evaluate(self, parent_widget, child_widget):
472
468
  return (
473
- child_widget.rect.bottomright == parent_widget.get_padded_rect().bottomright
469
+ child_widget.rect.bottomright == parent_widget.get_inner_rect().bottomright
474
470
  )
475
471
 
476
472
  def apply_constraint(self, parent_widget, child_widget):
477
- bottomright = parent_widget.get_padded_rect().bottomright
473
+ bottomright = parent_widget.get_inner_rect().bottomright
478
474
 
479
475
  child_widget.set_position(
480
476
  bottomright[0] - child_widget.rect.w,
@@ -485,27 +481,29 @@ class AnchorBottomRight(Constraint):
485
481
  class AnchorRight(Constraint):
486
482
  def __init__(self):
487
483
  super().__init__()
484
+ self.affects_position = True
488
485
 
489
486
  def evaluate(self, parent_widget, child_widget):
490
- return child_widget.rect.right == parent_widget.get_padded_right()
487
+ return child_widget.rect.right == parent_widget.get_inner_right()
491
488
 
492
489
  def apply_constraint(self, parent_widget, child_widget):
493
490
  child_widget.set_position(
494
- parent_widget.get_padded_right() - child_widget.rect.w,
495
- child_widget.rect.top,
491
+ parent_widget.get_inner_right() - child_widget.rect.w,
492
+ None,
496
493
  )
497
494
 
498
495
 
499
496
  class AnchorLeft(Constraint):
500
497
  def __init__(self):
501
498
  super().__init__()
499
+ self.affects_position = True
502
500
 
503
501
  def evaluate(self, parent_widget, child_widget):
504
- return child_widget.rect.left == parent_widget.get_padded_left()
502
+ return child_widget.rect.left == parent_widget.get_inner_left()
505
503
 
506
504
  def apply_constraint(self, parent_widget, child_widget):
507
505
  child_widget.set_position(
508
- parent_widget.get_padded_left(), child_widget.rect.top
506
+ parent_widget.get_inner_left(), None
509
507
  )
510
508
 
511
509
 
@@ -513,16 +511,17 @@ class MarginBottom(Constraint):
513
511
  def __init__(self, margin: float):
514
512
  super().__init__()
515
513
  self.margin = margin
514
+ self.affects_position = True
516
515
 
517
516
  def evaluate(self, parent_widget, child_widget):
518
517
  return (
519
- child_widget.rect.bottom == parent_widget.get_padded_bottom() - self.margin
518
+ child_widget.rect.bottom == parent_widget.get_inner_bottom() - self.margin
520
519
  )
521
520
 
522
521
  def apply_constraint(self, parent_widget, child_widget):
523
522
  child_widget.set_position(
524
523
  child_widget.rect.x,
525
- parent_widget.get_padded_bottom() - child_widget.rect.h - self.margin,
524
+ parent_widget.get_inner_bottom() - child_widget.rect.h - self.margin,
526
525
  )
527
526
 
528
527
  def __eq__(self,other:"Constraint")->bool:
@@ -537,13 +536,14 @@ class MarginTop(Constraint):
537
536
  def __init__(self, margin: float):
538
537
  super().__init__()
539
538
  self.margin = margin
539
+ self.affects_position = True
540
540
 
541
541
  def evaluate(self, parent_widget, child_widget):
542
- return child_widget.rect.top == parent_widget.get_padded_top() + self.margin
542
+ return child_widget.rect.top == parent_widget.get_inner_top() + self.margin
543
543
 
544
544
  def apply_constraint(self, parent_widget, child_widget):
545
545
  child_widget.set_position(
546
- child_widget.rect.x, parent_widget.get_padded_top() + self.margin
546
+ child_widget.rect.x, parent_widget.get_inner_top() + self.margin
547
547
  )
548
548
 
549
549
  def __eq__(self,other:"Constraint")->bool:
@@ -558,14 +558,15 @@ class MarginLeft(Constraint):
558
558
  def __init__(self, margin: float):
559
559
  super().__init__()
560
560
  self.margin = margin
561
+ self.affects_position = True
561
562
 
562
563
  def evaluate(self, parent_widget, child_widget):
563
- return child_widget.rect.left == parent_widget.get_padded_left() + self.margin
564
+ return child_widget.rect.left == parent_widget.get_inner_left() + self.margin
564
565
 
565
566
  def apply_constraint(self, parent_widget, child_widget):
566
567
  if not self.evaluate(parent_widget, child_widget):
567
568
  child_widget.set_position(
568
- parent_widget.get_padded_left() + self.margin, child_widget.rect.y
569
+ parent_widget.get_inner_left() + self.margin, child_widget.rect.y
569
570
  )
570
571
 
571
572
  def __eq__(self,other:"Constraint")->bool:
@@ -580,13 +581,14 @@ class MarginRight(Constraint):
580
581
  def __init__(self, margin: float):
581
582
  super().__init__()
582
583
  self.margin = margin
584
+ self.affects_position = True
583
585
 
584
586
  def evaluate(self, parent_widget, child_widget):
585
- return child_widget.rect.right == parent_widget.get_padded_right() - self.margin
587
+ return child_widget.rect.right == parent_widget.get_inner_right() - self.margin
586
588
 
587
589
  def apply_constraint(self, parent_widget, child_widget):
588
590
  child_widget.set_position(
589
- parent_widget.get_padded_right() - child_widget.rect.w - self.margin,
591
+ parent_widget.get_inner_right() - child_widget.rect.w - self.margin,
590
592
  child_widget.rect.y,
591
593
  )
592
594
 
@@ -602,6 +604,7 @@ class RectMarginBottom(Constraint):
602
604
  def __init__(self, margin: float):
603
605
  super().__init__()
604
606
  self.margin = margin
607
+ self.affects_position = True
605
608
 
606
609
  def evaluate(self, parent_widget, child_widget):
607
610
  return (
@@ -626,6 +629,7 @@ class RectMarginTop(Constraint):
626
629
  def __init__(self, margin: float):
627
630
  super().__init__()
628
631
  self.margin = margin
632
+ self.affects_position = True
629
633
 
630
634
  def evaluate(self, parent_widget, child_widget):
631
635
  return child_widget.rect.top == parent_widget.rect.top + self.margin
@@ -647,6 +651,7 @@ class RectMarginLeft(Constraint):
647
651
  def __init__(self, margin: float):
648
652
  super().__init__()
649
653
  self.margin = margin
654
+ self.affects_position = True
650
655
 
651
656
  def evaluate(self, parent_widget, child_widget):
652
657
  return child_widget.rect.left == parent_widget.rect.left + self.margin
@@ -669,6 +674,7 @@ class RectMarginRight(Constraint):
669
674
  def __init__(self, margin: float):
670
675
  super().__init__()
671
676
  self.margin = margin
677
+ self.affects_position = True
672
678
 
673
679
  def evaluate(self, parent_widget, child_widget):
674
680
  return child_widget.rect.right == parent_widget.rect.right - self.margin
@@ -691,20 +697,22 @@ class PercentageMarginBottom(Constraint):
691
697
  def __init__(self, margin: float):
692
698
  super().__init__()
693
699
  self.margin = margin
700
+ self.affects_position = True
694
701
 
695
702
  def evaluate(self, parent_widget, child_widget):
696
- return (
703
+ return abs(
697
704
  child_widget.rect.bottom
698
- == parent_widget.get_padded_top()
699
- + parent_widget.get_padded_height() * self.margin
700
- )
705
+ - (
706
+ parent_widget.get_inner_bottom()-
707
+ parent_widget.get_inner_height() * self.margin)
708
+ ) < 0.01
701
709
 
702
710
  def apply_constraint(self, parent_widget, child_widget):
703
711
  child_widget.set_position(
704
712
  child_widget.rect.x,
705
- parent_widget.get_padded_bottom()
713
+ parent_widget.get_inner_bottom()
706
714
  - child_widget.rect.h
707
- - parent_widget.get_padded_height() * self.margin,
715
+ - parent_widget.get_inner_height() * self.margin,
708
716
  )
709
717
 
710
718
  def __eq__(self,other:"Constraint")->bool:
@@ -719,19 +727,21 @@ class PercentageMarginTop(Constraint):
719
727
  def __init__(self, margin: float):
720
728
  super().__init__()
721
729
  self.margin = margin
730
+ self.affects_position = True
722
731
 
723
732
  def evaluate(self, parent_widget, child_widget):
724
- return (
733
+ return abs(
725
734
  child_widget.rect.top
726
- == parent_widget.get_padded_top()
727
- + parent_widget.get_padded_height() * self.margin
728
- )
735
+ - (
736
+ parent_widget.get_inner_top()+
737
+ parent_widget.get_inner_height() * self.margin)
738
+ ) < 0.01
729
739
 
730
740
  def apply_constraint(self, parent_widget, child_widget):
731
741
  child_widget.set_position(
732
742
  child_widget.rect.x,
733
- parent_widget.get_padded_top()
734
- + parent_widget.get_padded_height() * self.margin,
743
+ parent_widget.get_inner_top()
744
+ + parent_widget.get_inner_height() * self.margin,
735
745
  )
736
746
 
737
747
  def __eq__(self,other:"Constraint")->bool:
@@ -746,19 +756,20 @@ class PercentageMarginLeft(Constraint):
746
756
  def __init__(self, margin: float):
747
757
  super().__init__()
748
758
  self.margin = margin
759
+ self.affects_position = True
749
760
 
750
761
  def evaluate(self, parent_widget, child_widget):
751
762
  return (
752
763
  child_widget.rect.left
753
- == parent_widget.get_padded_left()
754
- + parent_widget.get_padded_width() * self.margin
764
+ == parent_widget.get_inner_left()
765
+ + parent_widget.get_inner_width() * self.margin
755
766
  )
756
767
 
757
768
  def apply_constraint(self, parent_widget, child_widget):
758
769
  if not self.evaluate(parent_widget, child_widget):
759
770
  child_widget.set_position(
760
- parent_widget.get_padded_left()
761
- + parent_widget.get_padded_width() * self.margin,
771
+ parent_widget.get_inner_left()
772
+ + parent_widget.get_inner_width() * self.margin,
762
773
  child_widget.rect.y,
763
774
  )
764
775
 
@@ -774,19 +785,20 @@ class PercentageMarginRight(Constraint):
774
785
  def __init__(self, margin: float):
775
786
  super().__init__()
776
787
  self.margin = margin
788
+ self.affects_position = True
777
789
 
778
790
  def evaluate(self, parent_widget, child_widget):
779
791
  return (
780
792
  child_widget.rect.right
781
- == parent_widget.get_padded_right()
782
- - parent_widget.get_padded_width() * self.margin
793
+ == parent_widget.get_inner_right()
794
+ - parent_widget.get_inner_width() * self.margin
783
795
  )
784
796
 
785
797
  def apply_constraint(self, parent_widget, child_widget):
786
798
  child_widget.set_position(
787
- parent_widget.get_padded_right()
799
+ parent_widget.get_inner_right()
788
800
  - child_widget.rect.w
789
- - parent_widget.get_padded_width() * self.margin,
801
+ - parent_widget.get_inner_width() * self.margin,
790
802
  child_widget.rect.y,
791
803
  )
792
804
 
@@ -802,6 +814,7 @@ class PercentageRectMarginBottom(Constraint):
802
814
  def __init__(self, margin: float):
803
815
  super().__init__()
804
816
  self.margin = margin
817
+ self.affects_position = True
805
818
 
806
819
  def evaluate(self, parent_widget, child_widget):
807
820
  return (
@@ -829,6 +842,7 @@ class PercentageRectMarginTop(Constraint):
829
842
  def __init__(self, margin: float):
830
843
  super().__init__()
831
844
  self.margin = margin
845
+ self.affects_position = True
832
846
 
833
847
  def evaluate(self, parent_widget, child_widget):
834
848
  return (
@@ -854,6 +868,7 @@ class PercentageRectMarginLeft(Constraint):
854
868
  def __init__(self, margin: float):
855
869
  super().__init__()
856
870
  self.margin = margin
871
+ self.affects_position = True
857
872
 
858
873
  def evaluate(self, parent_widget, child_widget):
859
874
  return (
@@ -880,6 +895,7 @@ class PercentageRectMarginRight(Constraint):
880
895
  def __init__(self, margin: float):
881
896
  super().__init__()
882
897
  self.margin = margin
898
+ self.affects_position = True
883
899
 
884
900
  def evaluate(self, parent_widget, child_widget):
885
901
  return (
@@ -902,3 +918,63 @@ class PercentageRectMarginRight(Constraint):
902
918
  other.name == self.name and
903
919
  other.margin == self.margin
904
920
  )
921
+
922
+
923
+
924
+
925
+ class Grow(Constraint, ABC):
926
+
927
+ @abstractmethod
928
+ def evaluate(self, parent_widget, child_widget):
929
+ pass
930
+
931
+ @abstractmethod
932
+ def apply_constraint(self, parent_widget, child_widget):
933
+ pass
934
+
935
+ def __eq__(self, other: "Constraint") -> bool:
936
+ return isinstance(other, self.__class__)
937
+
938
+
939
+ class GrowH(Grow):
940
+ def __init__(self):
941
+ super().__init__()
942
+ self.affects_size = True
943
+
944
+ def evaluate(self, parent_widget, child_widget):
945
+ siblings = [s for s in parent_widget.children if s != child_widget]
946
+ sibling_width = sum(s.rect.w for s in siblings)
947
+ return abs(parent_widget.get_inner_width() - (child_widget.rect.w + sibling_width)) == 0
948
+
949
+ def apply_constraint(self, parent_widget, child_widget):
950
+ child_widget.set_autoresize_w(False)
951
+ siblings = [s for s in parent_widget.children if s != child_widget]
952
+ sibling_width = sum(s.rect.w for s in siblings)
953
+ # print(parent_widget.get_inner_width() - sibling_width," is new size")
954
+ if hasattr(parent_widget,"layout"):
955
+ w = parent_widget.layout.get_free_space()[0]
956
+ else:
957
+ w = parent_widget.get_inner_width()
958
+ child_widget.set_size((w - sibling_width, None))
959
+
960
+
961
+ class GrowV(Grow):
962
+ def __init__(self):
963
+ super().__init__()
964
+ self.affects_size = True
965
+
966
+ def evaluate(self, parent_widget, child_widget):
967
+ siblings = [s for s in parent_widget.children if s != child_widget]
968
+ sibling_height = sum(s.rect.h for s in siblings)
969
+ return abs(parent_widget.get_inner_height() - (child_widget.rect.h + sibling_height)) == 0
970
+
971
+ def apply_constraint(self, parent_widget, child_widget):
972
+ child_widget.set_autoresize_h(False)
973
+ siblings = [s for s in parent_widget.children if s != child_widget]
974
+ sibling_height = sum(s.rect.h for s in siblings)
975
+ if hasattr(parent_widget,"layou"):
976
+ h = parent_widget.layout.get_free_space()[1]
977
+ else:
978
+ h = parent_widget.get_inner_height()
979
+
980
+ child_widget.set_size((None, h- sibling_height))