batframework 1.0.8a4__py3-none-any.whl → 1.0.8a6__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 +15 -1
- batFramework/animatedSprite.py +65 -50
- batFramework/character.py +27 -0
- batFramework/dynamicEntity.py +1 -0
- batFramework/enums.py +2 -2
- batFramework/fontManager.py +2 -2
- batFramework/gui/clickableWidget.py +6 -7
- batFramework/gui/constraints/constraints.py +125 -40
- batFramework/gui/image.py +14 -14
- batFramework/gui/interactiveWidget.py +15 -0
- batFramework/gui/label.py +44 -27
- batFramework/gui/layout.py +23 -14
- batFramework/gui/meter.py +10 -7
- batFramework/gui/radioButton.py +1 -1
- batFramework/gui/shape.py +3 -25
- batFramework/gui/slider.py +40 -30
- batFramework/gui/textInput.py +160 -50
- batFramework/gui/toggle.py +20 -22
- batFramework/gui/widget.py +65 -32
- batFramework/manager.py +17 -5
- batFramework/object.py +17 -8
- batFramework/particle.py +18 -4
- batFramework/scene.py +1 -1
- batFramework/sceneManager.py +42 -13
- batFramework/stateMachine.py +9 -6
- batFramework/templates/__init__.py +2 -0
- batFramework/templates/character.py +44 -0
- batFramework/templates/states.py +166 -0
- batFramework/time.py +30 -9
- batFramework/transition.py +2 -2
- batFramework/triggerZone.py +1 -1
- batFramework/utils.py +35 -6
- {batframework-1.0.8a4.dist-info → batframework-1.0.8a6.dist-info}/METADATA +3 -15
- batframework-1.0.8a6.dist-info/RECORD +62 -0
- {batframework-1.0.8a4.dist-info → batframework-1.0.8a6.dist-info}/WHEEL +1 -1
- batframework-1.0.8a4.dist-info/RECORD +0 -58
- {batframework-1.0.8a4.dist-info → batframework-1.0.8a6.dist-info}/LICENCE +0 -0
- {batframework-1.0.8a4.dist-info → batframework-1.0.8a6.dist-info}/top_level.txt +0 -0
@@ -4,9 +4,12 @@ import pygame
|
|
4
4
|
|
5
5
|
|
6
6
|
class Constraint:
|
7
|
-
def __init__(self, name=
|
7
|
+
def __init__(self, name:str|None=None, priority=0):
|
8
8
|
self.priority = priority
|
9
|
-
self.name = name
|
9
|
+
self.name = name if name is not None else self.__class__.__name__
|
10
|
+
|
11
|
+
def on_removal(self,child_widget: Widget)->None:
|
12
|
+
pass
|
10
13
|
|
11
14
|
def set_priority(self, priority) -> "Constraint":
|
12
15
|
self.priority = priority
|
@@ -34,13 +37,20 @@ class Constraint:
|
|
34
37
|
|
35
38
|
class MinWidth(Constraint):
|
36
39
|
def __init__(self, width: float):
|
37
|
-
super().__init__(
|
40
|
+
super().__init__()
|
38
41
|
self.min_width = width
|
39
42
|
|
43
|
+
def on_removal(self, child_widget: Widget) -> None:
|
44
|
+
child_widget.set_autoresize_w(False)
|
45
|
+
|
40
46
|
def evaluate(self, parent_widget, child_widget):
|
41
|
-
|
47
|
+
res = child_widget.rect.width >= self.min_width
|
48
|
+
if not res:
|
49
|
+
child_widget.set_autoresize_w(False)
|
50
|
+
return res
|
42
51
|
|
43
52
|
def apply_constraint(self, parent_widget, child_widget):
|
53
|
+
child_widget.set_autoresize_w(True)
|
44
54
|
child_widget.set_size((self.min_width, None))
|
45
55
|
|
46
56
|
def __eq__(self,other:"Constraint")->bool:
|
@@ -53,11 +63,17 @@ class MinWidth(Constraint):
|
|
53
63
|
|
54
64
|
class MinHeight(Constraint):
|
55
65
|
def __init__(self, height: float):
|
56
|
-
super().__init__(
|
66
|
+
super().__init__()
|
57
67
|
self.min_height = height
|
58
68
|
|
69
|
+
def on_removal(self, child_widget: Widget) -> None:
|
70
|
+
child_widget.set_autoresize_h(False)
|
71
|
+
|
59
72
|
def evaluate(self, parent_widget, child_widget):
|
60
|
-
|
73
|
+
res = child_widget.rect.h >= self.min_height
|
74
|
+
if not res:
|
75
|
+
child_widget.set_autoresize_w(False)
|
76
|
+
return res
|
61
77
|
|
62
78
|
def apply_constraint(self, parent_widget, child_widget):
|
63
79
|
child_widget.set_size((None, self.min_height))
|
@@ -70,9 +86,60 @@ class MinHeight(Constraint):
|
|
70
86
|
other.min_height == self.min_height
|
71
87
|
)
|
72
88
|
|
89
|
+
class MaxWidth(Constraint):
|
90
|
+
def __init__(self, width: float):
|
91
|
+
super().__init__()
|
92
|
+
self.max_width = width
|
93
|
+
|
94
|
+
def on_removal(self, child_widget: Widget) -> None:
|
95
|
+
child_widget.set_autoresize_w(False)
|
96
|
+
|
97
|
+
def evaluate(self, parent_widget, child_widget):
|
98
|
+
res = child_widget.rect.width <= self.max_width
|
99
|
+
if not res:
|
100
|
+
child_widget.set_autoresize_w(False)
|
101
|
+
return res
|
102
|
+
|
103
|
+
def apply_constraint(self, parent_widget, child_widget):
|
104
|
+
child_widget.set_autoresize_w(True)
|
105
|
+
current_height = child_widget.rect.height
|
106
|
+
child_widget.set_size((self.max_width, current_height))
|
107
|
+
|
108
|
+
def __eq__(self, other: "Constraint") -> bool:
|
109
|
+
if not isinstance(other, self.__class__):
|
110
|
+
return False
|
111
|
+
return other.max_width == self.max_width
|
112
|
+
|
113
|
+
|
114
|
+
class MaxHeight(Constraint):
|
115
|
+
def __init__(self, height: float):
|
116
|
+
super().__init__()
|
117
|
+
self.max_height = height
|
118
|
+
|
119
|
+
def on_removal(self, child_widget: Widget) -> None:
|
120
|
+
child_widget.set_autoresize_h(False)
|
121
|
+
|
122
|
+
def evaluate(self, parent_widget, child_widget):
|
123
|
+
res = child_widget.rect.height <= self.max_height
|
124
|
+
if not res:
|
125
|
+
child_widget.set_autoresize_h(False)
|
126
|
+
return res
|
127
|
+
|
128
|
+
def apply_constraint(self, parent_widget, child_widget):
|
129
|
+
child_widget.set_autoresize_h(True)
|
130
|
+
current_width = child_widget.rect.width
|
131
|
+
child_widget.set_size((current_width, self.max_height))
|
132
|
+
|
133
|
+
def __eq__(self, other: "Constraint") -> bool:
|
134
|
+
if not isinstance(other, self.__class__):
|
135
|
+
return False
|
136
|
+
return other.max_height == self.max_height
|
137
|
+
|
138
|
+
|
139
|
+
|
73
140
|
class CenterX(Constraint):
|
74
141
|
def __init__(self):
|
75
|
-
super().__init__(
|
142
|
+
super().__init__()
|
76
143
|
|
77
144
|
def evaluate(self, parent_widget, child_widget):
|
78
145
|
return (
|
@@ -87,7 +154,7 @@ class CenterX(Constraint):
|
|
87
154
|
|
88
155
|
class CenterY(Constraint):
|
89
156
|
def __init__(self):
|
90
|
-
super().__init__(
|
157
|
+
super().__init__()
|
91
158
|
|
92
159
|
def evaluate(self, parent_widget, child_widget):
|
93
160
|
return (
|
@@ -102,7 +169,7 @@ class CenterY(Constraint):
|
|
102
169
|
|
103
170
|
class Center(Constraint):
|
104
171
|
def __init__(self):
|
105
|
-
super().__init__(
|
172
|
+
super().__init__()
|
106
173
|
|
107
174
|
def evaluate(self, parent_widget, child_widget):
|
108
175
|
return (
|
@@ -117,10 +184,13 @@ class Center(Constraint):
|
|
117
184
|
|
118
185
|
class PercentageWidth(Constraint):
|
119
186
|
def __init__(self, percentage: float, keep_autoresize: bool = False):
|
120
|
-
super().__init__(
|
187
|
+
super().__init__()
|
121
188
|
self.percentage: float = percentage
|
122
189
|
self.keep_autoresize: bool = keep_autoresize
|
123
190
|
|
191
|
+
def on_removal(self, child_widget: Widget) -> None:
|
192
|
+
child_widget.set_autoresize_w(True)
|
193
|
+
|
124
194
|
def __str__(self) -> str:
|
125
195
|
return f"{super().__str__()}.[{self.percentage*100}%,keep_autoresize={self.keep_autoresize}]"
|
126
196
|
|
@@ -153,10 +223,13 @@ class PercentageWidth(Constraint):
|
|
153
223
|
|
154
224
|
class PercentageHeight(Constraint):
|
155
225
|
def __init__(self, percentage: float, keep_autoresize: bool = False):
|
156
|
-
super().__init__(
|
226
|
+
super().__init__()
|
157
227
|
self.percentage: float = percentage
|
158
228
|
self.keep_autoresize: bool = keep_autoresize
|
159
229
|
|
230
|
+
def on_removal(self, child_widget: Widget) -> None:
|
231
|
+
child_widget.set_autoresize_h(True)
|
232
|
+
|
160
233
|
def evaluate(self, parent_widget, child_widget):
|
161
234
|
return child_widget.rect.height == round(
|
162
235
|
parent_widget.get_padded_height() * self.percentage
|
@@ -188,7 +261,7 @@ class PercentageHeight(Constraint):
|
|
188
261
|
class FillX(PercentageWidth):
|
189
262
|
def __init__(self, keep_autoresize: bool = False):
|
190
263
|
super().__init__(1, keep_autoresize)
|
191
|
-
self.name = "
|
264
|
+
self.name = "FillX"
|
192
265
|
|
193
266
|
def __eq__(self, other: Constraint) -> bool:
|
194
267
|
return Constraint.__eq__(self,other)
|
@@ -196,7 +269,7 @@ class FillX(PercentageWidth):
|
|
196
269
|
class FillY(PercentageHeight):
|
197
270
|
def __init__(self, keep_autoresize: bool = False):
|
198
271
|
super().__init__(1, keep_autoresize)
|
199
|
-
self.name = "
|
272
|
+
self.name = "FillY"
|
200
273
|
|
201
274
|
def __eq__(self, other: Constraint) -> bool:
|
202
275
|
return Constraint.__eq__(self,other)
|
@@ -204,10 +277,13 @@ class FillY(PercentageHeight):
|
|
204
277
|
|
205
278
|
class PercentageRectHeight(Constraint):
|
206
279
|
def __init__(self, percentage: float, keep_autoresize: bool = False):
|
207
|
-
super().__init__(
|
280
|
+
super().__init__()
|
208
281
|
self.percentage: float = percentage
|
209
282
|
self.keep_autoresize: bool = keep_autoresize
|
210
283
|
|
284
|
+
def on_removal(self, child_widget: Widget) -> None:
|
285
|
+
child_widget.set_autoresize_h(True)
|
286
|
+
|
211
287
|
def evaluate(self, parent_widget, child_widget):
|
212
288
|
return child_widget.rect.height == round(
|
213
289
|
parent_widget.rect.height * self.percentage
|
@@ -238,10 +314,13 @@ class PercentageRectHeight(Constraint):
|
|
238
314
|
|
239
315
|
class PercentageRectWidth(Constraint):
|
240
316
|
def __init__(self, percentage: float, keep_autoresize: bool = False):
|
241
|
-
super().__init__(
|
317
|
+
super().__init__()
|
242
318
|
self.percentage: float = percentage
|
243
319
|
self.keep_autoresize: bool = keep_autoresize
|
244
320
|
|
321
|
+
def on_removal(self, child_widget: Widget) -> None:
|
322
|
+
child_widget.set_autoresize_w(True)
|
323
|
+
|
245
324
|
def evaluate(self, parent_widget, child_widget):
|
246
325
|
return child_widget.rect.width == round(
|
247
326
|
parent_widget.rect.width * self.percentage
|
@@ -287,7 +366,7 @@ class AspectRatio(Constraint):
|
|
287
366
|
reference_axis: bf.axis = bf.axis.HORIZONTAL,
|
288
367
|
keep_autoresize=False,
|
289
368
|
):
|
290
|
-
super().__init__(
|
369
|
+
super().__init__()
|
291
370
|
self.ref_axis: bf.axis = reference_axis
|
292
371
|
self.keep_autoresize: bool = keep_autoresize
|
293
372
|
|
@@ -302,6 +381,10 @@ class AspectRatio(Constraint):
|
|
302
381
|
else:
|
303
382
|
raise TypeError(f"Ratio must be float or FRect")
|
304
383
|
|
384
|
+
def on_removal(self, child_widget: Widget) -> None:
|
385
|
+
child_widget.set_autoresize(True)
|
386
|
+
|
387
|
+
|
305
388
|
def evaluate(self, parent_widget, child_widget):
|
306
389
|
if self.ref_axis == bf.axis.HORIZONTAL:
|
307
390
|
return self.ratio == child_widget.rect.h / child_widget.rect.w
|
@@ -343,7 +426,7 @@ class AspectRatio(Constraint):
|
|
343
426
|
|
344
427
|
class AnchorBottom(Constraint):
|
345
428
|
def __init__(self):
|
346
|
-
super().__init__(
|
429
|
+
super().__init__()
|
347
430
|
|
348
431
|
def evaluate(self, parent_widget, child_widget):
|
349
432
|
return (
|
@@ -358,7 +441,7 @@ class AnchorBottom(Constraint):
|
|
358
441
|
|
359
442
|
class AnchorTop(Constraint):
|
360
443
|
def __init__(self):
|
361
|
-
super().__init__(
|
444
|
+
super().__init__()
|
362
445
|
|
363
446
|
def evaluate(self, parent_widget, child_widget):
|
364
447
|
return (child_widget.rect.top == parent_widget.get_padded_top())
|
@@ -369,21 +452,21 @@ class AnchorTop(Constraint):
|
|
369
452
|
|
370
453
|
class AnchorTopRight(Constraint):
|
371
454
|
def __init__(self):
|
372
|
-
super().__init__(
|
455
|
+
super().__init__()
|
373
456
|
|
374
457
|
def evaluate(self, parent_widget, child_widget):
|
375
458
|
return child_widget.rect.topright == parent_widget.get_padded_rect().topright
|
376
459
|
|
377
460
|
def apply_constraint(self, parent_widget, child_widget):
|
378
|
-
child_widget.
|
379
|
-
|
380
|
-
|
381
|
-
)
|
461
|
+
# print("before",child_widget.rect.topright, parent_widget.get_padded_rect().topright)
|
462
|
+
topright = parent_widget.get_padded_rect().topright
|
463
|
+
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)
|
382
465
|
|
383
466
|
|
384
467
|
class AnchorBottomRight(Constraint):
|
385
468
|
def __init__(self):
|
386
|
-
super().__init__(
|
469
|
+
super().__init__()
|
387
470
|
|
388
471
|
def evaluate(self, parent_widget, child_widget):
|
389
472
|
return (
|
@@ -391,15 +474,17 @@ class AnchorBottomRight(Constraint):
|
|
391
474
|
)
|
392
475
|
|
393
476
|
def apply_constraint(self, parent_widget, child_widget):
|
477
|
+
bottomright = parent_widget.get_padded_rect().bottomright
|
478
|
+
|
394
479
|
child_widget.set_position(
|
395
|
-
|
396
|
-
|
480
|
+
bottomright[0] - child_widget.rect.w,
|
481
|
+
bottomright[1] - child_widget.rect.h,
|
397
482
|
)
|
398
483
|
|
399
484
|
|
400
485
|
class AnchorRight(Constraint):
|
401
486
|
def __init__(self):
|
402
|
-
super().__init__(
|
487
|
+
super().__init__()
|
403
488
|
|
404
489
|
def evaluate(self, parent_widget, child_widget):
|
405
490
|
return child_widget.rect.right == parent_widget.get_padded_right()
|
@@ -413,7 +498,7 @@ class AnchorRight(Constraint):
|
|
413
498
|
|
414
499
|
class AnchorLeft(Constraint):
|
415
500
|
def __init__(self):
|
416
|
-
super().__init__(
|
501
|
+
super().__init__()
|
417
502
|
|
418
503
|
def evaluate(self, parent_widget, child_widget):
|
419
504
|
return child_widget.rect.left == parent_widget.get_padded_left()
|
@@ -426,7 +511,7 @@ class AnchorLeft(Constraint):
|
|
426
511
|
|
427
512
|
class MarginBottom(Constraint):
|
428
513
|
def __init__(self, margin: float):
|
429
|
-
super().__init__(
|
514
|
+
super().__init__()
|
430
515
|
self.margin = margin
|
431
516
|
|
432
517
|
def evaluate(self, parent_widget, child_widget):
|
@@ -450,7 +535,7 @@ class MarginBottom(Constraint):
|
|
450
535
|
|
451
536
|
class MarginTop(Constraint):
|
452
537
|
def __init__(self, margin: float):
|
453
|
-
super().__init__(
|
538
|
+
super().__init__()
|
454
539
|
self.margin = margin
|
455
540
|
|
456
541
|
def evaluate(self, parent_widget, child_widget):
|
@@ -471,7 +556,7 @@ class MarginTop(Constraint):
|
|
471
556
|
|
472
557
|
class MarginLeft(Constraint):
|
473
558
|
def __init__(self, margin: float):
|
474
|
-
super().__init__(
|
559
|
+
super().__init__()
|
475
560
|
self.margin = margin
|
476
561
|
|
477
562
|
def evaluate(self, parent_widget, child_widget):
|
@@ -493,7 +578,7 @@ class MarginLeft(Constraint):
|
|
493
578
|
|
494
579
|
class MarginRight(Constraint):
|
495
580
|
def __init__(self, margin: float):
|
496
|
-
super().__init__(
|
581
|
+
super().__init__()
|
497
582
|
self.margin = margin
|
498
583
|
|
499
584
|
def evaluate(self, parent_widget, child_widget):
|
@@ -515,7 +600,7 @@ class MarginRight(Constraint):
|
|
515
600
|
|
516
601
|
class PercentageMarginBottom(Constraint):
|
517
602
|
def __init__(self, margin: float):
|
518
|
-
super().__init__(
|
603
|
+
super().__init__()
|
519
604
|
self.margin = margin
|
520
605
|
|
521
606
|
def evaluate(self, parent_widget, child_widget):
|
@@ -543,7 +628,7 @@ class PercentageMarginBottom(Constraint):
|
|
543
628
|
|
544
629
|
class PercentageMarginTop(Constraint):
|
545
630
|
def __init__(self, margin: float):
|
546
|
-
super().__init__(
|
631
|
+
super().__init__()
|
547
632
|
self.margin = margin
|
548
633
|
|
549
634
|
def evaluate(self, parent_widget, child_widget):
|
@@ -570,7 +655,7 @@ class PercentageMarginTop(Constraint):
|
|
570
655
|
|
571
656
|
class PercentageMarginLeft(Constraint):
|
572
657
|
def __init__(self, margin: float):
|
573
|
-
super().__init__(
|
658
|
+
super().__init__()
|
574
659
|
self.margin = margin
|
575
660
|
|
576
661
|
def evaluate(self, parent_widget, child_widget):
|
@@ -598,7 +683,7 @@ class PercentageMarginLeft(Constraint):
|
|
598
683
|
|
599
684
|
class PercentageMarginRight(Constraint):
|
600
685
|
def __init__(self, margin: float):
|
601
|
-
super().__init__(
|
686
|
+
super().__init__()
|
602
687
|
self.margin = margin
|
603
688
|
|
604
689
|
def evaluate(self, parent_widget, child_widget):
|
@@ -626,7 +711,7 @@ class PercentageMarginRight(Constraint):
|
|
626
711
|
|
627
712
|
class PercentageRectMarginBottom(Constraint):
|
628
713
|
def __init__(self, margin: float):
|
629
|
-
super().__init__(
|
714
|
+
super().__init__()
|
630
715
|
self.margin = margin
|
631
716
|
|
632
717
|
def evaluate(self, parent_widget, child_widget):
|
@@ -653,7 +738,7 @@ class PercentageRectMarginBottom(Constraint):
|
|
653
738
|
|
654
739
|
class PercentageRectMarginTop(Constraint):
|
655
740
|
def __init__(self, margin: float):
|
656
|
-
super().__init__(
|
741
|
+
super().__init__()
|
657
742
|
self.margin = margin
|
658
743
|
|
659
744
|
def evaluate(self, parent_widget, child_widget):
|
@@ -678,7 +763,7 @@ class PercentageRectMarginTop(Constraint):
|
|
678
763
|
|
679
764
|
class PercentageRectMarginLeft(Constraint):
|
680
765
|
def __init__(self, margin: float):
|
681
|
-
super().__init__(
|
766
|
+
super().__init__()
|
682
767
|
self.margin = margin
|
683
768
|
|
684
769
|
def evaluate(self, parent_widget, child_widget):
|
@@ -704,7 +789,7 @@ class PercentageRectMarginLeft(Constraint):
|
|
704
789
|
|
705
790
|
class PercentageRectMarginRight(Constraint):
|
706
791
|
def __init__(self, margin: float):
|
707
|
-
super().__init__(
|
792
|
+
super().__init__()
|
708
793
|
self.margin = margin
|
709
794
|
|
710
795
|
def evaluate(self, parent_widget, child_widget):
|
batFramework/gui/image.py
CHANGED
@@ -21,15 +21,22 @@ class Image(Shape):
|
|
21
21
|
|
22
22
|
def paint(self) -> None:
|
23
23
|
super().paint()
|
24
|
-
# self.surface.fill((0,0,0,0 if self.convert_alpha else 255))
|
25
24
|
if self.original_surface is None:
|
26
25
|
return
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
)
|
26
|
+
padded = self.get_padded_rect().move(-self.rect.x,-self.rect.y)
|
27
|
+
target_size = padded.size
|
28
|
+
if self.original_surface.get_size() != target_size:
|
29
|
+
self.surface.blit(pygame.transform.scale(self.original_surface, target_size), padded.topleft)
|
31
30
|
else:
|
32
|
-
self.surface.blit(self.original_surface,
|
31
|
+
self.surface.blit(self.original_surface, padded.topleft)
|
32
|
+
|
33
|
+
def build(self) -> None:
|
34
|
+
if self.original_surface is not None:
|
35
|
+
self.set_size_if_autoresize(
|
36
|
+
self.inflate_rect_by_padding((0,0,*self.original_surface.get_size())).size
|
37
|
+
)
|
38
|
+
super().build()
|
39
|
+
|
33
40
|
|
34
41
|
def from_path(self, path: str) -> Self:
|
35
42
|
tmp = bf.ResourceManager().get_image(path, self.convert_alpha)
|
@@ -37,10 +44,6 @@ class Image(Shape):
|
|
37
44
|
return self
|
38
45
|
self.original_surface = tmp
|
39
46
|
size = self.original_surface.get_size()
|
40
|
-
if not self.autoresize_h:
|
41
|
-
size[0] = None
|
42
|
-
if not self.autoresize_h:
|
43
|
-
size[1] = None
|
44
47
|
self.set_size(size)
|
45
48
|
self.dirty_surface = True
|
46
49
|
return self
|
@@ -50,10 +53,7 @@ class Image(Shape):
|
|
50
53
|
return self
|
51
54
|
self.original_surface = surface
|
52
55
|
size = self.original_surface.get_size()
|
53
|
-
if not self.autoresize_h:
|
54
|
-
size[0] = None
|
55
|
-
if not self.autoresize_h:
|
56
|
-
size[1] = None
|
57
56
|
self.set_size(size)
|
57
|
+
|
58
58
|
self.dirty_surface = True
|
59
59
|
return self
|
@@ -8,6 +8,14 @@ if TYPE_CHECKING:
|
|
8
8
|
from .container import Container
|
9
9
|
import batFramework as bf
|
10
10
|
|
11
|
+
def children_has_focus(widget):
|
12
|
+
if isinstance(widget,InteractiveWidget) and widget.is_focused:
|
13
|
+
return True
|
14
|
+
for child in widget.children:
|
15
|
+
if children_has_focus(child):
|
16
|
+
return True
|
17
|
+
return False
|
18
|
+
|
11
19
|
|
12
20
|
class InteractiveWidget(Widget):
|
13
21
|
def __init__(self, *args, **kwargs) -> None:
|
@@ -39,6 +47,13 @@ class InteractiveWidget(Widget):
|
|
39
47
|
return True
|
40
48
|
return False
|
41
49
|
|
50
|
+
def set_parent(self, parent: Widget) -> Self:
|
51
|
+
if parent is None and children_has_focus(self):
|
52
|
+
self.get_root().clear_focused()
|
53
|
+
# pass focus on
|
54
|
+
|
55
|
+
return super().set_parent(parent)
|
56
|
+
|
42
57
|
def on_get_focus(self) -> None:
|
43
58
|
self.is_focused = True
|
44
59
|
self.do_on_get_focus()
|
batFramework/gui/label.py
CHANGED
@@ -2,7 +2,7 @@ import batFramework as bf
|
|
2
2
|
import pygame
|
3
3
|
from .shape import Shape
|
4
4
|
from typing import Self
|
5
|
-
|
5
|
+
from math import ceil
|
6
6
|
|
7
7
|
class Label(Shape):
|
8
8
|
_text_cache = {}
|
@@ -59,7 +59,7 @@ class Label(Shape):
|
|
59
59
|
Label._text_cache = {}
|
60
60
|
|
61
61
|
def __str__(self) -> str:
|
62
|
-
return f"Label({self.text})"
|
62
|
+
return f"Label({repr(self.text)})"
|
63
63
|
|
64
64
|
def enable_caching(self) -> Self:
|
65
65
|
self.do_caching = True
|
@@ -106,6 +106,7 @@ class Label(Shape):
|
|
106
106
|
m = [[self._text_outline_mask.get_at((x,y)) for x in range(min(old_size[0],size[0]))] for y in range(min(old_size[1],size[1]))]
|
107
107
|
self._text_outline_mask = pygame.Mask(size, fill=True)
|
108
108
|
self.set_text_outline_matrix(m)
|
109
|
+
return self
|
109
110
|
|
110
111
|
def set_text_outline_matrix(self, matrix: list[list[0 | 1]]) -> Self:
|
111
112
|
if matrix is None:
|
@@ -113,7 +114,7 @@ class Label(Shape):
|
|
113
114
|
for y in range(3):
|
114
115
|
for x in range(3):
|
115
116
|
self._text_outline_mask.set_at((x, y), matrix[2 - y][2 - x])
|
116
|
-
self.
|
117
|
+
self.dirty_shape = True
|
117
118
|
return self
|
118
119
|
|
119
120
|
def set_text_outline_color(self, color) -> Self:
|
@@ -123,12 +124,12 @@ class Label(Shape):
|
|
123
124
|
|
124
125
|
def enable_text_outline(self) -> Self:
|
125
126
|
self.show_text_outline = True
|
126
|
-
self.
|
127
|
+
self.dirty_shape = True
|
127
128
|
return self
|
128
129
|
|
129
130
|
def disable_text_outline(self) -> Self:
|
130
131
|
self.show_text_outline = False
|
131
|
-
self.
|
132
|
+
self.dirty_shape = True
|
132
133
|
return self
|
133
134
|
|
134
135
|
def set_alignment(self, alignment: bf.alignment) -> Self:
|
@@ -146,7 +147,8 @@ class Label(Shape):
|
|
146
147
|
|
147
148
|
def get_debug_outlines(self):
|
148
149
|
if self.visible:
|
149
|
-
|
150
|
+
offset = self._get_outline_offset() if self.show_text_outline else (0,0)
|
151
|
+
yield (self.text_rect.move(self.rect.x - offset[0],self.rect.y - offset[1]), "purple")
|
150
152
|
yield from super().get_debug_outlines()
|
151
153
|
|
152
154
|
def set_font(self, font_name: str = None, force: bool = False) -> Self:
|
@@ -194,7 +196,8 @@ class Label(Shape):
|
|
194
196
|
if not self.text_rect:
|
195
197
|
self.text_rect.size = self._get_text_rect_required_size()
|
196
198
|
res = self.inflate_rect_by_padding((0, 0, *self.text_rect.size)).size
|
197
|
-
|
199
|
+
|
200
|
+
return res
|
198
201
|
return res[0] if self.autoresize_w else self.rect.w, (
|
199
202
|
res[1] if self.autoresize_h else self.rect.h
|
200
203
|
)
|
@@ -238,22 +241,34 @@ class Label(Shape):
|
|
238
241
|
|
239
242
|
return surf
|
240
243
|
def _get_text_rect_required_size(self):
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
244
|
+
font_height = self.font_object.get_linesize()
|
245
|
+
if not self.text:
|
246
|
+
# font_height = self.font_object.get_ascent() - self.font_object.get_ascent()
|
247
|
+
size = (0,font_height)
|
248
|
+
else:
|
249
|
+
tmp_text = self.text
|
250
|
+
if self.text.endswith('\n'):
|
251
|
+
tmp_text+=" "
|
252
|
+
params = {
|
253
|
+
"font_name": self.font_object.name,
|
254
|
+
"text": tmp_text,
|
255
|
+
"antialias": self.antialias,
|
256
|
+
"color": self.text_color,
|
257
|
+
"bgcolor": None, # if (self.has_alpha_color() or self.draw_mode == bf.drawMode.TEXTURED) else self.color,
|
258
|
+
"wraplength": int(self.get_padded_width()) if self.auto_wraplength and not self.autoresize_w else 0,
|
259
|
+
}
|
260
|
+
|
261
|
+
size = self._render_font(params).get_size()
|
262
|
+
size = size[0],max(font_height,size[1])
|
263
|
+
s = self._get_outline_offset() if self.show_text_outline else (0,0)
|
264
|
+
return size[0] + s[0]*2, size[1] + s[1]*2
|
249
265
|
|
250
|
-
size = self._render_font(params).get_size()
|
251
|
-
s = self._text_outline_mask.get_size()
|
252
|
-
return size[0] + s[0]//2, size[1] + s[1]//2
|
253
266
|
def _build_layout(self) -> None:
|
254
267
|
|
255
268
|
self.text_rect.size = self._get_text_rect_required_size()
|
256
|
-
|
269
|
+
# self.text_rect.w = ceil(self.text_rect.w)
|
270
|
+
# self.text_rect.h = ceil(self.text_rect.h)
|
271
|
+
|
257
272
|
if self.autoresize_h or self.autoresize_w:
|
258
273
|
target_rect = self.inflate_rect_by_padding((0, 0, *self.text_rect.size))
|
259
274
|
if not self.autoresize_w:
|
@@ -264,7 +279,8 @@ class Label(Shape):
|
|
264
279
|
self.set_size(target_rect.size)
|
265
280
|
self.build()
|
266
281
|
return
|
267
|
-
|
282
|
+
offset = self._get_outline_offset() if self.show_text_outline else (0,0)
|
283
|
+
padded = self.get_padded_rect().move(-self.rect.x + offset[0], -self.rect.y + offset[1])
|
268
284
|
self.align_text(self.text_rect, padded, self.alignment)
|
269
285
|
|
270
286
|
def _get_outline_offset(self)->tuple[int,int]:
|
@@ -282,8 +298,9 @@ class Label(Shape):
|
|
282
298
|
"antialias": self.antialias,
|
283
299
|
"color": self.text_color,
|
284
300
|
"bgcolor": None, # if (self.has_alpha_color() or self.draw_mode == bf.drawMode.TEXTURED) else self.color,
|
285
|
-
"wraplength": int(self.get_padded_width()) if self.auto_wraplength else 0,
|
301
|
+
"wraplength": int(self.get_padded_width()) if self.auto_wraplength and not self.autoresize_w else 0,
|
286
302
|
}
|
303
|
+
|
287
304
|
self.text_surface = self._render_font(params)
|
288
305
|
|
289
306
|
if self.show_text_outline:
|
@@ -294,16 +311,15 @@ class Label(Shape):
|
|
294
311
|
)
|
295
312
|
|
296
313
|
l = []
|
297
|
-
outline_offset = self._get_outline_offset()
|
314
|
+
outline_offset = self._get_outline_offset() if self.show_text_outline else (0,0)
|
315
|
+
|
298
316
|
if self.show_text_outline:
|
299
317
|
l.append(
|
300
|
-
(
|
301
|
-
|
302
|
-
self.text_rect.move(0, self.relief - self.get_relief()),
|
303
|
-
)
|
318
|
+
(self.text_outline_surface,
|
319
|
+
(self.text_rect.x - outline_offset[0],self.text_rect.y - outline_offset[1]))
|
304
320
|
)
|
305
321
|
l.append(
|
306
|
-
(self.text_surface, self.text_rect
|
322
|
+
(self.text_surface, self.text_rect)
|
307
323
|
)
|
308
324
|
self.surface.fblits(l)
|
309
325
|
|
@@ -317,6 +333,7 @@ class Label(Shape):
|
|
317
333
|
|
318
334
|
pos = area.__getattribute__(alignment.value)
|
319
335
|
text_rect.__setattr__(alignment.value, pos)
|
336
|
+
text_rect.y = ceil(text_rect.y)
|
320
337
|
|
321
338
|
def build(self) -> None:
|
322
339
|
super().build()
|