scustomtkinter 0.2.1__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.
- scustomtkinter/__init__.py +81 -0
- scustomtkinter/assets/images/error.png +0 -0
- scustomtkinter/assets/images/info.png +0 -0
- scustomtkinter/assets/images/warning.png +0 -0
- scustomtkinter/assets/sCTkThemes.json +1963 -0
- scustomtkinter/license_morecustomtkinterwidgets.txt +22 -0
- scustomtkinter/sctk_button_primary.py +366 -0
- scustomtkinter/sctk_button_secondary.py +354 -0
- scustomtkinter/sctk_button_tertiary.py +375 -0
- scustomtkinter/sctk_checkbox.py +270 -0
- scustomtkinter/sctk_combobox.py +155 -0
- scustomtkinter/sctk_core.py +15 -0
- scustomtkinter/sctk_dial.py +1472 -0
- scustomtkinter/sctk_dialog.py +701 -0
- scustomtkinter/sctk_dialog_toplevel.py +268 -0
- scustomtkinter/sctk_entry_primary.py +400 -0
- scustomtkinter/sctk_entry_secondary.py +342 -0
- scustomtkinter/sctk_file_explorer.py +879 -0
- scustomtkinter/sctk_frame.py +210 -0
- scustomtkinter/sctk_frame_labeled_primary.py +667 -0
- scustomtkinter/sctk_frame_labeled_secondary.py +598 -0
- scustomtkinter/sctk_frequency_display.py +636 -0
- scustomtkinter/sctk_label_primary.py +283 -0
- scustomtkinter/sctk_label_secondary.py +275 -0
- scustomtkinter/sctk_label_tertiary.py +278 -0
- scustomtkinter/sctk_messagebox.py +275 -0
- scustomtkinter/sctk_notebook.py +1103 -0
- scustomtkinter/sctk_optionmenu_border_mixin.py +203 -0
- scustomtkinter/sctk_optionmenu_primary.py +378 -0
- scustomtkinter/sctk_optionmenu_secondary.py +346 -0
- scustomtkinter/sctk_path_chooser.py +516 -0
- scustomtkinter/sctk_progress_bar.py +274 -0
- scustomtkinter/sctk_radiobutton.py +360 -0
- scustomtkinter/sctk_scroll_mixin.py +546 -0
- scustomtkinter/sctk_scrollable_frame.py +795 -0
- scustomtkinter/sctk_scrollbar.py +313 -0
- scustomtkinter/sctk_segmentedbutton.py +424 -0
- scustomtkinter/sctk_selector.py +581 -0
- scustomtkinter/sctk_separator.py +308 -0
- scustomtkinter/sctk_slider.py +264 -0
- scustomtkinter/sctk_smeter.py +405 -0
- scustomtkinter/sctk_smeter_bar.py +557 -0
- scustomtkinter/sctk_spinbox.py +664 -0
- scustomtkinter/sctk_switch.py +463 -0
- scustomtkinter/sctk_tableview.py +869 -0
- scustomtkinter/sctk_tabview.py +409 -0
- scustomtkinter/sctk_textbox_primary.py +291 -0
- scustomtkinter/sctk_textbox_secondary.py +225 -0
- scustomtkinter/sctk_toplevel.py +153 -0
- scustomtkinter/themeable_widget.py +938 -0
- scustomtkinter-0.2.1.dist-info/METADATA +336 -0
- scustomtkinter-0.2.1.dist-info/RECORD +101 -0
- scustomtkinter-0.2.1.dist-info/WHEEL +5 -0
- scustomtkinter-0.2.1.dist-info/entry_points.txt +2 -0
- scustomtkinter-0.2.1.dist-info/licenses/LICENSE +21 -0
- scustomtkinter-0.2.1.dist-info/licenses/scustomtkinter/license_morecustomtkinterwidgets.txt +22 -0
- scustomtkinter-0.2.1.dist-info/top_level.txt +2 -0
- scustomtkinter_pygubu/__init__.py +1 -0
- scustomtkinter_pygubu/designer/__init__.py +0 -0
- scustomtkinter_pygubu/designer/plugin.py +1854 -0
- scustomtkinter_pygubu/designer/properties.py +247 -0
- scustomtkinter_pygubu/sCTkButtonPrimarybo.py +46 -0
- scustomtkinter_pygubu/sCTkButtonSecondarybo.py +45 -0
- scustomtkinter_pygubu/sCTkButtonTertiarybo.py +44 -0
- scustomtkinter_pygubu/sCTkCheckBoxbo.py +45 -0
- scustomtkinter_pygubu/sCTkComboBoxbo.py +45 -0
- scustomtkinter_pygubu/sCTkCorebo.py +120 -0
- scustomtkinter_pygubu/sCTkDialbo.py +371 -0
- scustomtkinter_pygubu/sCTkDialogbo.py +397 -0
- scustomtkinter_pygubu/sCTkEntryPrimarybo.py +100 -0
- scustomtkinter_pygubu/sCTkEntrySecondarybo.py +98 -0
- scustomtkinter_pygubu/sCTkFileExplorerbo.py +189 -0
- scustomtkinter_pygubu/sCTkFrameLabeledPrimarybo.py +69 -0
- scustomtkinter_pygubu/sCTkFrameLabeledSecondarybo.py +71 -0
- scustomtkinter_pygubu/sCTkFramebo.py +46 -0
- scustomtkinter_pygubu/sCTkFrequencyDisplaybo.py +175 -0
- scustomtkinter_pygubu/sCTkLabelPrimarybo.py +45 -0
- scustomtkinter_pygubu/sCTkLabelSecondarybo.py +44 -0
- scustomtkinter_pygubu/sCTkLabelTertiarybo.py +45 -0
- scustomtkinter_pygubu/sCTkNotebookbo.py +392 -0
- scustomtkinter_pygubu/sCTkOptionMenuPrimarybo.py +45 -0
- scustomtkinter_pygubu/sCTkOptionMenuSecondarybo.py +39 -0
- scustomtkinter_pygubu/sCTkPathChooserbo.py +204 -0
- scustomtkinter_pygubu/sCTkProgressBarbo.py +45 -0
- scustomtkinter_pygubu/sCTkRadioButtonbo.py +45 -0
- scustomtkinter_pygubu/sCTkSMeterBarbo.py +153 -0
- scustomtkinter_pygubu/sCTkSMeterbo.py +101 -0
- scustomtkinter_pygubu/sCTkScrollableFramebo.py +66 -0
- scustomtkinter_pygubu/sCTkScrollbarbo.py +48 -0
- scustomtkinter_pygubu/sCTkSegmentedButtonbo.py +47 -0
- scustomtkinter_pygubu/sCTkSelectorbo.py +167 -0
- scustomtkinter_pygubu/sCTkSeparatorbo.py +141 -0
- scustomtkinter_pygubu/sCTkSliderbo.py +45 -0
- scustomtkinter_pygubu/sCTkSpinboxbo.py +200 -0
- scustomtkinter_pygubu/sCTkSwitchbo.py +45 -0
- scustomtkinter_pygubu/sCTkTableviewbo.py +188 -0
- scustomtkinter_pygubu/sCTkTabviewbo.py +226 -0
- scustomtkinter_pygubu/sCTkTextboxPrimarybo.py +45 -0
- scustomtkinter_pygubu/sCTkTextboxSecondarybo.py +45 -0
- scustomtkinter_pygubu/sCTkToplevelbo.py +55 -0
- scustomtkinter_pygubu/sCTkWidgetSetForPygubuDesigner.py +141 -0
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
#!/usr/bin/python3
|
|
2
|
+
"""
|
|
3
|
+
sCTkComboBox
|
|
4
|
+
|
|
5
|
+
A custom, theme-compliant parameter selection dropdown combobox widget.
|
|
6
|
+
Inherits cleanly and directly from ctk.CTkComboBox to preserve 100% of native
|
|
7
|
+
CustomTkinter features, theme tracking loops, and native input locks.
|
|
8
|
+
"""
|
|
9
|
+
import customtkinter as ctk
|
|
10
|
+
from .themeable_widget import ThemeableWidget
|
|
11
|
+
|
|
12
|
+
class sCTkComboBox(ctk.CTkComboBox, ThemeableWidget):
|
|
13
|
+
def __init__(self, master=None, **kw):
|
|
14
|
+
# 1. PARAMETER POPPING: Capture combobox-specific tracking parameters early
|
|
15
|
+
values = kw.pop("values", [""])
|
|
16
|
+
command = kw.pop("command", None)
|
|
17
|
+
variable = kw.pop("variable", None)
|
|
18
|
+
|
|
19
|
+
# 2. Fire our shared theme logic first. It automatically finds "sCTkComboBox" in the JSON
|
|
20
|
+
ThemeableWidget.__init__(self, kw)
|
|
21
|
+
|
|
22
|
+
# 3. THE MUTATION SAFEGUARD DEEP COPY:
|
|
23
|
+
self._local_defaults = dict(self.final_kw)
|
|
24
|
+
self._custom_disabled_map = dict(self._widget_disabled_map)
|
|
25
|
+
|
|
26
|
+
# 4. Initialize CustomTkinter natively with the clean final kwargs array safely
|
|
27
|
+
super().__init__(master, **self.final_kw)
|
|
28
|
+
|
|
29
|
+
# 5. Build your inner custom properties using your popped parameters safely
|
|
30
|
+
if values:
|
|
31
|
+
super().configure(values=values)
|
|
32
|
+
if isinstance(values, list) and len(values) > 0 and values[0] != "":
|
|
33
|
+
self.set(values[0])
|
|
34
|
+
|
|
35
|
+
if command: super().configure(command=command)
|
|
36
|
+
if variable: super().configure(variable=variable)
|
|
37
|
+
|
|
38
|
+
self._custom_current_state = "normal"
|
|
39
|
+
|
|
40
|
+
# 6. REGISTER LIFECYCLE HANDSHAKE HOOK:
|
|
41
|
+
self._finalize_themeable_lifecycle()
|
|
42
|
+
|
|
43
|
+
def _set_appearance_mode(self, mode_string: str):
|
|
44
|
+
"""
|
|
45
|
+
EXPERIMENTAL: no longer manually re-triggers _update_current_visual_state().
|
|
46
|
+
_update_current_visual_state() now passes raw (light, dark) tuples straight
|
|
47
|
+
through to configure() instead of pre-resolving to a single color, so CTk's
|
|
48
|
+
own appearance-mode tracking should repaint correctly on its own. If colors
|
|
49
|
+
stop following mode changes (especially while disabled), that's the signal
|
|
50
|
+
this doesn't hold and the manual re-trigger needs to come back.
|
|
51
|
+
"""
|
|
52
|
+
if hasattr(super(), "_set_appearance_mode"):
|
|
53
|
+
try:
|
|
54
|
+
super()._set_appearance_mode(mode_string)
|
|
55
|
+
except Exception:
|
|
56
|
+
pass
|
|
57
|
+
|
|
58
|
+
def configure(self, *args, **kwargs):
|
|
59
|
+
"""Handles Pygubu designer queries and manages composite state updates safely."""
|
|
60
|
+
if len(args) == 1:
|
|
61
|
+
if isinstance(args[0], dict):
|
|
62
|
+
kwargs = {**args[0], **kwargs}
|
|
63
|
+
else:
|
|
64
|
+
pname = args[0]
|
|
65
|
+
if pname == "state":
|
|
66
|
+
return ("state", "state", "state", "normal", str(self.state()))
|
|
67
|
+
|
|
68
|
+
if pname in ["fg_color", "border_color", "text_color", "hover_color"]:
|
|
69
|
+
current_state = str(self.state()).lower()
|
|
70
|
+
val = self._custom_disabled_map.get(pname) if current_state == "disabled" else self._local_defaults.get(pname)
|
|
71
|
+
return (pname, pname, pname, self._query_value(self._theme_default(pname)), self._query_value(val))
|
|
72
|
+
|
|
73
|
+
return self._configure_query(pname)
|
|
74
|
+
|
|
75
|
+
if "values" in kwargs: super().configure(values=kwargs.pop("values"))
|
|
76
|
+
if "command" in kwargs: super().configure(command=kwargs.pop("command"))
|
|
77
|
+
if "variable" in kwargs: super().configure(variable=kwargs.pop("variable"))
|
|
78
|
+
|
|
79
|
+
# Runtime overrides have to reach the map a repaint reads, or
|
|
80
|
+
# _update_current_visual_state() puts the theme value straight back --
|
|
81
|
+
# see ThemeableWidget._record_theme_overrides().
|
|
82
|
+
self._record_theme_overrides(kwargs)
|
|
83
|
+
|
|
84
|
+
if "state" in kwargs:
|
|
85
|
+
self.state(kwargs.pop("state"))
|
|
86
|
+
|
|
87
|
+
if kwargs:
|
|
88
|
+
self._drop_cleared(kwargs)
|
|
89
|
+
if kwargs:
|
|
90
|
+
return super().configure(**kwargs)
|
|
91
|
+
return None
|
|
92
|
+
|
|
93
|
+
config = configure
|
|
94
|
+
|
|
95
|
+
def get_state(self):
|
|
96
|
+
"""Explicit getter synchronized with your standalone test harness script assertions."""
|
|
97
|
+
return self.state()
|
|
98
|
+
|
|
99
|
+
def state(self, mode: str = None):
|
|
100
|
+
"""Dedicated combobox state controller."""
|
|
101
|
+
if mode is None:
|
|
102
|
+
return str(getattr(self, "_custom_current_state", "normal")).lower()
|
|
103
|
+
|
|
104
|
+
mode = mode.lower()
|
|
105
|
+
if mode in ("normal", "enabled", "active"):
|
|
106
|
+
self._custom_current_state = "normal"
|
|
107
|
+
self._update_current_visual_state()
|
|
108
|
+
|
|
109
|
+
elif mode == "disabled":
|
|
110
|
+
self._custom_current_state = "disabled"
|
|
111
|
+
self._update_current_visual_state()
|
|
112
|
+
|
|
113
|
+
# FIX: this returned nothing when SETTING a mode -- only the query
|
|
114
|
+
# branch above returned a value -- so `widget.state("disabled")` gave
|
|
115
|
+
# None. Every other themed widget returns the resulting state, and
|
|
116
|
+
# sCTkCheckBox had the identical gap fixed earlier in this audit.
|
|
117
|
+
return self._custom_current_state
|
|
118
|
+
|
|
119
|
+
def _update_current_visual_state(self):
|
|
120
|
+
"""
|
|
121
|
+
EXPERIMENTAL: passes raw (light, dark) tuples straight through to configure()
|
|
122
|
+
instead of resolving to a single color first, so CTk's native tracking can
|
|
123
|
+
handle appearance-mode repaints without help from _set_appearance_mode.
|
|
124
|
+
"""
|
|
125
|
+
is_disabled = getattr(self, "_custom_current_state", "normal") == "disabled"
|
|
126
|
+
target_map = self._custom_disabled_map if is_disabled else self._local_defaults
|
|
127
|
+
|
|
128
|
+
config_payload = {}
|
|
129
|
+
for key in ("fg_color", "border_color", "button_color", "button_hover_color",
|
|
130
|
+
"dropdown_fg_color", "dropdown_text_color", "dropdown_hover_color", "border_width", "font"):
|
|
131
|
+
val = target_map.get(key)
|
|
132
|
+
if val is not None:
|
|
133
|
+
config_payload[key] = val
|
|
134
|
+
|
|
135
|
+
# text_color is handled separately, because this widget sets CTk's own
|
|
136
|
+
# state="disabled" below -- and CTkComboBox's draw code then uses its
|
|
137
|
+
# native text_color_disabled option, overriding whatever text_color was
|
|
138
|
+
# set to. Swapping text_color out of disabled_map was therefore
|
|
139
|
+
# discarded at draw time and the theme key had no visible effect.
|
|
140
|
+
#
|
|
141
|
+
# Both options are set, so CTk chooses between them as designed.
|
|
142
|
+
normal_text = self._local_defaults.get("text_color")
|
|
143
|
+
if normal_text is not None:
|
|
144
|
+
config_payload["text_color"] = normal_text
|
|
145
|
+
disabled_text = self._custom_disabled_map.get("text_color")
|
|
146
|
+
if disabled_text is not None:
|
|
147
|
+
config_payload["text_color_disabled"] = disabled_text
|
|
148
|
+
|
|
149
|
+
if config_payload:
|
|
150
|
+
super().configure(**config_payload)
|
|
151
|
+
|
|
152
|
+
if is_disabled:
|
|
153
|
+
super().configure(state="disabled")
|
|
154
|
+
else:
|
|
155
|
+
super().configure(state="normal")
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/python3
|
|
2
|
+
"""
|
|
3
|
+
sCTk
|
|
4
|
+
|
|
5
|
+
A clean, zero-overhead wrapper subclass of ctk.CTk.
|
|
6
|
+
Eliminitates the need for end-users to import customtkinter directly,
|
|
7
|
+
acting as the singular core application window root for the sCustomTkinter library.
|
|
8
|
+
"""
|
|
9
|
+
import customtkinter as ctk
|
|
10
|
+
|
|
11
|
+
class sCTk(ctk.CTk):
|
|
12
|
+
def __init__(self, fg_color=None, **kwargs):
|
|
13
|
+
# 🔑 THE HOOK PASS: Explicitly scoop up and forward all positional/keyword arguments
|
|
14
|
+
# directly up to the native CustomTkinter top-level application root constructor safely.
|
|
15
|
+
super().__init__(fg_color=fg_color, **kwargs)
|