batframework 1.0.9a10__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.
Files changed (73) hide show
  1. batFramework/__init__.py +2 -0
  2. batFramework/action.py +280 -279
  3. batFramework/actionContainer.py +105 -82
  4. batFramework/animatedSprite.py +80 -58
  5. batFramework/animation.py +91 -77
  6. batFramework/audioManager.py +156 -131
  7. batFramework/baseScene.py +249 -240
  8. batFramework/camera.py +245 -317
  9. batFramework/constants.py +57 -51
  10. batFramework/cutscene.py +239 -253
  11. batFramework/cutsceneManager.py +34 -34
  12. batFramework/drawable.py +107 -77
  13. batFramework/dynamicEntity.py +30 -30
  14. batFramework/easingController.py +58 -58
  15. batFramework/entity.py +130 -130
  16. batFramework/enums.py +171 -135
  17. batFramework/fontManager.py +65 -65
  18. batFramework/gui/__init__.py +28 -25
  19. batFramework/gui/animatedLabel.py +90 -89
  20. batFramework/gui/button.py +17 -17
  21. batFramework/gui/clickableWidget.py +244 -245
  22. batFramework/gui/collapseContainer.py +98 -0
  23. batFramework/gui/constraints/__init__.py +1 -1
  24. batFramework/gui/constraints/constraints.py +1066 -980
  25. batFramework/gui/container.py +220 -201
  26. batFramework/gui/debugger.py +140 -130
  27. batFramework/gui/draggableWidget.py +63 -44
  28. batFramework/gui/image.py +61 -58
  29. batFramework/gui/indicator.py +116 -113
  30. batFramework/gui/interactiveWidget.py +243 -239
  31. batFramework/gui/label.py +147 -344
  32. batFramework/gui/layout.py +442 -426
  33. batFramework/gui/meter.py +155 -96
  34. batFramework/gui/radioButton.py +43 -35
  35. batFramework/gui/root.py +228 -228
  36. batFramework/gui/scrollingContainer.py +282 -0
  37. batFramework/gui/selector.py +232 -250
  38. batFramework/gui/shape.py +286 -276
  39. batFramework/gui/slider.py +353 -397
  40. batFramework/gui/style.py +10 -10
  41. batFramework/gui/styleManager.py +49 -54
  42. batFramework/gui/syncedVar.py +43 -49
  43. batFramework/gui/textInput.py +331 -306
  44. batFramework/gui/textWidget.py +308 -0
  45. batFramework/gui/toggle.py +140 -128
  46. batFramework/gui/tooltip.py +35 -30
  47. batFramework/gui/widget.py +546 -521
  48. batFramework/manager.py +131 -134
  49. batFramework/particle.py +118 -118
  50. batFramework/propertyEaser.py +79 -79
  51. batFramework/renderGroup.py +34 -34
  52. batFramework/resourceManager.py +130 -130
  53. batFramework/scene.py +31 -31
  54. batFramework/sceneLayer.py +134 -138
  55. batFramework/sceneManager.py +200 -197
  56. batFramework/scrollingSprite.py +115 -115
  57. batFramework/sprite.py +46 -51
  58. batFramework/stateMachine.py +49 -54
  59. batFramework/templates/__init__.py +2 -1
  60. batFramework/templates/character.py +15 -0
  61. batFramework/templates/controller.py +158 -97
  62. batFramework/templates/stateMachine.py +39 -0
  63. batFramework/tileset.py +46 -46
  64. batFramework/timeManager.py +213 -213
  65. batFramework/transition.py +162 -162
  66. batFramework/triggerZone.py +22 -22
  67. batFramework/utils.py +306 -306
  68. {batframework-1.0.9a10.dist-info → batframework-1.0.9a12.dist-info}/LICENSE +20 -20
  69. {batframework-1.0.9a10.dist-info → batframework-1.0.9a12.dist-info}/METADATA +24 -17
  70. batframework-1.0.9a12.dist-info/RECORD +72 -0
  71. batframework-1.0.9a10.dist-info/RECORD +0 -67
  72. {batframework-1.0.9a10.dist-info → batframework-1.0.9a12.dist-info}/WHEEL +0 -0
  73. {batframework-1.0.9a10.dist-info → batframework-1.0.9a12.dist-info}/top_level.txt +0 -0
@@ -1,245 +1,244 @@
1
- import batFramework as bf
2
- from typing import Self, Callable, Any
3
- from .interactiveWidget import InteractiveWidget
4
- from .shape import Shape
5
- import pygame
6
-
7
-
8
- class ClickableWidget(Shape, InteractiveWidget):
9
- _cache: dict = {}
10
-
11
- def __init__(self, callback: Callable[[],Any] = None, *args, **kwargs) -> None:
12
- super().__init__(*args, **kwargs)
13
- self.callback = callback
14
- self.is_pressed: bool = False # the state where the button is being held down (releasing will trigger callback)
15
- self.is_enabled: bool = True #
16
- self.hover_cursor = bf.const.DEFAULT_HOVER_CURSOR
17
- self.click_cursor = bf.const.DEFAULT_CLICK_CURSOR
18
-
19
- self.click_down_sound = None
20
- self.click_up_sound = None
21
- self.get_focus_sound = None
22
- self.lose_focus_sound = None
23
-
24
- self.pressed_relief: int = 1 # Depth effect height when pressed
25
- self.unpressed_relief: int = 2 # Depth effect height when released (default)
26
- self.silent_focus: bool = False
27
- self.set_debug_color("cyan")
28
- self.set_relief(self.unpressed_relief)
29
-
30
-
31
- def get_min_required_size(self) -> tuple[float, float]:
32
- res = super().get_min_required_size()
33
- res = res[0],res[1]+self.unpressed_relief
34
- return res
35
-
36
- def set_unpressed_relief(self, relief: int) -> Self:
37
- if relief == self.unpressed_relief:
38
- return self
39
- self.unpressed_relief = relief
40
- self.dirty_shape = True
41
- if not self.is_pressed:
42
- self.set_relief(relief)
43
- return self
44
-
45
- def set_pressed_relief(self, relief: int) -> Self:
46
- if relief == self.pressed_relief:
47
- return self
48
- self.pressed_relief = relief
49
- self.dirty_shape = True
50
- if self.is_pressed:
51
- self.set_relief(relief)
52
- return self
53
-
54
- def set_silent_focus(self, value: bool) -> Self:
55
- self.silent_focus = value
56
- return self
57
-
58
- def set_click_down_sound(self, sound_name: str) -> Self:
59
- self.click_down_sound = sound_name
60
- return self
61
-
62
- def set_click_up_sound(self, sound_name: str) -> Self:
63
- self.click_up_sound = sound_name
64
- return self
65
-
66
- def set_get_focus_sound(self, sound_name: str) -> Self:
67
- self.get_focus_sound = sound_name
68
- return self
69
-
70
- def set_lose_focus_sound(self, sound_name: str) -> Self:
71
- self.lose_focus_sound = sound_name
72
- return self
73
-
74
- def set_hover_cursor(self, cursor: pygame.Cursor) -> Self:
75
- self.hover_cursor = cursor
76
- return self
77
-
78
- def set_click_cursor(self, cursor: pygame.Cursor) -> Self:
79
- self.click_cursor = cursor
80
- return self
81
-
82
- def get_surface_filter(self) -> pygame.Surface | None:
83
- size = int(self.rect.w), int(self.rect.h)
84
- surface_filter = ClickableWidget._cache.get((size, *self.border_radius), None)
85
- if surface_filter is None:
86
- # Create a mask from the original surface
87
- mask = pygame.mask.from_surface(self.surface, threshold=0)
88
-
89
- silhouette_surface = mask.to_surface(
90
- setcolor=(30, 30, 30), unsetcolor=(0, 0, 0)
91
- )
92
-
93
- ClickableWidget._cache[(size, *self.border_radius)] = silhouette_surface
94
-
95
- surface_filter = silhouette_surface
96
-
97
- return surface_filter
98
-
99
- def allow_focus_to_self(self) -> bool:
100
- return True
101
-
102
- def enable(self) -> Self:
103
- self.is_enabled = True
104
- self.dirty_surface = True
105
- return self
106
-
107
- def disable(self) -> Self:
108
- self.is_enabled = False
109
- self.dirty_surface = True
110
- return self
111
-
112
- def set_callback(self, callback: Callable[[],Any]) -> Self:
113
- self.callback = callback
114
- return self
115
-
116
- def on_get_focus(self):
117
- super().on_get_focus()
118
- if self.get_focus_sound and not self.silent_focus:
119
- if self.parent_scene and self.parent_scene.visible:
120
- bf.AudioManager().play_sound(self.get_focus_sound)
121
- if self.silent_focus:
122
- self.silent_focus = False
123
-
124
- def on_lose_focus(self):
125
- super().on_lose_focus()
126
- if self.lose_focus_sound and not self.silent_focus:
127
- if self.parent_scene and self.parent_scene.visible:
128
- bf.AudioManager().play_sound(self.lose_focus_sound)
129
- if self.silent_focus:
130
- self.silent_focus = False
131
-
132
- def __str__(self) -> str:
133
- return f"ClickableWidget"
134
-
135
- def click(self, force=False) -> None:
136
- if not self.is_enabled and not force:
137
- return False
138
- if self.callback is not None:
139
- self.callback()
140
- return True
141
- return False
142
-
143
- def on_key_down(self, key):
144
- if key == pygame.K_SPACE:
145
- self.on_click_down(1)
146
- return True
147
- return self.do_on_key_down(key)
148
-
149
- def on_key_up(self, key):
150
- if key == pygame.K_SPACE:
151
- self.on_click_up(1)
152
- return True
153
- return self.do_on_key_down(key)
154
-
155
-
156
- def on_click_down(self, button) -> bool:
157
- if button < 1 or button > 5 : return False
158
- self.is_clicked_down[button-1] = True
159
- if self.is_enabled and button == 1:
160
- if self.get_focus():
161
- self.is_pressed = True
162
- if self.click_down_sound:
163
- bf.AudioManager().play_sound(self.click_down_sound)
164
- pygame.mouse.set_cursor(self.click_cursor)
165
- self.set_relief(self.pressed_relief)
166
- self.do_on_click_down(button)
167
- return True
168
- return False
169
-
170
- def on_click_up(self, button):
171
- if button < 1 or button > 5 : return False
172
- self.is_clicked_down[button-1] = False
173
- if self.is_enabled and button == 1 and self.is_pressed:
174
- self.is_pressed = False
175
- if self.click_up_sound:
176
- bf.AudioManager().play_sound(self.click_up_sound)
177
- self.set_relief(self.unpressed_relief)
178
- self.click()
179
- self.do_on_click_up(button)
180
- return True
181
- return False
182
-
183
-
184
- def on_enter(self) -> None:
185
- if not self.is_enabled:
186
- return
187
- super().on_enter()
188
- self.dirty_surface = True
189
- pygame.mouse.set_cursor(self.hover_cursor)
190
-
191
- def on_exit(self) -> None:
192
- super().on_exit()
193
- if self.is_pressed:
194
- self.set_relief(self.unpressed_relief)
195
- self.is_pressed = False
196
- self.dirty_surface = True
197
- pygame.mouse.set_cursor(bf.const.DEFAULT_CURSOR)
198
-
199
- def on_lose_focus(self):
200
- super().on_lose_focus()
201
- self.on_exit()
202
-
203
-
204
- def _paint_disabled(self) -> None:
205
- self.surface.blit(
206
- self.get_surface_filter(), (0, 0), special_flags=pygame.BLEND_RGB_SUB
207
- )
208
-
209
- def _paint_hovered(self) -> None:
210
- self.surface.blit(
211
- self.get_surface_filter(), (0, 0), special_flags=pygame.BLEND_RGB_ADD
212
- )
213
-
214
- def get_inner_rect(self) -> pygame.FRect:
215
- return pygame.FRect(
216
- self.rect.x + self.padding[0],
217
- self.rect.y + self.padding[1] + (self.unpressed_relief - self.pressed_relief if self.is_pressed else 0),
218
- self.rect.w - self.padding[2] - self.padding[0],
219
- self.rect.h - self.unpressed_relief - self.padding[1] - self.padding[3],
220
- )
221
-
222
- def get_local_inner_rect(self) -> pygame.FRect:
223
- return pygame.FRect(
224
- self.padding[0],
225
- self.padding[1] + (self.unpressed_relief - self.pressed_relief if self.is_pressed else 0),
226
- self.rect.w - self.padding[2] - self.padding[0],
227
- self.rect.h - self.unpressed_relief - self.padding[1] - self.padding[3],
228
- )
229
-
230
-
231
- def _get_elevated_rect(self) -> pygame.FRect:
232
- return pygame.FRect(
233
- 0,
234
- self.unpressed_relief - self.pressed_relief if self.is_pressed else 0,
235
- self.rect.w,
236
- self.rect.h - self.unpressed_relief,
237
- )
238
-
239
- def paint(self) -> None:
240
- super().paint()
241
- if not self.is_enabled:
242
- self._paint_disabled()
243
- elif self.is_hovered:
244
- self._paint_hovered()
245
-
1
+ import batFramework as bf
2
+ from typing import Self, Callable, Any
3
+ from .interactiveWidget import InteractiveWidget
4
+ from .shape import Shape
5
+ import pygame
6
+
7
+
8
+ class ClickableWidget(Shape, InteractiveWidget):
9
+ _cache: dict = {}
10
+
11
+ def __init__(self, callback: Callable[[],Any] = None, *args, **kwargs) -> None:
12
+ super().__init__(*args, **kwargs)
13
+ self.callback = callback
14
+ self.is_pressed: bool = False # the state where the button is being held down (releasing will trigger callback)
15
+ self.is_enabled: bool = True #
16
+ self.hover_cursor = bf.const.DEFAULT_HOVER_CURSOR
17
+ self.click_cursor = bf.const.DEFAULT_CLICK_CURSOR
18
+
19
+ self.click_down_sound = None
20
+ self.click_up_sound = None
21
+ self.get_focus_sound = None
22
+ self.lose_focus_sound = None
23
+
24
+ self.pressed_relief: int = 1 # Depth effect height when pressed
25
+ self.unpressed_relief: int = 2 # Depth effect height when released (default)
26
+ self.silent_focus: bool = False
27
+ self.set_debug_color("cyan")
28
+ self.set_relief(self.unpressed_relief)
29
+ self.set_click_pass_through(False)
30
+
31
+ def get_min_required_size(self) -> tuple[float, float]:
32
+ res = super().get_min_required_size()
33
+ res = res[0],res[1]+self.unpressed_relief
34
+ return res
35
+
36
+ def set_unpressed_relief(self, relief: int) -> Self:
37
+ if relief == self.unpressed_relief:
38
+ return self
39
+ self.unpressed_relief = relief
40
+ self.dirty_shape = True
41
+ if not self.is_pressed:
42
+ self.set_relief(relief)
43
+ return self
44
+
45
+ def set_pressed_relief(self, relief: int) -> Self:
46
+ if relief == self.pressed_relief:
47
+ return self
48
+ self.pressed_relief = relief
49
+ self.dirty_shape = True
50
+ if self.is_pressed:
51
+ self.set_relief(relief)
52
+ return self
53
+
54
+ def set_silent_focus(self, value: bool) -> Self:
55
+ self.silent_focus = value
56
+ return self
57
+
58
+ def set_click_down_sound(self, sound_name: str) -> Self:
59
+ self.click_down_sound = sound_name
60
+ return self
61
+
62
+ def set_click_up_sound(self, sound_name: str) -> Self:
63
+ self.click_up_sound = sound_name
64
+ return self
65
+
66
+ def set_get_focus_sound(self, sound_name: str) -> Self:
67
+ self.get_focus_sound = sound_name
68
+ return self
69
+
70
+ def set_lose_focus_sound(self, sound_name: str) -> Self:
71
+ self.lose_focus_sound = sound_name
72
+ return self
73
+
74
+ def set_hover_cursor(self, cursor: pygame.Cursor) -> Self:
75
+ self.hover_cursor = cursor
76
+ return self
77
+
78
+ def set_click_cursor(self, cursor: pygame.Cursor) -> Self:
79
+ self.click_cursor = cursor
80
+ return self
81
+
82
+ def get_surface_filter(self) -> pygame.Surface | None:
83
+ size = int(self.rect.w), int(self.rect.h)
84
+ surface_filter = ClickableWidget._cache.get((size, *self.border_radius), None)
85
+ if surface_filter is None:
86
+ # Create a mask from the original surface
87
+ mask = pygame.mask.from_surface(self.surface, threshold=0)
88
+
89
+ silhouette_surface = mask.to_surface(
90
+ setcolor=(30, 30, 30), unsetcolor=(0, 0, 0)
91
+ )
92
+
93
+ ClickableWidget._cache[(size, *self.border_radius)] = silhouette_surface
94
+
95
+ surface_filter = silhouette_surface
96
+
97
+ return surface_filter
98
+
99
+ def allow_focus_to_self(self) -> bool:
100
+ return True
101
+
102
+ def enable(self) -> Self:
103
+ self.is_enabled = True
104
+ self.dirty_surface = True
105
+ return self
106
+
107
+ def disable(self) -> Self:
108
+ self.is_enabled = False
109
+ self.dirty_surface = True
110
+ return self
111
+
112
+ def set_callback(self, callback: Callable[[],Any]) -> Self:
113
+ self.callback = callback
114
+ return self
115
+
116
+ def on_get_focus(self):
117
+ super().on_get_focus()
118
+ if self.get_focus_sound and not self.silent_focus:
119
+ if self.parent_scene and self.parent_scene.visible:
120
+ bf.AudioManager().play_sound(self.get_focus_sound)
121
+ if self.silent_focus:
122
+ self.silent_focus = False
123
+
124
+ def on_lose_focus(self):
125
+ super().on_lose_focus()
126
+ if self.lose_focus_sound and not self.silent_focus:
127
+ if self.parent_scene and self.parent_scene.visible:
128
+ bf.AudioManager().play_sound(self.lose_focus_sound)
129
+ if self.silent_focus:
130
+ self.silent_focus = False
131
+
132
+ def __str__(self) -> str:
133
+ return f"ClickableWidget"
134
+
135
+ def click(self, force=False) -> None:
136
+ if not self.is_enabled and not force:
137
+ return False
138
+ if self.callback is not None:
139
+ self.callback()
140
+ return True
141
+ return False
142
+
143
+ def on_key_down(self, key,event):
144
+ if key == pygame.K_SPACE:
145
+ self.on_click_down(1,event)
146
+ self.do_on_key_down(key,event)
147
+
148
+ def on_key_up(self, key,event):
149
+ if key == pygame.K_SPACE:
150
+ self.on_click_up(1,event)
151
+ self.do_on_key_down(key,event)
152
+
153
+ def on_click_down(self, button,event) -> None :
154
+ if button < 1 or button > 5 :
155
+ return
156
+ self.is_clicked_down[button-1] = True
157
+ if button != 1:
158
+ return
159
+ event.consumed = not self.click_pass_through
160
+ if self.is_enabled and self.get_focus():
161
+ self.is_pressed = True
162
+ if self.click_down_sound:
163
+ bf.AudioManager().play_sound(self.click_down_sound)
164
+ pygame.mouse.set_cursor(self.click_cursor)
165
+ self.set_relief(self.pressed_relief)
166
+ self.do_on_click_down(button,event)
167
+
168
+ def on_click_up(self, button,event):
169
+ if button < 1 or button > 5 :
170
+ return
171
+ self.is_clicked_down[button-1] = False
172
+ if button != 1 :
173
+ return
174
+ event.consumed = not self.click_pass_through
175
+ if self.is_enabled and self.is_pressed:
176
+ self.is_pressed = False
177
+ if self.click_up_sound:
178
+ bf.AudioManager().play_sound(self.click_up_sound)
179
+ self.set_relief(self.unpressed_relief)
180
+ self.click()
181
+ self.do_on_click_up(button,event)
182
+
183
+ def on_enter(self) -> None:
184
+ self.is_hovered = True
185
+ if not self.is_enabled:
186
+ return
187
+ super().on_enter()
188
+ self.dirty_surface = True
189
+ pygame.mouse.set_cursor(self.hover_cursor)
190
+
191
+ def on_exit(self) -> None:
192
+ super().on_exit()
193
+ if self.is_pressed:
194
+ self.set_relief(self.unpressed_relief)
195
+ self.is_pressed = False
196
+ self.dirty_surface = True
197
+ pygame.mouse.set_cursor(bf.const.DEFAULT_CURSOR)
198
+
199
+ def on_lose_focus(self):
200
+ super().on_lose_focus()
201
+ self.on_exit()
202
+
203
+ def _paint_disabled(self) -> None:
204
+ self.surface.blit(
205
+ self.get_surface_filter(), (0, 0), special_flags=pygame.BLEND_RGB_SUB
206
+ )
207
+
208
+ def _paint_hovered(self) -> None:
209
+ self.surface.blit(
210
+ self.get_surface_filter(), (0, 0), special_flags=pygame.BLEND_RGB_ADD
211
+ )
212
+
213
+ def get_inner_rect(self) -> pygame.FRect:
214
+ return pygame.FRect(
215
+ self.rect.x + self.padding[0],
216
+ self.rect.y + self.padding[1] + (self.unpressed_relief - self.pressed_relief if self.is_pressed else 0),
217
+ self.rect.w - self.padding[2] - self.padding[0],
218
+ self.rect.h - self.unpressed_relief - self.padding[1] - self.padding[3],
219
+ )
220
+
221
+ def get_local_inner_rect(self) -> pygame.FRect:
222
+ return pygame.FRect(
223
+ self.padding[0],
224
+ self.padding[1] + (self.unpressed_relief - self.pressed_relief if self.is_pressed else 0),
225
+ self.rect.w - self.padding[2] - self.padding[0],
226
+ self.rect.h - self.unpressed_relief - self.padding[1] - self.padding[3],
227
+ )
228
+
229
+
230
+ def _get_elevated_rect(self) -> pygame.FRect:
231
+ return pygame.FRect(
232
+ 0,
233
+ self.unpressed_relief - self.pressed_relief if self.is_pressed else 0,
234
+ self.rect.w,
235
+ self.rect.h - self.unpressed_relief,
236
+ )
237
+
238
+ def paint(self) -> None:
239
+ super().paint()
240
+ if not self.is_enabled:
241
+ self._paint_disabled()
242
+ elif self.is_hovered:
243
+ self._paint_hovered()
244
+
@@ -0,0 +1,98 @@
1
+ from .container import Container
2
+ from .scrollingContainer import ScrollingContainer
3
+ from .interactiveWidget import InteractiveWidget
4
+ from .toggle import Toggle
5
+ from .shape import Shape
6
+ from .indicator import ArrowIndicator
7
+ from .syncedVar import SyncedVar
8
+ from .layout import Column
9
+ import batFramework as bf
10
+ from .syncedVar import SyncedVar
11
+ from .widget import Widget
12
+ from .layout import Layout
13
+
14
+
15
+ class CollapseIndicator(ArrowIndicator):
16
+ def __init__(self,synced_var:SyncedVar[bool]):
17
+ super().__init__(bf.direction.RIGHT)
18
+ synced_var.bind(self,self.on_state_change)
19
+
20
+ def on_state_change(self,state:bool):
21
+ self.set_arrow_direction(bf.direction.DOWN if state else bf.direction.RIGHT)
22
+
23
+ def top_at(self, x: float, y: float) -> "None|Widget":
24
+ r = super().top_at(x, y)
25
+ if r is self:
26
+ return None
27
+ return r
28
+
29
+
30
+ class CollapseContainer(Shape,InteractiveWidget):
31
+ def __init__(self, text:str, layout:Layout=None, *children:Widget, **kwargs):
32
+ super().__init__(**kwargs)
33
+ self.state = SyncedVar[bool](False)
34
+ self.state.bind(self,self._on_state_change)
35
+ self.toggle = Toggle(text,synced_var=self.state)
36
+ self.toggle.set_autoresize_w(False)
37
+ self.container = Container(layout,*children)
38
+ self.container.set_autoresize_w(False)
39
+ self.add(self.toggle,self.container)
40
+ self.state.value = False
41
+ self.toggle.set_indicator(CollapseIndicator(self.state))
42
+ self.toggle.indicator.add_constraints(bf.gui.AspectRatio(1,reference_axis=bf.axis.VERTICAL))
43
+
44
+ def __str__(self):
45
+ return "CollapseContainer"
46
+
47
+ def _on_state_change(self,value):
48
+ print("state is ",value)
49
+ self.container.show() if value else self.container.hide()
50
+ self.dirty_shape = True
51
+
52
+ def allow_focus_to_self(self):
53
+ return super().allow_focus_to_self() and self.toggle.allow_focus_to_self()
54
+
55
+ def get_focus(self):
56
+ if self.allow_focus_to_self() and ((r := self.get_root()) is not None):
57
+ r.focus_on(self.toggle)
58
+ return True
59
+ return False
60
+
61
+ def build(self):
62
+ res = False
63
+ min_size = self.get_min_required_size()
64
+ target_size = self.resolve_size(min_size)
65
+ if self.rect.size != target_size :
66
+ self.set_size(target_size)
67
+ res = True
68
+
69
+ inner = self.get_inner_rect()
70
+ self.toggle.set_size((inner.w,None))
71
+ self.toggle.set_position(*inner.topleft)
72
+ if self.state.value:
73
+ self.container.set_size((inner.w,None))
74
+ self.container.set_position(*self.toggle.rect.bottomleft)
75
+ return res
76
+
77
+ def apply_updates(self, pass_type):
78
+
79
+ if pass_type == "pre":
80
+ self.apply_pre_updates()
81
+ if self.state.value : self.container.apply_updates("pre")
82
+ self.toggle.apply_updates("pre")
83
+ elif pass_type == "post":
84
+ if self.state.value : self.container.apply_updates("post")
85
+ self.toggle.apply_updates("post")
86
+ self.apply_post_updates(skip_draw=not self.visible)
87
+
88
+
89
+ def get_min_required_size(self):
90
+ t_min = self.toggle.get_min_required_size()
91
+ if self.container.layout:
92
+ c_min = self.container.expand_rect_with_padding((0,0,*self.container.layout.get_raw_size())).size
93
+ else:
94
+ c_min = self.container.get_min_required_size()
95
+ if not self.state.value:
96
+ c_min = (c_min[0],0)
97
+
98
+ return self.expand_rect_with_padding((0,0,max(t_min[0],c_min[0]),t_min[1]+c_min[1])).size
@@ -1 +1 @@
1
- from . import constraints
1
+ from . import constraints