CTkDataTable 0.1.0__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.
@@ -0,0 +1,210 @@
1
+ """Table-wide styling options for CTkDataTable."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Mapping
6
+ from dataclasses import dataclass, fields, replace
7
+ from typing import Any, TypeAlias
8
+
9
+ from .table_column import ColorValue
10
+
11
+
12
+ @dataclass(frozen=True)
13
+ class TableStyle:
14
+ """Optional colors, spacing, and radii for a CTkDataTable.
15
+
16
+ Any field left as None falls back to the active CustomTkinter theme.
17
+ """
18
+
19
+ corner_radius: float | None = None
20
+ border_width: float | None = None
21
+ cell_padding_x: int | None = None
22
+ badge_padding_x: int | None = None
23
+ button_padding_x: int | None = None
24
+ badge_radius: float | None = None
25
+ checkbox_radius: float | None = None
26
+ progress_radius: float | None = None
27
+ pill_radius: float | None = None
28
+ action_radius: float | None = None
29
+
30
+ canvas_bg: ColorValue | None = None
31
+ surface_bg: ColorValue | None = None
32
+ row_bg: ColorValue | None = None
33
+ row_alt_bg: ColorValue | None = None
34
+ header_bg: ColorValue | None = None
35
+ footer_bg: ColorValue | None = None
36
+ hover_bg: ColorValue | None = None
37
+ selected_bg: ColorValue | None = None
38
+ selected_hover_bg: ColorValue | None = None
39
+ text_color: ColorValue | None = None
40
+ hover_text_color: ColorValue | None = None
41
+ selected_text_color: ColorValue | None = None
42
+ selected_hover_text_color: ColorValue | None = None
43
+ muted_text_color: ColorValue | None = None
44
+ header_text_color: ColorValue | None = None
45
+ footer_text_color: ColorValue | None = None
46
+ divider_color: ColorValue | None = None
47
+ header_divider_color: ColorValue | None = None
48
+ border_color: ColorValue | None = None
49
+ sort_indicator_color: ColorValue | None = None
50
+ filter_indicator_color: ColorValue | None = None
51
+ badge_bg: ColorValue | None = None
52
+ badge_text_color: ColorValue | None = None
53
+ pill_bg: ColorValue | None = None
54
+ pill_text_color: ColorValue | None = None
55
+ progress_bg: ColorValue | None = None
56
+ progress_fill: ColorValue | None = None
57
+ progress_text_color: ColorValue | None = None
58
+ link_text_color: ColorValue | None = None
59
+ checkbox_fill: ColorValue | None = None
60
+ checkbox_fill_checked: ColorValue | None = None
61
+ checkbox_border: ColorValue | None = None
62
+ checkbox_check: ColorValue | None = None
63
+ action_bg: ColorValue | None = None
64
+ action_border: ColorValue | None = None
65
+ action_text_color: ColorValue | None = None
66
+ loading_indicator_color: ColorValue | None = None
67
+
68
+
69
+ TableStyleDefinition: TypeAlias = TableStyle | Mapping[str, Any]
70
+
71
+ TABLE_STYLE_COLOR_MAP = {
72
+ "canvas_bg": "canvas_bg",
73
+ "surface_bg": "surface_bg",
74
+ "row_bg": "row_bg",
75
+ "row_alt_bg": "row_alt_bg",
76
+ "header_bg": "header_bg",
77
+ "footer_bg": "footer_bg",
78
+ "hover_bg": "hover_bg",
79
+ "selected_bg": "selected_bg",
80
+ "selected_hover_bg": "selected_hover_bg",
81
+ "text_color": "text",
82
+ "hover_text_color": "hover_text",
83
+ "selected_text_color": "selected_text",
84
+ "selected_hover_text_color": "selected_hover_text",
85
+ "muted_text_color": "muted_text",
86
+ "header_text_color": "header_text",
87
+ "footer_text_color": "footer_text",
88
+ "divider_color": "divider",
89
+ "header_divider_color": "header_divider",
90
+ "border_color": "table_border",
91
+ "sort_indicator_color": "sort_indicator",
92
+ "filter_indicator_color": "filter_indicator",
93
+ "badge_bg": "badge_default_bg",
94
+ "badge_text_color": "badge_text",
95
+ "pill_bg": "pill_bg",
96
+ "pill_text_color": "pill_text",
97
+ "progress_bg": "progress_bg",
98
+ "progress_fill": "progress_fill",
99
+ "progress_text_color": "progress_text",
100
+ "link_text_color": "link_text",
101
+ "checkbox_fill": "checkbox_fill",
102
+ "checkbox_fill_checked": "checkbox_fill_checked",
103
+ "checkbox_border": "checkbox_border",
104
+ "checkbox_check": "checkbox_check",
105
+ "action_bg": "action_bg",
106
+ "action_border": "action_border",
107
+ "action_text_color": "action_text",
108
+ "loading_indicator_color": "loading_indicator",
109
+ }
110
+
111
+ TABLE_STYLE_DIMENSION_FIELDS = {
112
+ "corner_radius",
113
+ "border_width",
114
+ "cell_padding_x",
115
+ "badge_padding_x",
116
+ "button_padding_x",
117
+ "badge_radius",
118
+ "checkbox_radius",
119
+ "progress_radius",
120
+ "pill_radius",
121
+ "action_radius",
122
+ }
123
+
124
+ _FIELD_NAMES = {field.name for field in fields(TableStyle)}
125
+ _ALIASES = {
126
+ "fg_color": "canvas_bg",
127
+ "text": "text_color",
128
+ "hover_text": "hover_text_color",
129
+ "selected_text": "selected_text_color",
130
+ "selected_hover_text": "selected_hover_text_color",
131
+ "muted_text": "muted_text_color",
132
+ "header_text": "header_text_color",
133
+ "footer_text": "footer_text_color",
134
+ "divider": "divider_color",
135
+ "header_divider": "header_divider_color",
136
+ "table_border": "border_color",
137
+ "sort_indicator": "sort_indicator_color",
138
+ "filter_indicator": "filter_indicator_color",
139
+ "badge_default_bg": "badge_bg",
140
+ "badge_text": "badge_text_color",
141
+ "pill_text": "pill_text_color",
142
+ "progress_text": "progress_text_color",
143
+ "link_text": "link_text_color",
144
+ "action_text": "action_text_color",
145
+ "loading_indicator": "loading_indicator_color",
146
+ }
147
+
148
+
149
+ def normalize_table_style(style: TableStyleDefinition | None = None, **overrides: Any) -> TableStyle:
150
+ """Return a TableStyle from a TableStyle, mapping, or keyword overrides."""
151
+
152
+ values: dict[str, Any] = {}
153
+ if style is not None:
154
+ if isinstance(style, TableStyle):
155
+ values.update(_style_values(style, include_none=False))
156
+ elif isinstance(style, Mapping):
157
+ values.update(_normalize_style_mapping(style))
158
+ else:
159
+ raise TypeError("style must be a TableStyle, mapping, or None.")
160
+ if overrides:
161
+ values.update(_normalize_style_mapping(overrides))
162
+ _validate_dimensions(values)
163
+ return TableStyle(**values)
164
+
165
+
166
+ def merge_table_style(base: TableStyle, style: TableStyleDefinition | None = None, **overrides: Any) -> TableStyle:
167
+ """Merge style options onto an existing TableStyle."""
168
+
169
+ values = _style_values(base, include_none=False)
170
+ if style is not None:
171
+ if isinstance(style, TableStyle):
172
+ values.update(_style_values(style, include_none=False))
173
+ elif isinstance(style, Mapping):
174
+ values.update(_normalize_style_mapping(style))
175
+ else:
176
+ raise TypeError("style must be a TableStyle, mapping, or None.")
177
+ if overrides:
178
+ values.update(_normalize_style_mapping(overrides))
179
+ _validate_dimensions(values)
180
+ return replace(base, **values)
181
+
182
+
183
+ def _style_values(style: TableStyle, *, include_none: bool) -> dict[str, Any]:
184
+ values = {field.name: getattr(style, field.name) for field in fields(TableStyle)}
185
+ if include_none:
186
+ return values
187
+ return {key: value for key, value in values.items() if value is not None}
188
+
189
+
190
+ def _normalize_style_mapping(style: Mapping[str, Any]) -> dict[str, Any]:
191
+ values: dict[str, Any] = {}
192
+ for raw_key, value in style.items():
193
+ key = _ALIASES.get(str(raw_key), str(raw_key))
194
+ if key not in _FIELD_NAMES:
195
+ raise ValueError(f"Unknown table style option '{raw_key}'.")
196
+ values[key] = value
197
+ return values
198
+
199
+
200
+ def _validate_dimensions(values: Mapping[str, Any]) -> None:
201
+ for key in TABLE_STYLE_DIMENSION_FIELDS:
202
+ value = values.get(key)
203
+ if value is None:
204
+ continue
205
+ try:
206
+ number = float(value)
207
+ except (TypeError, ValueError) as error:
208
+ raise TypeError(f"Table style option '{key}' must be numeric.") from error
209
+ if number < 0:
210
+ raise ValueError(f"Table style option '{key}' must not be negative.")