batframework 1.0.8a2__py3-none-any.whl → 1.0.8a3__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 +115 -65
  5. batFramework/audioManager.py +69 -26
  6. batFramework/camera.py +259 -69
  7. batFramework/constants.py +16 -54
  8. batFramework/cutscene.py +36 -29
  9. batFramework/cutsceneBlocks.py +37 -42
  10. batFramework/dynamicEntity.py +9 -7
  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 +219 -0
  18. batFramework/gui/constraints/__init__.py +1 -0
  19. batFramework/gui/constraints/constraints.py +590 -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 +288 -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 +128 -38
  32. batFramework/gui/shape.py +253 -57
  33. batFramework/gui/slider.py +246 -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 +115 -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 +84 -0
  44. batFramework/scene.py +242 -114
  45. batFramework/sceneManager.py +145 -107
  46. batFramework/scrollingSprite.py +115 -0
  47. batFramework/sprite.py +51 -0
  48. batFramework/stateMachine.py +2 -2
  49. batFramework/tileset.py +46 -0
  50. batFramework/time.py +117 -57
  51. batFramework/transition.py +184 -126
  52. batFramework/utils.py +31 -156
  53. batframework-1.0.8a3.dist-info/LICENCE +21 -0
  54. batframework-1.0.8a3.dist-info/METADATA +55 -0
  55. batframework-1.0.8a3.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.8a3.dist-info}/WHEEL +0 -0
  65. {batframework-1.0.8a2.dist-info → batframework-1.0.8a3.dist-info}/top_level.txt +0 -0
batFramework/gui/shape.py CHANGED
@@ -1,86 +1,282 @@
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: 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 = 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:
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:
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
+ self.surface.fill((0, 0, 0, 0))
227
+ self.surface.fill(self.shadow_color, self._get_base_rect())
228
+ self.surface.fill(self.color, self._get_elevated_rect())
229
+
230
+ def _paint_rounded_shape(self) -> None:
231
+ self.surface.fill((0, 0, 0, 0))
232
+ e = self._get_elevated_rect()
233
+ b = e.copy()
234
+ b.bottom = self.rect.h
235
+ pygame.draw.rect(self.surface, self.shadow_color, b, 0, *self.border_radius)
236
+ pygame.draw.rect(self.surface, self.color, e, 0, *self.border_radius)
237
+
238
+ def _paint_outline(self) -> None:
239
+ if self.relief:
240
+ pygame.draw.rect(
241
+ self.surface,
242
+ self.outline_color,
243
+ (
244
+ 0,
245
+ self.relief - self.get_relief(),
246
+ self.rect.w,
247
+ self.rect.h - self.relief,
248
+ ),
249
+ self.outline,
250
+ )
72
251
  pygame.draw.rect(
73
252
  self.surface,
74
- self._outline_color,
75
- (0,0,*self.rect.size),
76
- self._outline
253
+ self.outline_color,
254
+ (
255
+ 0,
256
+ self.relief - self.get_relief(),
257
+ self.rect.w,
258
+ self.rect.h - (self.relief - self.get_relief()),
259
+ ),
260
+ self.outline,
77
261
  )
78
-
79
- def _build_rounded_outline(self)->None:
262
+
263
+ def _paint_rounded_outline(self) -> None:
264
+ e = self._get_elevated_rect()
265
+ b = e.copy()
266
+ b.h += e.bottom - b.bottom
267
+
80
268
  pygame.draw.rect(
81
269
  self.surface,
82
- self._outline_color,
83
- (0,0,*self.rect.size),
84
- self._outline,
85
- *self._border_radius
270
+ self.outline_color,
271
+ e,
272
+ self.outline,
273
+ *self.border_radius,
86
274
  )
275
+ if self.relief:
276
+ pygame.draw.rect(
277
+ self.surface,
278
+ self.outline_color,
279
+ b,
280
+ self.outline,
281
+ *self.border_radius,
282
+ )
@@ -0,0 +1,246 @@
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
+
15
+ def __str__(self) -> str:
16
+ return "SliderHandle"
17
+
18
+ def on_click_down(self, button: int) -> None:
19
+ super().on_click_down(button)
20
+ if button == 1:
21
+ self.parent.get_focus()
22
+
23
+ def on_exit(self) -> None:
24
+ self.is_hovered = False
25
+ self.do_on_exit()
26
+
27
+ def do_on_drag(
28
+ self, drag_start: tuple[float, float], drag_end: tuple[float, float]
29
+ ) -> None:
30
+ super().do_on_drag(drag_start, drag_end)
31
+ m: Meter = self.parent.meter
32
+ r = m.get_padded_rect()
33
+ position = self.rect.centerx
34
+ self.rect.clamp_ip(r)
35
+ # Adjust handle position to value
36
+ new_value = self.parent.position_to_value(position)
37
+ self.parent.set_value(new_value)
38
+ self.rect.centerx = self.parent.value_to_position(new_value)
39
+
40
+ def top_at(self, x, y):
41
+ return Widget.top_at(self, x, y)
42
+
43
+
44
+ class SliderMeter(Meter, InteractiveWidget):
45
+
46
+ def __str__(self) -> str:
47
+ return "SliderMeter"
48
+
49
+ def on_click_down(self, button: int) -> None:
50
+ if button == 1:
51
+ self.parent.get_focus()
52
+ r = self.get_root()
53
+ if r:
54
+ pos = r.drawing_camera.screen_to_world(pygame.mouse.get_pos())[0]
55
+ self.parent.set_value(self.parent.position_to_value(pos))
56
+
57
+ self.do_on_click_down(button)
58
+
59
+
60
+ class Slider(Button):
61
+ def __init__(self, text: str, default_value: float = 1.0) -> None:
62
+ super().__init__(text, None)
63
+ self.gap: float | int = 0
64
+ self.spacing: bf.spacing = bf.spacing.MANUAL
65
+ self.modified_callback = None
66
+ self.meter: SliderMeter = SliderMeter()
67
+ self.handle = SliderHandle()
68
+ self.add(self.meter, self.handle)
69
+ self.meter.set_debug_color(bf.color.RED)
70
+ self.set_value(default_value, True)
71
+ # print(self.handle.rect)
72
+ # self.handle.set_visible(False)
73
+
74
+ def set_visible(self, value: bool) -> Self:
75
+ self.handle.set_visible(value)
76
+ self.meter.set_visible(value)
77
+ return super().set_visible(value)
78
+
79
+ def __str__(self) -> str:
80
+ return "Slider"
81
+
82
+ def set_gap(self, value: int | float) -> Self:
83
+ value = max(0, value)
84
+ self.gap = value
85
+ return self
86
+
87
+ def get_min_required_size(self) -> tuple[float, float]:
88
+ gap = self.gap if self.text else 0
89
+ if not self.text_rect:
90
+ params = {
91
+ "font_name": self.font_object.name,
92
+ "text": self.text,
93
+ "antialias": False,
94
+ "color": "white",
95
+ "bgcolor": "black", # if (self.has_alpha_color() or self.draw_mode == bf.drawMode.TEXTURED) else self.color,
96
+ "wraplength": (
97
+ int(self.get_padded_width()) if self.auto_wraplength else 0
98
+ ),
99
+ }
100
+ self.text_rect.size = self._render_font(params).get_size()
101
+ w, h = self.text_rect.size
102
+ return self.inflate_rect_by_padding((0, 0, w + gap + self.meter.rect.w, h)).size
103
+
104
+ def set_spacing(self, spacing: bf.spacing) -> Self:
105
+ if spacing == self.spacing:
106
+ return self
107
+ self.spacing = spacing
108
+ self.dirty_shape = True
109
+ return self
110
+
111
+ def set_modify_callback(self, callback) -> Self:
112
+ self.modified_callback = callback
113
+ return self
114
+
115
+ def set_range(self, range_min: float, range_max: float) -> Self:
116
+ self.meter.set_range(range_min, range_max)
117
+ return self
118
+
119
+ def set_step(self, step: float) -> Self:
120
+ self.meter.set_step(step)
121
+ return self
122
+
123
+ def set_value(self, value, no_callback: bool = False) -> Self:
124
+ if self.meter.value != value:
125
+ self.meter.set_value(value)
126
+ self.dirty_shape = True
127
+ if self.modified_callback and (not no_callback):
128
+ self.modified_callback(self.meter.value)
129
+ return self
130
+
131
+ def get_value(self) -> float:
132
+ return self.meter.get_value()
133
+
134
+ def do_on_key_down(self, key):
135
+ if key == pygame.K_RIGHT:
136
+ self.set_value(self.meter.get_value() + self.meter.step)
137
+ bf.AudioManager().play_sound(self.click_down_sound)
138
+ elif key == pygame.K_LEFT:
139
+ self.set_value(self.meter.get_value() - self.meter.step)
140
+ bf.AudioManager().play_sound(self.click_down_sound)
141
+
142
+ def do_on_click_down(self, button) -> None:
143
+ if button == 1:
144
+ self.get_focus()
145
+
146
+ def value_to_position(self, value: float) -> float:
147
+ """
148
+ Converts a value to a position on the meter, considering the step size.
149
+ """
150
+ rect = self.meter.get_padded_rect()
151
+ value_range = self.meter.get_range()
152
+ value = round(value / self.meter.step) * self.meter.step
153
+ position_ratio = (value - self.meter.min_value) / value_range
154
+ # print(self.handle.rect)
155
+ # print(rect.left + (self.handle.rect.w/2) + position_ratio * (rect.width - self.handle.rect.w),self.handle.rect.w,self.rect.right)
156
+ return (
157
+ rect.left
158
+ + (self.handle.rect.w / 2)
159
+ + position_ratio * (rect.width - self.handle.rect.w)
160
+ )
161
+
162
+ def position_to_value(self, position: float) -> float:
163
+ """
164
+ Converts a position on the meter to a value, considering the step size.
165
+ """
166
+ handle_half = self.handle.rect.w / 2
167
+ rect = self.meter.get_padded_rect()
168
+ position = max(rect.left + handle_half, min(position, rect.right - handle_half))
169
+
170
+ position_ratio = (position - rect.left - handle_half) / (
171
+ rect.width - self.handle.rect.w
172
+ )
173
+ value_range = self.meter.get_range()
174
+ value = self.meter.min_value + position_ratio * value_range
175
+ return round(value / self.meter.step) * self.meter.step
176
+
177
+ def _build_layout(self) -> None:
178
+
179
+ gap = self.gap if self.text else 0
180
+
181
+ params = {
182
+ "font_name": self.font_object.name,
183
+ "text": self.text,
184
+ "antialias": False,
185
+ "color": "white",
186
+ "bgcolor": "black", # if (self.has_alpha_color() or self.draw_mode == bf.drawMode.TEXTURED) else self.color,
187
+ "wraplength": int(self.get_padded_width()) if self.auto_wraplength else 0,
188
+ }
189
+
190
+ self.text_rect.size = self._render_font(params).get_size()
191
+
192
+ meter_size = [self.text_rect.h * 10, self.font_object.point_size]
193
+ if not self.autoresize_w:
194
+ meter_size[0] = self.get_padded_width() - self.text_rect.w - gap
195
+
196
+ tmp_rect = pygame.FRect(
197
+ 0, 0, self.text_rect.w + gap + meter_size[0], self.text_rect.h
198
+ )
199
+
200
+ if self.autoresize_h or self.autoresize_w:
201
+ target_rect = self.inflate_rect_by_padding(tmp_rect)
202
+ if not self.autoresize_w:
203
+ target_rect.w = self.rect.w
204
+ if not self.autoresize_h:
205
+ target_rect.h = self.rect.h
206
+ if self.rect.size != target_rect.size:
207
+ self.set_size(target_rect.size)
208
+ self.build()
209
+ return
210
+
211
+ # ------------------------------------ size is ok
212
+ padded = self.get_padded_rect().move(-self.rect.x, -self.rect.y)
213
+
214
+ self.meter.set_size_if_autoresize(meter_size)
215
+ handle_size = 2 * [self.meter.get_padded_height()]
216
+
217
+ self.handle.set_size_if_autoresize(handle_size)
218
+
219
+ self.align_text(tmp_rect, padded, self.alignment)
220
+ self.text_rect.midleft = tmp_rect.midleft
221
+
222
+ if self.text:
223
+ match self.spacing:
224
+ case bf.spacing.MAX:
225
+ gap = padded.w - self.text_rect.w - self.meter.rect.w
226
+ case bf.spacing.MIN:
227
+ gap = 0
228
+
229
+ # place meter
230
+
231
+ self.meter.set_position(
232
+ *self.text_rect.move(
233
+ self.rect.x + gap,
234
+ self.rect.y + (self.text_rect.h / 2) - meter_size[1] / 2,
235
+ ).topright
236
+ )
237
+ # place handle
238
+
239
+ # print(self.meter.rect.top - self.rect.top)
240
+ # print(self.meter.rect.h)
241
+
242
+ x = self.value_to_position(self.meter.value)
243
+ r = self.meter.get_padded_rect()
244
+ self.handle.set_center(x, r.centery)
245
+
246
+ # 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