batframework 1.0.8a2__py3-none-any.whl → 1.0.8a4__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 (65) hide show
  1. batFramework/__init__.py +53 -50
  2. batFramework/action.py +126 -99
  3. batFramework/actionContainer.py +53 -9
  4. batFramework/animatedSprite.py +117 -73
  5. batFramework/audioManager.py +69 -26
  6. batFramework/camera.py +259 -69
  7. batFramework/constants.py +16 -54
  8. batFramework/cutscene.py +39 -29
  9. batFramework/cutsceneBlocks.py +36 -43
  10. batFramework/dynamicEntity.py +17 -9
  11. batFramework/easingController.py +58 -0
  12. batFramework/entity.py +48 -97
  13. batFramework/enums.py +113 -0
  14. batFramework/fontManager.py +65 -0
  15. batFramework/gui/__init__.py +10 -2
  16. batFramework/gui/button.py +9 -78
  17. batFramework/gui/clickableWidget.py +221 -0
  18. batFramework/gui/constraints/__init__.py +1 -0
  19. batFramework/gui/constraints/constraints.py +730 -0
  20. batFramework/gui/container.py +174 -32
  21. batFramework/gui/debugger.py +131 -43
  22. batFramework/gui/dialogueBox.py +99 -0
  23. batFramework/gui/draggableWidget.py +40 -0
  24. batFramework/gui/image.py +54 -18
  25. batFramework/gui/indicator.py +38 -21
  26. batFramework/gui/interactiveWidget.py +177 -13
  27. batFramework/gui/label.py +292 -74
  28. batFramework/gui/layout.py +219 -60
  29. batFramework/gui/meter.py +71 -0
  30. batFramework/gui/radioButton.py +84 -0
  31. batFramework/gui/root.py +134 -38
  32. batFramework/gui/shape.py +259 -57
  33. batFramework/gui/slider.py +230 -0
  34. batFramework/gui/style.py +10 -0
  35. batFramework/gui/styleManager.py +48 -0
  36. batFramework/gui/textInput.py +137 -0
  37. batFramework/gui/toggle.py +103 -51
  38. batFramework/gui/widget.py +329 -254
  39. batFramework/manager.py +40 -19
  40. batFramework/object.py +114 -0
  41. batFramework/particle.py +101 -0
  42. batFramework/renderGroup.py +67 -0
  43. batFramework/resourceManager.py +100 -0
  44. batFramework/scene.py +281 -123
  45. batFramework/sceneManager.py +141 -108
  46. batFramework/scrollingSprite.py +114 -0
  47. batFramework/sprite.py +51 -0
  48. batFramework/stateMachine.py +2 -2
  49. batFramework/tileset.py +46 -0
  50. batFramework/time.py +123 -58
  51. batFramework/transition.py +195 -124
  52. batFramework/utils.py +87 -151
  53. batframework-1.0.8a4.dist-info/LICENCE +21 -0
  54. batframework-1.0.8a4.dist-info/METADATA +55 -0
  55. batframework-1.0.8a4.dist-info/RECORD +58 -0
  56. batFramework/debugger.py +0 -48
  57. batFramework/easing.py +0 -71
  58. batFramework/gui/constraints.py +0 -204
  59. batFramework/gui/frame.py +0 -19
  60. batFramework/particles.py +0 -77
  61. batFramework/transitionManager.py +0 -0
  62. batframework-1.0.8a2.dist-info/METADATA +0 -58
  63. batframework-1.0.8a2.dist-info/RECORD +0 -42
  64. {batframework-1.0.8a2.dist-info → batframework-1.0.8a4.dist-info}/WHEEL +0 -0
  65. {batframework-1.0.8a2.dist-info → batframework-1.0.8a4.dist-info}/top_level.txt +0 -0
batFramework/gui/shape.py CHANGED
@@ -1,86 +1,288 @@
1
1
  import batFramework as bf
2
2
  from .widget import Widget
3
3
  import pygame
4
+ from typing import Self, Iterable
5
+ from math import ceil
4
6
 
5
7
 
6
8
  class Shape(Widget):
7
- def __init__(self,width:float,height:float):
8
- self._color = (0,0,0,0)
9
- self._border_radius:list[int] = [0]
10
- self._outline : int = 0
11
- self._outline_color : tuple[int,int,int] | str = (0,0,0,0)
12
- super().__init__(convert_alpha = True)
13
- self.set_size(width,height)
9
+ def __init__(self, size: tuple[float, float] = None, *args, **kwargs):
10
+ super().__init__(size=size, convert_alpha=True)
11
+ self.color = (0, 0, 0, 0)
12
+ self.border_radius: list[int] = [0]
13
+ self.outline_width: int = 0
14
+ self.outline_color: tuple[int, int, int] | str = (0, 0, 0, 255)
15
+ self.texture_surface = None
16
+ self.texture_subsize = (0, 0)
17
+ self.relief = 0
18
+ self.shadow_color: tuple[int, int, int] | str = (0, 0, 0, 255)
19
+ self.draw_mode = bf.drawMode.SOLID
14
20
 
21
+ def get_padded_bottom(self) -> float:
22
+ return self.rect.bottom - self.padding[3] - self.relief
15
23
 
16
- def to_string_id(self)->str:
24
+ def get_padded_height(self) -> float:
25
+ return self.rect.h - self.padding[1] - self.padding[3] - self.relief
26
+
27
+ def get_padded_top(self) -> float:
28
+ return self.rect.y + self.relief
29
+
30
+ def get_padded_rect(self) -> pygame.FRect:
31
+ return pygame.FRect(
32
+ self.rect.x + self.padding[0],
33
+ self.rect.y + self.padding[1],
34
+ self.rect.w - self.padding[2] - self.padding[0],
35
+ self.rect.h - self.padding[1] - self.padding[3] - self.relief,
36
+ )
37
+
38
+ def set_shadow_color(self, color: tuple[int, int, int] | str) -> Self:
39
+ self.shadow_color = color
40
+ self.dirty_surface = True
41
+ return self
42
+
43
+ def set_relief(self, relief: int) -> Self:
44
+ if relief < 0:
45
+ return self
46
+ if self.relief == relief:
47
+ return self
48
+ self.relief = relief
49
+ self.dirty_shape = True
50
+ return self
51
+
52
+ def get_relief(self) -> int:
53
+ return self.relief
54
+
55
+ def set_texture(
56
+ self, surface: pygame.SurfaceType, subsize: tuple[int, int] | None = None
57
+ ) -> Self:
58
+ self.texture_surface = surface
59
+ if subsize is None:
60
+ subsize = (ceil(surface.get_width() / 3), ceil(surface.get_height() / 3))
61
+ self.texture_subsize = subsize
62
+ self.dirty_surface = True
63
+ return self
64
+
65
+ def set_draw_mode(self, mode: bf.drawMode) -> Self:
66
+ self.draw_mode = mode
67
+ self.dirty_surface = True
68
+ return self
69
+
70
+ def get_draw_mode(self) -> bf.drawMode:
71
+ return self.draw_mode
72
+
73
+ def has_alpha_color(self) -> bool:
74
+ return (pygame.Color(self.color).a != 255) or (
75
+ pygame.Color(self.outline_color).a != 255
76
+ )
77
+
78
+ def __str__(self) -> str:
17
79
  return "Shape"
18
80
 
19
- def set_color(self,color:tuple[int,int,int]|str) -> "Frame":
20
- self._color = color
21
- self.build()
81
+ def set_color(self, color: tuple[int, int, int] | str) -> Self:
82
+ self.color = color
83
+ self.dirty_surface = True
22
84
  return self
23
85
 
24
- def set_outline_color(self,color:tuple[int,int,int]|str) -> "Frame":
25
- self._outline_color = color
26
- self.build()
86
+ def set_outline_color(self, color: tuple[int, int, int] | str) -> Self:
87
+ self.outline_color = color
88
+ self.dirty_surface = True
27
89
  return self
28
90
 
29
- def set_border_radius(self,value:int|list[int]) -> "Frame":
30
- if isinstance(value,int):
31
- self._border_radius = [value]
91
+ def set_border_radius(self, value: int | list[int]) -> Self:
92
+ if isinstance(value, int):
93
+ self.border_radius = [value]
32
94
  else:
33
- self._border_radius = value
34
- self.build()
95
+ self.border_radius = value
96
+ self.dirty_surface = True
35
97
  return self
36
-
37
- def set_outline_width(self,value:int) -> "Frame":
38
- self._outline = value
39
- self.build()
98
+
99
+ def set_outline_width(self, value: int) -> Self:
100
+ self.outline_width = value
101
+ self.dirty_surface = True
40
102
  return self
41
-
42
- def build(self)->None:
43
- if self.surface.get_size() != self.get_size_int():
44
- self.surface = pygame.Surface(self.get_size_int())
45
- if self.convert_alpha :
46
- self.surface = self.surface.convert_alpha()
47
- self.surface.fill((0,0,0,0))
48
- if self.parent :
49
- self.parent.children_modified()
50
- if self._border_radius == [0]:
51
- self._build_shape()
52
- if self._outline : self._build_outline()
103
+
104
+ def paint(self) -> None:
105
+ if self.draw_mode == bf.drawMode.TEXTURED:
106
+ self._paint_textured()
107
+ return
108
+ if self.border_radius == [0]:
109
+ self._paint_shape()
110
+ if self.outline_width:
111
+ self._paint_outline()
53
112
  else:
54
- self._build_rounded_shape()
55
- if self._outline : self._build_rounded_outline()
113
+ self._paint_rounded_shape()
114
+ if self.outline_width:
115
+ self._paint_rounded_outline()
56
116
 
117
+ def _paint_textured(self) -> None:
118
+ self.surface.fill((0, 0, 0, 0))
119
+ if self.texture_surface is None:
120
+ return
121
+ w, h = self.surface.get_size()
122
+ sw, sh = self.texture_surface.get_size()
123
+ sub = self.texture_subsize
57
124
 
58
- def _build_shape(self)->None:
59
- self.surface.fill(self._color)
125
+ # center
126
+ center_surface = self.texture_surface.subsurface((sub[0], sub[1], *sub))
127
+ top_surface = self.texture_surface.subsurface((sub[0], 0, *sub))
128
+ bottom_surface = self.texture_surface.subsurface((sub[0], sh - sub[1], *sub))
129
+ left_surface = self.texture_surface.subsurface((0, sub[1], *sub))
130
+ right_surface = self.texture_surface.subsurface((sw - sub[0], sub[1], *sub))
60
131
 
61
- def _build_rounded_shape(self)->None:
62
- self.surface.fill((0,0,0,0))
63
- pygame.draw.rect(
64
- self.surface,
65
- self._color,
66
- (0,0,*self.rect.size),
67
- 0,
68
- *self._border_radius
132
+ lst = []
133
+ for y in range(sub[1], h + 1 - sub[1] * 2, sub[1]):
134
+ for x in range(sub[0], w + 1 - sub[0] * 2, sub[0]):
135
+ lst.append((center_surface, (x, y)))
136
+
137
+ w_remainder = w % sub[0]
138
+ h_remainder = h % sub[1]
139
+ fix_x = ((w // sub[0]) - 1) * sub[0]
140
+ fix_y = ((h // sub[1]) - 1) * sub[1]
141
+
142
+ if (w > sub[0]) and (w_remainder > 0):
143
+ # Center : Fix gaps on the x axis
144
+ h_portion = center_surface.subsurface(0, 0, w_remainder, sub[1])
145
+ for y in range(sub[1], h - sub[1] * 2, sub[1]):
146
+ lst.append((h_portion, (fix_x, y)))
147
+
148
+ # Fix partial gaps on the top
149
+
150
+ t_portion = top_surface.subsurface(0, 0, w_remainder, sub[1])
151
+ lst.append((t_portion, (fix_x, 0)))
152
+
153
+ # Fix partial gaps on the bottom
154
+ b_portion = bottom_surface.subsurface(0, 0, w_remainder, sub[1])
155
+ lst.append((b_portion, (fix_x, h - sub[1] - 1)))
156
+
157
+ if (h > sub[1]) and (h_remainder > 0):
158
+ # Center : Fix gaps on the y axis
159
+ v_portion = center_surface.subsurface(0, 0, sub[0], h_remainder)
160
+ for x in range(sub[0], w - sub[0] * 2, sub[0]):
161
+ lst.append((v_portion, (x, fix_y)))
162
+
163
+ # Fix partial gaps on the left
164
+ l_portion = left_surface.subsurface(0, 0, sub[0], h_remainder)
165
+ lst.append((l_portion, (0, fix_y)))
166
+
167
+ # Fix partial gaps on the right
168
+ r_portion = right_surface.subsurface(0, 0, sub[0], h_remainder)
169
+ lst.append((r_portion, (w - sub[0] - 1, fix_y)))
170
+
171
+ # fix corner gap
172
+ if h > sub[1] or w > sub[0]:
173
+ corner_portion = center_surface.subsurface(
174
+ 0,
175
+ 0,
176
+ w_remainder if w_remainder else sub[0],
177
+ h_remainder if h_remainder else sub[1],
178
+ )
179
+ if w_remainder == 0:
180
+ fix_x -= sub[0]
181
+ if h_remainder == 0:
182
+ fix_y -= sub[1]
183
+ lst.append((corner_portion, (fix_x - 1, fix_y - 1)))
184
+
185
+ # borders
186
+ lst.extend(
187
+ [(top_surface, (x, 0)) for x in range(sub[0], w + 1 - sub[0] * 2, sub[0])]
188
+ + [
189
+ (bottom_surface, (x, h - sub[1] - 1))
190
+ for x in range(sub[0], w + 1 - sub[0] * 2, sub[0])
191
+ ]
192
+ + [
193
+ (left_surface, (0, y))
194
+ for y in range(sub[1], h + 1 - sub[1] * 2, sub[1])
195
+ ]
196
+ + [
197
+ (right_surface, (w - sub[0] - 1, y))
198
+ for y in range(sub[1], h + 1 - sub[1] * 2, sub[1])
199
+ ]
200
+ + [
201
+ (self.texture_surface.subsurface((0, 0, *sub)), (0, 0)),
202
+ (
203
+ self.texture_surface.subsurface((sw - sub[0], 0, *sub)),
204
+ (w - sub[0] - 1, 0),
205
+ ),
206
+ (
207
+ self.texture_surface.subsurface((0, sh - sub[1], *sub)),
208
+ (0, h - sub[1] - 1),
209
+ ),
210
+ (
211
+ self.texture_surface.subsurface((sw - sub[0], sh - sub[1], *sub)),
212
+ (w - sub[0] - 1, h - sub[1] - 1),
213
+ ),
214
+ ]
69
215
  )
70
216
 
71
- def _build_outline(self)->None:
217
+ self.surface.fblits(lst)
218
+
219
+ def _get_elevated_rect(self) -> pygame.FRect:
220
+ return pygame.FRect(0, 0, self.rect.w, self.rect.h - self.relief)
221
+
222
+ def _get_base_rect(self) -> pygame.FRect:
223
+ return pygame.FRect(0, self.rect.h - self.relief, self.rect.w, self.relief)
224
+
225
+ def _paint_shape(self) -> None:
226
+ if self.relief!=0:
227
+ self.surface.fill((0, 0, 0, 0))
228
+ self.surface.fill(self.shadow_color, self._get_base_rect())
229
+ self.surface.fill(self.color, self._get_elevated_rect())
230
+ else:
231
+ self.surface.fill(self.color, self._get_elevated_rect())
232
+
233
+ def _paint_rounded_shape(self) -> None:
234
+ self.surface.fill((0, 0, 0, 0))
235
+ e = self._get_elevated_rect()
236
+ if self.relief != 0:
237
+ b = e.copy()
238
+ b.bottom = self.rect.h
239
+ pygame.draw.rect(self.surface, self.shadow_color, b, 0, *self.border_radius)
240
+ pygame.draw.rect(self.surface, self.color, e, 0, *self.border_radius)
241
+ else:
242
+ pygame.draw.rect(self.surface, self.color, e, 0, *self.border_radius)
243
+
244
+ def _paint_outline(self) -> None:
245
+ if self.relief:
246
+ pygame.draw.rect(
247
+ self.surface,
248
+ self.outline_color,
249
+ (
250
+ 0,
251
+ self.relief - self.get_relief(),
252
+ self.rect.w,
253
+ self.rect.h - self.relief,
254
+ ),
255
+ self.outline_width,
256
+ )
72
257
  pygame.draw.rect(
73
258
  self.surface,
74
- self._outline_color,
75
- (0,0,*self.rect.size),
76
- self._outline
259
+ self.outline_color,
260
+ (
261
+ 0,
262
+ self.relief - self.get_relief(),
263
+ self.rect.w,
264
+ self.rect.h - (self.relief - self.get_relief()),
265
+ ),
266
+ self.outline_width,
77
267
  )
78
-
79
- def _build_rounded_outline(self)->None:
268
+
269
+ def _paint_rounded_outline(self) -> None:
270
+ e = self._get_elevated_rect()
271
+ b = e.copy()
272
+ b.h += e.bottom - b.bottom
273
+
80
274
  pygame.draw.rect(
81
275
  self.surface,
82
- self._outline_color,
83
- (0,0,*self.rect.size),
84
- self._outline,
85
- *self._border_radius
276
+ self.outline_color,
277
+ e,
278
+ self.outline_width,
279
+ *self.border_radius,
86
280
  )
281
+ if self.relief:
282
+ pygame.draw.rect(
283
+ self.surface,
284
+ self.outline_color,
285
+ b,
286
+ self.outline_width,
287
+ *self.border_radius,
288
+ )
@@ -0,0 +1,230 @@
1
+ import batFramework as bf
2
+ from .meter import Meter
3
+ from .button import Button
4
+ from .indicator import *
5
+ from .meter import Meter
6
+ from .shape import Shape
7
+ from .interactiveWidget import InteractiveWidget
8
+
9
+
10
+ class SliderHandle(Indicator, DraggableWidget):
11
+ def __init__(self):
12
+ super().__init__()
13
+ self.set_color(bf.color.CLOUD_SHADE)
14
+ self.old_key_repeat: tuple = (0, 0)
15
+
16
+ def __str__(self) -> str:
17
+ return "SliderHandle"
18
+
19
+ def on_click_down(self, button: int) -> None:
20
+ super().on_click_down(button)
21
+ if button == 1:
22
+ self.parent.get_focus()
23
+
24
+ def on_exit(self) -> None:
25
+ self.is_hovered = False
26
+ self.do_on_exit()
27
+
28
+ def do_on_drag(
29
+ self, drag_start: tuple[float, float], drag_end: tuple[float, float]
30
+ ) -> None:
31
+ super().do_on_drag(drag_start, drag_end)
32
+ m: Meter = self.parent.meter
33
+ r = m.get_padded_rect()
34
+ position = self.rect.centerx
35
+ self.rect.clamp_ip(r)
36
+ # Adjust handle position to value
37
+ new_value = self.parent.position_to_value(position)
38
+ self.parent.set_value(new_value)
39
+ self.rect.centerx = self.parent.value_to_position(new_value)
40
+
41
+ def top_at(self, x, y):
42
+ return Widget.top_at(self, x, y)
43
+
44
+
45
+ class SliderMeter(Meter, InteractiveWidget):
46
+
47
+ def __str__(self) -> str:
48
+ return "SliderMeter"
49
+
50
+ def on_click_down(self, button: int) -> None:
51
+ if button == 1:
52
+ self.parent.get_focus()
53
+ r = self.get_root()
54
+ if r:
55
+ pos = r.drawing_camera.screen_to_world(pygame.mouse.get_pos())[0]
56
+ self.parent.set_value(self.parent.position_to_value(pos))
57
+
58
+ self.do_on_click_down(button)
59
+
60
+
61
+ class Slider(Button):
62
+ def __init__(self, text: str, default_value: float = 1.0) -> None:
63
+ super().__init__(text, None)
64
+ self.gap: float | int = 0
65
+ self.spacing: bf.spacing = bf.spacing.MANUAL
66
+ self.modified_callback = None
67
+ self.meter: SliderMeter = SliderMeter()
68
+ self.handle = SliderHandle()
69
+ self.add(self.meter, self.handle)
70
+ self.meter.set_debug_color(bf.color.RED)
71
+ self.set_value(default_value, True)
72
+
73
+ def set_visible(self, value: bool) -> Self:
74
+ self.handle.set_visible(value)
75
+ self.meter.set_visible(value)
76
+ return super().set_visible(value)
77
+
78
+ def __str__(self) -> str:
79
+ return "Slider"
80
+
81
+ def set_gap(self, value: int | float) -> Self:
82
+ value = max(0, value)
83
+ self.gap = value
84
+ return self
85
+
86
+ def do_on_get_focus(self) -> None:
87
+ super().do_on_get_focus()
88
+ self.old_key_repeat = pygame.key.get_repeat()
89
+ pygame.key.set_repeat(200, 50)
90
+
91
+ def do_on_lose_focus(self) -> None:
92
+ super().do_on_lose_focus()
93
+ pygame.key.set_repeat(*self.old_key_repeat)
94
+
95
+ def get_min_required_size(self) -> tuple[float, float]:
96
+ gap = self.gap if self.text else 0
97
+ if not self.text_rect:
98
+ self.text_rect.size = self._get_text_rect_required_size()
99
+ w, h = self.text_rect.size
100
+ return self.inflate_rect_by_padding((0, 0, w + gap + self.meter.rect.w, h)).size
101
+
102
+ def set_spacing(self, spacing: bf.spacing) -> Self:
103
+ if spacing == self.spacing:
104
+ return self
105
+ self.spacing = spacing
106
+ self.dirty_shape = True
107
+ return self
108
+
109
+ def set_modify_callback(self, callback) -> Self:
110
+ self.modified_callback = callback
111
+ return self
112
+
113
+ def set_range(self, range_min: float, range_max: float) -> Self:
114
+ self.meter.set_range(range_min, range_max)
115
+ return self
116
+
117
+ def set_step(self, step: float) -> Self:
118
+ self.meter.set_step(step)
119
+ return self
120
+
121
+ def set_value(self, value, no_callback: bool = False) -> Self:
122
+ if self.meter.value != value:
123
+ self.meter.set_value(value)
124
+ self.dirty_shape = True
125
+ if self.modified_callback and (not no_callback):
126
+ self.modified_callback(self.meter.value)
127
+ return self
128
+
129
+ def get_value(self) -> float:
130
+ return self.meter.get_value()
131
+
132
+ def do_on_key_down(self, key):
133
+ if key == pygame.K_RIGHT:
134
+ self.set_value(self.meter.get_value() + self.meter.step)
135
+ elif key == pygame.K_LEFT:
136
+ self.set_value(self.meter.get_value() - self.meter.step)
137
+
138
+ def do_on_click_down(self, button) -> None:
139
+ if button == 1:
140
+ self.get_focus()
141
+
142
+ def value_to_position(self, value: float) -> float:
143
+ """
144
+ Converts a value to a position on the meter, considering the step size.
145
+ """
146
+ rect = self.meter.get_padded_rect()
147
+ value_range = self.meter.get_range()
148
+ value = round(value / self.meter.step) * self.meter.step
149
+ position_ratio = (value - self.meter.min_value) / value_range
150
+ return (
151
+ rect.left
152
+ + (self.handle.rect.w / 2)
153
+ + position_ratio * (rect.width - self.handle.rect.w)
154
+ )
155
+
156
+ def position_to_value(self, position: float) -> float:
157
+ """
158
+ Converts a position on the meter to a value, considering the step size.
159
+ """
160
+ handle_half = self.handle.rect.w / 2
161
+ rect = self.meter.get_padded_rect()
162
+ position = max(rect.left + handle_half, min(position, rect.right - handle_half))
163
+
164
+ position_ratio = (position - rect.left - handle_half) / (
165
+ rect.width - self.handle.rect.w
166
+ )
167
+ value_range = self.meter.get_range()
168
+ value = self.meter.min_value + position_ratio * value_range
169
+ return round(value / self.meter.step) * self.meter.step
170
+
171
+ def _build_layout(self) -> None:
172
+
173
+ gap = self.gap if self.text else 0
174
+
175
+ self.text_rect.size = self._get_text_rect_required_size()
176
+
177
+ meter_size = [self.text_rect.h * 10, self.font_object.point_size]
178
+ if not self.autoresize_w:
179
+ meter_size[0] = self.get_padded_width() - self.text_rect.w - gap
180
+
181
+ tmp_rect = pygame.FRect(
182
+ 0, 0, self.text_rect.w + gap + meter_size[0], self.text_rect.h
183
+ )
184
+
185
+ if self.autoresize_h or self.autoresize_w:
186
+ target_rect = self.inflate_rect_by_padding(tmp_rect)
187
+ if not self.autoresize_w:
188
+ target_rect.w = self.rect.w
189
+ if not self.autoresize_h:
190
+ target_rect.h = self.rect.h
191
+ if self.rect.size != target_rect.size:
192
+ self.set_size(target_rect.size)
193
+ self.build()
194
+ return
195
+
196
+ # ------------------------------------ size is ok
197
+ padded_rect = self.get_padded_rect()
198
+ padded_relative = padded_rect.move(-self.rect.x, -self.rect.y)
199
+
200
+
201
+ self.meter.set_size_if_autoresize(meter_size)
202
+
203
+ self.align_text(tmp_rect, padded_relative, self.alignment)
204
+ self.text_rect.midleft = tmp_rect.midleft
205
+
206
+ if self.text:
207
+ match self.spacing:
208
+ case bf.spacing.MAX:
209
+ gap = padded_relative.right - self.text_rect.right - self.meter.rect.w
210
+ case bf.spacing.MIN:
211
+ gap = 0
212
+
213
+ # place meter
214
+
215
+ self.meter.set_position(
216
+ *self.text_rect.move(
217
+ self.rect.x + gap,
218
+ self.rect.y + (self.text_rect.h / 2) - meter_size[1] / 2,
219
+ ).topright
220
+ )
221
+ # place handle
222
+
223
+ # print(self.meter.rect.top - self.rect.top)
224
+ # print(self.meter.rect.h)
225
+
226
+ x = self.value_to_position(self.meter.value)
227
+ r = self.meter.get_padded_rect()
228
+ self.handle.set_center(x, r.centery)
229
+
230
+ # self.handle.set_center(x,self.rect.top)
@@ -0,0 +1,10 @@
1
+ from .widget import Widget
2
+
3
+
4
+ class Style:
5
+
6
+ def __init__(self):
7
+ pass
8
+
9
+ def apply(self, widget: Widget):
10
+ pass
@@ -0,0 +1,48 @@
1
+ from ..utils import Singleton
2
+ from .widget import Widget
3
+
4
+
5
+ class Style:
6
+ def __init__(self):
7
+ pass
8
+
9
+ def apply(self, widget: Widget):
10
+ pass
11
+
12
+
13
+ class StyleManager(metaclass=Singleton):
14
+ def __init__(self):
15
+ self.styles: list[Style] = []
16
+ self.widgets: set[Widget] = set()
17
+ self.lookup: dict[Widget, bool] = {}
18
+
19
+ def register_widget(self, widget: Widget):
20
+ if widget in self.widgets:
21
+ return
22
+ self.widgets.add(widget)
23
+ self.lookup[widget] = False
24
+ self.update()
25
+
26
+ def refresh_widget(self, widget: Widget):
27
+ if widget in self.widgets:
28
+ self.lookup[widget] = True
29
+ self.update()
30
+
31
+ def remove_widget(self, widget: Widget):
32
+ if widget not in self.widgets:
33
+ return
34
+ self.widgets.remove(widget)
35
+ self.lookup.pop(widget)
36
+
37
+ def add(self, style: Style):
38
+ self.styles.append(style)
39
+ self.lookup = {key: False for key in self.lookup}
40
+ self.update()
41
+
42
+ def update(self):
43
+ for widget in self.widgets:
44
+ if self.lookup[widget]:
45
+ continue
46
+ for style in self.styles:
47
+ style.apply(widget)
48
+ self.lookup[widget] = True