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.
- CTkDataTable/__init__.py +17 -0
- CTkDataTable/_utils.py +58 -0
- CTkDataTable/ctk_data_table.py +1659 -0
- CTkDataTable/examples/__init__.py +1 -0
- CTkDataTable/examples/basic_table.py +208 -0
- CTkDataTable/py.typed +1 -0
- CTkDataTable/table_column.py +446 -0
- CTkDataTable/table_events.py +18 -0
- CTkDataTable/table_model.py +603 -0
- CTkDataTable/table_renderer.py +1239 -0
- CTkDataTable/table_style.py +210 -0
- ctkdatatable-0.1.0.dist-info/METADATA +681 -0
- ctkdatatable-0.1.0.dist-info/RECORD +16 -0
- ctkdatatable-0.1.0.dist-info/WHEEL +5 -0
- ctkdatatable-0.1.0.dist-info/licenses/LICENSE +21 -0
- ctkdatatable-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -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.")
|