rocket-welder-sdk 1.1.0__py3-none-any.whl → 1.1.26__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.
- rocket_welder_sdk/__init__.py +22 -0
- rocket_welder_sdk/controllers.py +125 -66
- rocket_welder_sdk/external_controls/__init__.py +30 -0
- rocket_welder_sdk/external_controls/contracts.py +100 -0
- rocket_welder_sdk/external_controls/contracts_old.py +105 -0
- rocket_welder_sdk/gst_metadata.py +315 -144
- rocket_welder_sdk/rocket_welder_client.py +10 -13
- rocket_welder_sdk/ui/__init__.py +48 -0
- rocket_welder_sdk/ui/controls.py +362 -0
- rocket_welder_sdk/ui/icons.py +21628 -0
- rocket_welder_sdk/ui/ui_events_projection.py +226 -0
- rocket_welder_sdk/ui/ui_service.py +358 -0
- rocket_welder_sdk/ui/value_types.py +72 -0
- {rocket_welder_sdk-1.1.0.dist-info → rocket_welder_sdk-1.1.26.dist-info}/METADATA +4 -2
- rocket_welder_sdk-1.1.26.dist-info/RECORD +20 -0
- rocket_welder_sdk-1.1.0.dist-info/RECORD +0 -11
- {rocket_welder_sdk-1.1.0.dist-info → rocket_welder_sdk-1.1.26.dist-info}/WHEEL +0 -0
- {rocket_welder_sdk-1.1.0.dist-info → rocket_welder_sdk-1.1.26.dist-info}/top_level.txt +0 -0
|
@@ -20,6 +20,9 @@ if TYPE_CHECKING:
|
|
|
20
20
|
# Type alias for OpenCV Mat
|
|
21
21
|
Mat = np.ndarray[Any, Any]
|
|
22
22
|
|
|
23
|
+
# Module logger
|
|
24
|
+
logger = logging.getLogger(__name__)
|
|
25
|
+
|
|
23
26
|
|
|
24
27
|
class RocketWelderClient:
|
|
25
28
|
"""
|
|
@@ -28,20 +31,18 @@ class RocketWelderClient:
|
|
|
28
31
|
Provides a unified interface for different connection types and protocols.
|
|
29
32
|
"""
|
|
30
33
|
|
|
31
|
-
def __init__(self, connection: str | ConnectionString
|
|
34
|
+
def __init__(self, connection: str | ConnectionString):
|
|
32
35
|
"""
|
|
33
36
|
Initialize the RocketWelder client.
|
|
34
37
|
|
|
35
38
|
Args:
|
|
36
39
|
connection: Connection string or ConnectionString object
|
|
37
|
-
logger: Optional logger instance
|
|
38
40
|
"""
|
|
39
41
|
if isinstance(connection, str):
|
|
40
42
|
self._connection = ConnectionString.parse(connection)
|
|
41
43
|
else:
|
|
42
44
|
self._connection = connection
|
|
43
45
|
|
|
44
|
-
self._logger = logger or logging.getLogger(__name__)
|
|
45
46
|
self._controller: IController | None = None
|
|
46
47
|
self._lock = threading.Lock()
|
|
47
48
|
|
|
@@ -93,15 +94,15 @@ class RocketWelderClient:
|
|
|
93
94
|
# Create appropriate controller based on connection
|
|
94
95
|
if self._connection.protocol == Protocol.SHM:
|
|
95
96
|
if self._connection.connection_mode == ConnectionMode.DUPLEX:
|
|
96
|
-
self._controller = DuplexShmController(self._connection
|
|
97
|
+
self._controller = DuplexShmController(self._connection)
|
|
97
98
|
else:
|
|
98
|
-
self._controller = OneWayShmController(self._connection
|
|
99
|
+
self._controller = OneWayShmController(self._connection)
|
|
99
100
|
else:
|
|
100
101
|
raise ValueError(f"Unsupported protocol: {self._connection.protocol}")
|
|
101
102
|
|
|
102
103
|
# Start the controller
|
|
103
104
|
self._controller.start(on_frame, cancellation_token) # type: ignore[arg-type]
|
|
104
|
-
|
|
105
|
+
logger.info("RocketWelder client started with %s", self._connection)
|
|
105
106
|
|
|
106
107
|
def stop(self) -> None:
|
|
107
108
|
"""Stop the client and clean up resources."""
|
|
@@ -109,7 +110,7 @@ class RocketWelderClient:
|
|
|
109
110
|
if self._controller:
|
|
110
111
|
self._controller.stop()
|
|
111
112
|
self._controller = None
|
|
112
|
-
|
|
113
|
+
logger.info("RocketWelder client stopped")
|
|
113
114
|
|
|
114
115
|
def __enter__(self) -> RocketWelderClient:
|
|
115
116
|
"""Context manager entry."""
|
|
@@ -125,7 +126,6 @@ class RocketWelderClient:
|
|
|
125
126
|
buffer_name: str,
|
|
126
127
|
buffer_size: str = "256MB",
|
|
127
128
|
metadata_size: str = "4KB",
|
|
128
|
-
logger: logging.Logger | None = None,
|
|
129
129
|
) -> RocketWelderClient:
|
|
130
130
|
"""
|
|
131
131
|
Create a one-way shared memory client.
|
|
@@ -134,7 +134,6 @@ class RocketWelderClient:
|
|
|
134
134
|
buffer_name: Name of the shared memory buffer
|
|
135
135
|
buffer_size: Size of the buffer (e.g., "256MB")
|
|
136
136
|
metadata_size: Size of metadata buffer (e.g., "4KB")
|
|
137
|
-
logger: Optional logger
|
|
138
137
|
|
|
139
138
|
Returns:
|
|
140
139
|
Configured RocketWelderClient instance
|
|
@@ -142,7 +141,7 @@ class RocketWelderClient:
|
|
|
142
141
|
connection_str = (
|
|
143
142
|
f"shm://{buffer_name}?size={buffer_size}&metadata={metadata_size}&mode=OneWay"
|
|
144
143
|
)
|
|
145
|
-
return cls(connection_str
|
|
144
|
+
return cls(connection_str)
|
|
146
145
|
|
|
147
146
|
@classmethod
|
|
148
147
|
def create_duplex_shm(
|
|
@@ -150,7 +149,6 @@ class RocketWelderClient:
|
|
|
150
149
|
buffer_name: str,
|
|
151
150
|
buffer_size: str = "256MB",
|
|
152
151
|
metadata_size: str = "4KB",
|
|
153
|
-
logger: logging.Logger | None = None,
|
|
154
152
|
) -> RocketWelderClient:
|
|
155
153
|
"""
|
|
156
154
|
Create a duplex shared memory client.
|
|
@@ -159,7 +157,6 @@ class RocketWelderClient:
|
|
|
159
157
|
buffer_name: Name of the shared memory buffer
|
|
160
158
|
buffer_size: Size of the buffer (e.g., "256MB")
|
|
161
159
|
metadata_size: Size of metadata buffer (e.g., "4KB")
|
|
162
|
-
logger: Optional logger
|
|
163
160
|
|
|
164
161
|
Returns:
|
|
165
162
|
Configured RocketWelderClient instance
|
|
@@ -167,4 +164,4 @@ class RocketWelderClient:
|
|
|
167
164
|
connection_str = (
|
|
168
165
|
f"shm://{buffer_name}?size={buffer_size}&metadata={metadata_size}&mode=Duplex"
|
|
169
166
|
)
|
|
170
|
-
return cls(connection_str
|
|
167
|
+
return cls(connection_str)
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""UI module for RocketWelder SDK."""
|
|
2
|
+
|
|
3
|
+
from rocket_welder_sdk.external_controls.contracts import ArrowDirection
|
|
4
|
+
|
|
5
|
+
from .controls import (
|
|
6
|
+
ArrowGridControl,
|
|
7
|
+
ControlBase,
|
|
8
|
+
IconButtonControl,
|
|
9
|
+
LabelControl,
|
|
10
|
+
)
|
|
11
|
+
from .icons import Custom, Icons, Material
|
|
12
|
+
from .ui_events_projection import UiEventsProjection
|
|
13
|
+
from .ui_service import (
|
|
14
|
+
ItemsControl,
|
|
15
|
+
UiControlFactory,
|
|
16
|
+
UiService,
|
|
17
|
+
)
|
|
18
|
+
from .value_types import (
|
|
19
|
+
Color,
|
|
20
|
+
ControlType,
|
|
21
|
+
RegionName,
|
|
22
|
+
Size,
|
|
23
|
+
Typography,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
__all__ = [
|
|
27
|
+
"ArrowDirection",
|
|
28
|
+
"ArrowGridControl",
|
|
29
|
+
"Color",
|
|
30
|
+
# Controls
|
|
31
|
+
"ControlBase",
|
|
32
|
+
# Enums
|
|
33
|
+
"ControlType",
|
|
34
|
+
"Custom",
|
|
35
|
+
"IconButtonControl",
|
|
36
|
+
# Icons
|
|
37
|
+
"Icons",
|
|
38
|
+
"ItemsControl",
|
|
39
|
+
"LabelControl",
|
|
40
|
+
"Material",
|
|
41
|
+
"RegionName",
|
|
42
|
+
"Size",
|
|
43
|
+
"Typography",
|
|
44
|
+
"UiControlFactory",
|
|
45
|
+
"UiEventsProjection",
|
|
46
|
+
# Services
|
|
47
|
+
"UiService",
|
|
48
|
+
]
|
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
"""UI Control base classes and implementations."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from abc import ABC, abstractmethod
|
|
6
|
+
from typing import TYPE_CHECKING, Any, Callable, ClassVar
|
|
7
|
+
|
|
8
|
+
from rocket_welder_sdk.external_controls.contracts import (
|
|
9
|
+
ArrowDirection,
|
|
10
|
+
ButtonDown,
|
|
11
|
+
ButtonUp,
|
|
12
|
+
KeyDown,
|
|
13
|
+
KeyUp,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
from .value_types import Color, ControlType, Size, Typography
|
|
17
|
+
|
|
18
|
+
if TYPE_CHECKING:
|
|
19
|
+
from .ui_service import UiService
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class ControlBase(ABC):
|
|
23
|
+
"""Base class for all UI controls."""
|
|
24
|
+
|
|
25
|
+
def __init__(
|
|
26
|
+
self,
|
|
27
|
+
control_id: str,
|
|
28
|
+
control_type: ControlType,
|
|
29
|
+
ui_service: UiService,
|
|
30
|
+
properties: dict[str, str] | None = None,
|
|
31
|
+
) -> None:
|
|
32
|
+
"""
|
|
33
|
+
Initialize base control.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
control_id: Unique identifier for the control
|
|
37
|
+
control_type: Type of the control
|
|
38
|
+
ui_service: Reference to parent UiService
|
|
39
|
+
properties: Initial properties
|
|
40
|
+
"""
|
|
41
|
+
self.id: str = control_id
|
|
42
|
+
self.control_type: ControlType = control_type
|
|
43
|
+
self._ui_service: UiService = ui_service
|
|
44
|
+
self._properties: dict[str, str] = properties or {}
|
|
45
|
+
self._changed: dict[str, str] = {}
|
|
46
|
+
self._is_disposed: bool = False
|
|
47
|
+
|
|
48
|
+
@property
|
|
49
|
+
def is_dirty(self) -> bool:
|
|
50
|
+
"""Check if control has uncommitted changes."""
|
|
51
|
+
return bool(self._changed)
|
|
52
|
+
|
|
53
|
+
@property
|
|
54
|
+
def changed(self) -> dict[str, str]:
|
|
55
|
+
"""Get pending changes."""
|
|
56
|
+
return self._changed.copy()
|
|
57
|
+
|
|
58
|
+
@property
|
|
59
|
+
def properties(self) -> dict[str, str]:
|
|
60
|
+
"""Get current properties including changes."""
|
|
61
|
+
props = self._properties.copy()
|
|
62
|
+
props.update(self._changed)
|
|
63
|
+
return props
|
|
64
|
+
|
|
65
|
+
def set_property(self, name: str, value: Any) -> None:
|
|
66
|
+
"""
|
|
67
|
+
Set a property value.
|
|
68
|
+
|
|
69
|
+
Args:
|
|
70
|
+
name: Property name
|
|
71
|
+
value: Property value (will be converted to string)
|
|
72
|
+
"""
|
|
73
|
+
str_value = str(value) if value is not None else ""
|
|
74
|
+
if self._properties.get(name) != str_value:
|
|
75
|
+
self._changed[name] = str_value
|
|
76
|
+
|
|
77
|
+
def commit_changes(self) -> None:
|
|
78
|
+
"""Commit pending changes to properties."""
|
|
79
|
+
self._properties.update(self._changed)
|
|
80
|
+
self._changed.clear()
|
|
81
|
+
|
|
82
|
+
@abstractmethod
|
|
83
|
+
def handle_event(self, event: Any) -> None:
|
|
84
|
+
"""
|
|
85
|
+
Handle an event for this control.
|
|
86
|
+
|
|
87
|
+
Args:
|
|
88
|
+
event: Event to handle
|
|
89
|
+
"""
|
|
90
|
+
pass
|
|
91
|
+
|
|
92
|
+
def dispose(self) -> None:
|
|
93
|
+
"""Dispose of the control."""
|
|
94
|
+
if not self._is_disposed:
|
|
95
|
+
self._is_disposed = True
|
|
96
|
+
self._ui_service.schedule_delete(self.id)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
class IconButtonControl(ControlBase):
|
|
100
|
+
"""Icon button control with click events."""
|
|
101
|
+
|
|
102
|
+
def __init__(
|
|
103
|
+
self,
|
|
104
|
+
control_id: str,
|
|
105
|
+
ui_service: UiService,
|
|
106
|
+
icon: str,
|
|
107
|
+
properties: dict[str, str] | None = None,
|
|
108
|
+
) -> None:
|
|
109
|
+
"""
|
|
110
|
+
Initialize icon button control.
|
|
111
|
+
|
|
112
|
+
Args:
|
|
113
|
+
control_id: Unique identifier
|
|
114
|
+
ui_service: Parent UiService
|
|
115
|
+
icon: SVG path for the icon
|
|
116
|
+
properties: Additional properties
|
|
117
|
+
"""
|
|
118
|
+
props = properties or {}
|
|
119
|
+
props["Icon"] = icon
|
|
120
|
+
super().__init__(control_id, ControlType.ICON_BUTTON, ui_service, props)
|
|
121
|
+
|
|
122
|
+
# Event handlers
|
|
123
|
+
self.on_button_down: Callable[[IconButtonControl], None] | None = None
|
|
124
|
+
self.on_button_up: Callable[[IconButtonControl], None] | None = None
|
|
125
|
+
|
|
126
|
+
@property
|
|
127
|
+
def icon(self) -> str:
|
|
128
|
+
"""Get icon SVG path."""
|
|
129
|
+
return self.properties.get("Icon", "")
|
|
130
|
+
|
|
131
|
+
@icon.setter
|
|
132
|
+
def icon(self, value: str) -> None:
|
|
133
|
+
"""Set icon SVG path."""
|
|
134
|
+
self.set_property("Icon", value)
|
|
135
|
+
|
|
136
|
+
@property
|
|
137
|
+
def text(self) -> str | None:
|
|
138
|
+
"""Get button text."""
|
|
139
|
+
return self.properties.get("Text")
|
|
140
|
+
|
|
141
|
+
@text.setter
|
|
142
|
+
def text(self, value: str | None) -> None:
|
|
143
|
+
"""Set button text."""
|
|
144
|
+
if value is not None:
|
|
145
|
+
self.set_property("Text", value)
|
|
146
|
+
|
|
147
|
+
@property
|
|
148
|
+
def color(self) -> Color:
|
|
149
|
+
"""Get button color."""
|
|
150
|
+
color_str = self.properties.get("Color", Color.PRIMARY.value)
|
|
151
|
+
try:
|
|
152
|
+
return Color(color_str)
|
|
153
|
+
except ValueError:
|
|
154
|
+
return Color.PRIMARY
|
|
155
|
+
|
|
156
|
+
@color.setter
|
|
157
|
+
def color(self, value: Color | str) -> None:
|
|
158
|
+
"""Set button color."""
|
|
159
|
+
if isinstance(value, Color):
|
|
160
|
+
self.set_property("Color", value.value)
|
|
161
|
+
else:
|
|
162
|
+
# Try to find matching enum
|
|
163
|
+
for color in Color:
|
|
164
|
+
if color.value == value:
|
|
165
|
+
self.set_property("Color", value)
|
|
166
|
+
return
|
|
167
|
+
raise ValueError(f"Invalid color value: {value}")
|
|
168
|
+
|
|
169
|
+
@property
|
|
170
|
+
def size(self) -> Size:
|
|
171
|
+
"""Get button size."""
|
|
172
|
+
size_str = self.properties.get("Size", Size.MEDIUM.value)
|
|
173
|
+
try:
|
|
174
|
+
return Size(size_str)
|
|
175
|
+
except ValueError:
|
|
176
|
+
return Size.MEDIUM
|
|
177
|
+
|
|
178
|
+
@size.setter
|
|
179
|
+
def size(self, value: Size | str) -> None:
|
|
180
|
+
"""Set button size."""
|
|
181
|
+
if isinstance(value, Size):
|
|
182
|
+
self.set_property("Size", value.value)
|
|
183
|
+
else:
|
|
184
|
+
# Try to find matching enum
|
|
185
|
+
for size in Size:
|
|
186
|
+
if size.value == value:
|
|
187
|
+
self.set_property("Size", value)
|
|
188
|
+
return
|
|
189
|
+
raise ValueError(f"Invalid size value: {value}")
|
|
190
|
+
|
|
191
|
+
def handle_event(self, event: Any) -> None:
|
|
192
|
+
"""Handle button events."""
|
|
193
|
+
if isinstance(event, ButtonDown) and self.on_button_down:
|
|
194
|
+
self.on_button_down(self)
|
|
195
|
+
elif isinstance(event, ButtonUp) and self.on_button_up:
|
|
196
|
+
self.on_button_up(self)
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
class ArrowGridControl(ControlBase):
|
|
200
|
+
"""Arrow grid control for directional input."""
|
|
201
|
+
|
|
202
|
+
# Mapping from key codes to arrow directions
|
|
203
|
+
KEY_TO_DIRECTION: ClassVar[dict[str, ArrowDirection]] = {
|
|
204
|
+
"ArrowUp": ArrowDirection.UP,
|
|
205
|
+
"ArrowDown": ArrowDirection.DOWN,
|
|
206
|
+
"ArrowLeft": ArrowDirection.LEFT,
|
|
207
|
+
"ArrowRight": ArrowDirection.RIGHT,
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
def __init__(
|
|
211
|
+
self, control_id: str, ui_service: UiService, properties: dict[str, str] | None = None
|
|
212
|
+
) -> None:
|
|
213
|
+
"""
|
|
214
|
+
Initialize arrow grid control.
|
|
215
|
+
|
|
216
|
+
Args:
|
|
217
|
+
control_id: Unique identifier
|
|
218
|
+
ui_service: Parent UiService
|
|
219
|
+
properties: Additional properties
|
|
220
|
+
"""
|
|
221
|
+
super().__init__(control_id, ControlType.ARROW_GRID, ui_service, properties)
|
|
222
|
+
|
|
223
|
+
# Event handlers
|
|
224
|
+
self.on_arrow_down: Callable[[ArrowGridControl, ArrowDirection], None] | None = None
|
|
225
|
+
self.on_arrow_up: Callable[[ArrowGridControl, ArrowDirection], None] | None = None
|
|
226
|
+
|
|
227
|
+
@property
|
|
228
|
+
def size(self) -> Size:
|
|
229
|
+
"""Get grid size."""
|
|
230
|
+
size_str = self.properties.get("Size", Size.MEDIUM.value)
|
|
231
|
+
try:
|
|
232
|
+
return Size(size_str)
|
|
233
|
+
except ValueError:
|
|
234
|
+
return Size.MEDIUM
|
|
235
|
+
|
|
236
|
+
@size.setter
|
|
237
|
+
def size(self, value: Size | str) -> None:
|
|
238
|
+
"""Set grid size."""
|
|
239
|
+
if isinstance(value, Size):
|
|
240
|
+
self.set_property("Size", value.value)
|
|
241
|
+
else:
|
|
242
|
+
# Try to find matching enum
|
|
243
|
+
for size in Size:
|
|
244
|
+
if size.value == value:
|
|
245
|
+
self.set_property("Size", value)
|
|
246
|
+
return
|
|
247
|
+
raise ValueError(f"Invalid size value: {value}")
|
|
248
|
+
|
|
249
|
+
@property
|
|
250
|
+
def color(self) -> Color:
|
|
251
|
+
"""Get grid color."""
|
|
252
|
+
color_str = self.properties.get("Color", Color.PRIMARY.value)
|
|
253
|
+
try:
|
|
254
|
+
return Color(color_str)
|
|
255
|
+
except ValueError:
|
|
256
|
+
return Color.PRIMARY
|
|
257
|
+
|
|
258
|
+
@color.setter
|
|
259
|
+
def color(self, value: Color | str) -> None:
|
|
260
|
+
"""Set grid color."""
|
|
261
|
+
if isinstance(value, Color):
|
|
262
|
+
self.set_property("Color", value.value)
|
|
263
|
+
else:
|
|
264
|
+
# Try to find matching enum
|
|
265
|
+
for color in Color:
|
|
266
|
+
if color.value == value:
|
|
267
|
+
self.set_property("Color", value)
|
|
268
|
+
return
|
|
269
|
+
raise ValueError(f"Invalid color value: {value}")
|
|
270
|
+
|
|
271
|
+
def handle_event(self, event: Any) -> None:
|
|
272
|
+
"""Handle keyboard events and translate to arrow events."""
|
|
273
|
+
if isinstance(event, KeyDown):
|
|
274
|
+
direction = self.KEY_TO_DIRECTION.get(event.code)
|
|
275
|
+
if direction and self.on_arrow_down:
|
|
276
|
+
self.on_arrow_down(self, direction)
|
|
277
|
+
elif isinstance(event, KeyUp):
|
|
278
|
+
direction = self.KEY_TO_DIRECTION.get(event.code)
|
|
279
|
+
if direction and self.on_arrow_up:
|
|
280
|
+
self.on_arrow_up(self, direction)
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
class LabelControl(ControlBase):
|
|
284
|
+
"""Label control for displaying text."""
|
|
285
|
+
|
|
286
|
+
def __init__(
|
|
287
|
+
self,
|
|
288
|
+
control_id: str,
|
|
289
|
+
ui_service: UiService,
|
|
290
|
+
text: str,
|
|
291
|
+
properties: dict[str, str] | None = None,
|
|
292
|
+
) -> None:
|
|
293
|
+
"""
|
|
294
|
+
Initialize label control.
|
|
295
|
+
|
|
296
|
+
Args:
|
|
297
|
+
control_id: Unique identifier
|
|
298
|
+
ui_service: Parent UiService
|
|
299
|
+
text: Label text
|
|
300
|
+
properties: Additional properties
|
|
301
|
+
"""
|
|
302
|
+
props = properties or {}
|
|
303
|
+
props["Text"] = text
|
|
304
|
+
super().__init__(control_id, ControlType.LABEL, ui_service, props)
|
|
305
|
+
|
|
306
|
+
@property
|
|
307
|
+
def text(self) -> str:
|
|
308
|
+
"""Get label text."""
|
|
309
|
+
return self.properties.get("Text", "")
|
|
310
|
+
|
|
311
|
+
@text.setter
|
|
312
|
+
def text(self, value: str) -> None:
|
|
313
|
+
"""Set label text."""
|
|
314
|
+
self.set_property("Text", value)
|
|
315
|
+
|
|
316
|
+
@property
|
|
317
|
+
def typography(self) -> Typography:
|
|
318
|
+
"""Get label typography."""
|
|
319
|
+
typo_str = self.properties.get("Typography", Typography.BODY1.value)
|
|
320
|
+
try:
|
|
321
|
+
return Typography(typo_str)
|
|
322
|
+
except ValueError:
|
|
323
|
+
return Typography.BODY1
|
|
324
|
+
|
|
325
|
+
@typography.setter
|
|
326
|
+
def typography(self, value: Typography | str) -> None:
|
|
327
|
+
"""Set label typography."""
|
|
328
|
+
if isinstance(value, Typography):
|
|
329
|
+
self.set_property("Typography", value.value)
|
|
330
|
+
else:
|
|
331
|
+
# Try to find matching enum
|
|
332
|
+
for typo in Typography:
|
|
333
|
+
if typo.value == value:
|
|
334
|
+
self.set_property("Typography", value)
|
|
335
|
+
return
|
|
336
|
+
raise ValueError(f"Invalid typography value: {value}")
|
|
337
|
+
|
|
338
|
+
@property
|
|
339
|
+
def color(self) -> Color:
|
|
340
|
+
"""Get label color."""
|
|
341
|
+
color_str = self.properties.get("Color", Color.TEXT_PRIMARY.value)
|
|
342
|
+
try:
|
|
343
|
+
return Color(color_str)
|
|
344
|
+
except ValueError:
|
|
345
|
+
return Color.TEXT_PRIMARY
|
|
346
|
+
|
|
347
|
+
@color.setter
|
|
348
|
+
def color(self, value: Color | str) -> None:
|
|
349
|
+
"""Set label color."""
|
|
350
|
+
if isinstance(value, Color):
|
|
351
|
+
self.set_property("Color", value.value)
|
|
352
|
+
else:
|
|
353
|
+
# Try to find matching enum
|
|
354
|
+
for color in Color:
|
|
355
|
+
if color.value == value:
|
|
356
|
+
self.set_property("Color", value)
|
|
357
|
+
return
|
|
358
|
+
raise ValueError(f"Invalid color value: {value}")
|
|
359
|
+
|
|
360
|
+
def handle_event(self, event: Any) -> None:
|
|
361
|
+
"""Labels typically don't handle events."""
|
|
362
|
+
pass
|