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,189 @@
|
|
|
1
|
+
#!/usr/bin/python3
|
|
2
|
+
"""
|
|
3
|
+
sCTkFileExplorerbo
|
|
4
|
+
|
|
5
|
+
Pygubu Builder Object for the compound FileExplorer entry that is used by pathchooser.
|
|
6
|
+
"""
|
|
7
|
+
import pygubu
|
|
8
|
+
from pygubu.api.v1 import (
|
|
9
|
+
BuilderObject,
|
|
10
|
+
register_widget,
|
|
11
|
+
register_custom_property
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
# Import the native custom class
|
|
15
|
+
from scustomtkinter.sctk_file_explorer import sCTkFileExplorer
|
|
16
|
+
from pygubu.plugins.customtkinter.widgets import CTkFrameBO
|
|
17
|
+
|
|
18
|
+
# Builder UI placement definitions
|
|
19
|
+
widget_namespace = "scustomtkinter.sctk_file_explorer"
|
|
20
|
+
widget_classname = "sCTkFileExplorer"
|
|
21
|
+
builder_namespace = "scustomtkinter"
|
|
22
|
+
section_name = "sCustomTkinter"
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class sCTkFileExplorerBO(BuilderObject):
|
|
26
|
+
class_ = sCTkFileExplorer
|
|
27
|
+
|
|
28
|
+
# Define custom plugin properties (Note: 'title' has been completely removed)
|
|
29
|
+
OPTIONS_CUSTOM = (
|
|
30
|
+
"width", "height", "type", "initialdir", "initialfile",
|
|
31
|
+
"filetypes", "state", "command", "double_click_command",
|
|
32
|
+
"selection_color"
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
# Merge custom extensions cleanly on top of core container frame attributes
|
|
36
|
+
properties = CTkFrameBO.properties + OPTIONS_CUSTOM
|
|
37
|
+
command_properties = ("command", "double_click_command")
|
|
38
|
+
|
|
39
|
+
def _process_property_value(self, pname, value):
|
|
40
|
+
"""Passes values directly to allow core widget validations to handle exceptions."""
|
|
41
|
+
return super()._process_property_value(pname, value)
|
|
42
|
+
|
|
43
|
+
def _code_define_callback_args(self, cmd_pname, cmd):
|
|
44
|
+
"""
|
|
45
|
+
Declares what each callback receives, so the generated stub has
|
|
46
|
+
matching parameters.
|
|
47
|
+
|
|
48
|
+
FIX: without this, pygubu generated a stub with no arguments --
|
|
49
|
+
|
|
50
|
+
def single_cb(self):
|
|
51
|
+
pass
|
|
52
|
+
|
|
53
|
+
-- and the widget called it with the selected path:
|
|
54
|
+
|
|
55
|
+
TypeError: single_cb() takes 1 positional argument but 2 were given
|
|
56
|
+
|
|
57
|
+
The two callbacks differ. `command` receives the path alone;
|
|
58
|
+
`double_click_command` receives the WIDGET and the path, which is how
|
|
59
|
+
sCTkPathChooser drives it (it reads args[-1] to get the path).
|
|
60
|
+
"""
|
|
61
|
+
if cmd_pname == "double_click_command":
|
|
62
|
+
return ("explorer", "selected_path")
|
|
63
|
+
return ("selected_path",)
|
|
64
|
+
|
|
65
|
+
def _code_set_property(self, targetid, pname, value, code_bag):
|
|
66
|
+
"""
|
|
67
|
+
Emits `filetypes` as a real Python list, not a quoted string.
|
|
68
|
+
|
|
69
|
+
FIX: the bracketed form contains double quotes, and the default
|
|
70
|
+
handler wraps the whole value in double quotes again:
|
|
71
|
+
|
|
72
|
+
sctkfileexplorer1.configure(filetypes="[".py"]", ...)
|
|
73
|
+
^^^^^^^^^
|
|
74
|
+
SyntaxError: invalid syntax
|
|
75
|
+
|
|
76
|
+
Emitting the literal unquoted gives valid Python and a real list, so
|
|
77
|
+
the widget receives one directly rather than parsing a string back
|
|
78
|
+
out of it. Same approach sCTkSelectorbo uses for `items`.
|
|
79
|
+
|
|
80
|
+
A bare comma-separated value -- the other accepted form -- has no
|
|
81
|
+
brackets and no quotes, so it is emitted as a quoted string and parsed
|
|
82
|
+
by the widget as usual.
|
|
83
|
+
"""
|
|
84
|
+
if pname == "filetypes" and value:
|
|
85
|
+
text = str(value).strip()
|
|
86
|
+
if text.startswith("[") and text.endswith("]"):
|
|
87
|
+
code_bag[pname] = text
|
|
88
|
+
return None
|
|
89
|
+
return super()._code_set_property(targetid, pname, value, code_bag)
|
|
90
|
+
|
|
91
|
+
# NOTE: `type` and `filetypes` constrain each other in the WIDGET, but the
|
|
92
|
+
# inspector does not follow.
|
|
93
|
+
#
|
|
94
|
+
# Setting filetypes switches the widget to file mode, and choosing
|
|
95
|
+
# directory clears the filter -- see sCTkFileExplorer. The widget applies
|
|
96
|
+
# that to itself, and generated code is correct either way, because the
|
|
97
|
+
# widget corrects the combination at construction.
|
|
98
|
+
#
|
|
99
|
+
# The Designer keeps its own copy of the properties, so the inspector goes
|
|
100
|
+
# on showing the old value: adding a filter leaves `type` reading blank
|
|
101
|
+
# while the widget has switched to file mode. A set_property() override
|
|
102
|
+
# writing the companion value back into wmeta was tried and does not
|
|
103
|
+
# reach the live tree node, so it has been removed rather than left as
|
|
104
|
+
# dead code implying a behaviour that does not happen.
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
# Register the widget into Pygubu's layout parsing engine
|
|
108
|
+
builder_id = f"{builder_namespace}.{widget_classname}"
|
|
109
|
+
register_widget(builder_id, sCTkFileExplorerBO, 'sCTkFileExplorer', ("ttk", section_name))
|
|
110
|
+
|
|
111
|
+
# =========================================================================
|
|
112
|
+
# Custom Property Designer Registration Maps
|
|
113
|
+
# =========================================================================
|
|
114
|
+
|
|
115
|
+
register_custom_property(
|
|
116
|
+
builder_id,
|
|
117
|
+
"command",
|
|
118
|
+
"commandentry",
|
|
119
|
+
help="Method callback string triggered on single-click file item highlight"
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
register_custom_property(
|
|
123
|
+
builder_id,
|
|
124
|
+
"double_click_command",
|
|
125
|
+
"commandentry",
|
|
126
|
+
help="Method callback string triggered on double-click selection"
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
register_custom_property(
|
|
130
|
+
builder_id,
|
|
131
|
+
"width",
|
|
132
|
+
"naturalnumber",
|
|
133
|
+
help="Total horizontal pixel constraint footprint assigned to the layout canvas wrapper"
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
register_custom_property(
|
|
137
|
+
builder_id,
|
|
138
|
+
"height",
|
|
139
|
+
"naturalnumber",
|
|
140
|
+
help="Total vertical pixel constraint footprint assigned to the layout canvas wrapper"
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
register_custom_property(
|
|
144
|
+
builder_id,
|
|
145
|
+
"type",
|
|
146
|
+
"choice",
|
|
147
|
+
values=("", "file", "directory"),
|
|
148
|
+
state="readonly",
|
|
149
|
+
default_value="directory",
|
|
150
|
+
help="What the explorer selects. The widget's own default is 'directory'; "
|
|
151
|
+
"setting filetypes switches it to 'file'."
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
register_custom_property(
|
|
155
|
+
builder_id,
|
|
156
|
+
"initialdir",
|
|
157
|
+
"entry",
|
|
158
|
+
help="Default starting directory path location string"
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
register_custom_property(
|
|
162
|
+
builder_id,
|
|
163
|
+
"initialfile",
|
|
164
|
+
"entry",
|
|
165
|
+
help="Default starting highlight focus target file path string"
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
register_custom_property(
|
|
169
|
+
builder_id,
|
|
170
|
+
"filetypes",
|
|
171
|
+
"entry",
|
|
172
|
+
help='Filter by file extension. Preferred: [".py", ".txt"]. Bare comma-separated (.py, .txt) also works, but cannot contain a comma inside a value.'
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
register_custom_property(
|
|
176
|
+
builder_id,
|
|
177
|
+
"state",
|
|
178
|
+
"choice",
|
|
179
|
+
values=("", "normal", "disabled"),
|
|
180
|
+
state="readonly",
|
|
181
|
+
help="Set widget active visibility or input interaction lockdown state"
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
register_custom_property(
|
|
185
|
+
builder_id, "selection_color", "colorentry",
|
|
186
|
+
help="Colour of the highlighted row. Blank uses the theme's "
|
|
187
|
+
"selection_color. Separate from btn_fg, which colours the navigation "
|
|
188
|
+
"buttons -- changing one does not affect the other."
|
|
189
|
+
)
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
#!/usr/bin/python3
|
|
2
|
+
"""
|
|
3
|
+
sCTkFrameLabeledPrimary
|
|
4
|
+
|
|
5
|
+
Similer to ttk.labelframe built on ctkscrollableframe with scrollbars hidden
|
|
6
|
+
|
|
7
|
+
UI source file: sCTkFrameLabeledPrimary.ui
|
|
8
|
+
"""
|
|
9
|
+
import tkinter as tk
|
|
10
|
+
import tkinter.ttk as ttk
|
|
11
|
+
from customtkinter import CTkScrollableFrame
|
|
12
|
+
from pygubu.api.v1 import (
|
|
13
|
+
BuilderObject,
|
|
14
|
+
register_widget,
|
|
15
|
+
register_custom_property)
|
|
16
|
+
|
|
17
|
+
from pygubu.plugins.customtkinter.scrollableframe import CTkScrollableFrameBO
|
|
18
|
+
|
|
19
|
+
from scustomtkinter.sctk_frame_labeled_primary import sCTkFrameLabeledPrimary
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
#
|
|
23
|
+
# Builder definition section
|
|
24
|
+
#
|
|
25
|
+
widget_namespace = "scustomtkinter.sctk_frame_labeled_primary"
|
|
26
|
+
widget_classname = "sCTkFrameLabeledPrimary"
|
|
27
|
+
builder_namespace = "scustomtkinter"
|
|
28
|
+
section_name = "sCustomTkinter"
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
container = True
|
|
32
|
+
# CTkScrollableFrame does some weird things
|
|
33
|
+
# with layout so disabled container layout here on purpose.
|
|
34
|
+
container_layout = False
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class sCTkFrameLabeledPrimaryBO(CTkScrollableFrameBO):
|
|
38
|
+
class_ = sCTkFrameLabeledPrimary
|
|
39
|
+
|
|
40
|
+
# state was never declared here, so the property did not reach the
|
|
41
|
+
# inspector at all -- even though the widget implements it fully, with its
|
|
42
|
+
# own state()/get_state() and a disabled_map that dims the border and the
|
|
43
|
+
# label. sCTkScrollableFramebo declares it the same way.
|
|
44
|
+
OPTIONS_CUSTOM = ("state",)
|
|
45
|
+
properties = CTkScrollableFrameBO.properties + OPTIONS_CUSTOM
|
|
46
|
+
|
|
47
|
+
OPTIONS_CUSTOM_DEFAULTS = {
|
|
48
|
+
"state": "normal",
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def code_imports(self):
|
|
53
|
+
# should return an iterable of (module, classname/function) to import
|
|
54
|
+
# or None
|
|
55
|
+
imports = [(widget_namespace, widget_classname)]
|
|
56
|
+
imports.extend(self.code_extra_imports())
|
|
57
|
+
return imports
|
|
58
|
+
|
|
59
|
+
builder_id = f"{builder_namespace}.{widget_classname}"
|
|
60
|
+
register_widget(
|
|
61
|
+
builder_id, sCTkFrameLabeledPrimaryBO, widget_classname, ("ttk", section_name)
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
register_custom_property(
|
|
65
|
+
builder_id, "state", "choice", values=("normal", "disabled"),
|
|
66
|
+
state="readonly", default_value="normal",
|
|
67
|
+
help="Disabled dims the border and the label. The contents keep their own "
|
|
68
|
+
"state -- disabling the frame does not disable what is inside it."
|
|
69
|
+
)
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#!/usr/bin/python3
|
|
2
|
+
"""
|
|
3
|
+
sCTkFrameLabeledSecondary
|
|
4
|
+
|
|
5
|
+
Similer to ttk.labelframe built on ctkscrollableframe with scrollbars hidden
|
|
6
|
+
|
|
7
|
+
UI source file: sCTkFrameLabeledSecondary.ui
|
|
8
|
+
"""
|
|
9
|
+
import tkinter as tk
|
|
10
|
+
import tkinter.ttk as ttk
|
|
11
|
+
from customtkinter import CTkScrollableFrame
|
|
12
|
+
from pygubu.api.v1 import (
|
|
13
|
+
BuilderObject,
|
|
14
|
+
register_widget,
|
|
15
|
+
register_custom_property
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
from pygubu.plugins.customtkinter import nsctk
|
|
19
|
+
from pygubu.plugins.customtkinter.scrollableframe import CTkScrollableFrameBO
|
|
20
|
+
from pygubu.api.v1 import copy_custom_property
|
|
21
|
+
|
|
22
|
+
from scustomtkinter.sctk_frame_labeled_secondary import sCTkFrameLabeledSecondary
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
#
|
|
26
|
+
# Builder definition section
|
|
27
|
+
#
|
|
28
|
+
widget_namespace = "scustomtkinter.sctk_frame_labeled_secondary"
|
|
29
|
+
widget_classname = "sCTkFrameLabeledSecondary"
|
|
30
|
+
builder_namespace = "scustomtkinter"
|
|
31
|
+
section_name = "sCustomTkinter"
|
|
32
|
+
|
|
33
|
+
container = True
|
|
34
|
+
# CTkScrollableFrame does some weird things
|
|
35
|
+
# with layout so disabled container layout here on purpose.
|
|
36
|
+
container_layout = False
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class sCTkFrameLabeledSecondaryBO(CTkScrollableFrameBO):
|
|
40
|
+
class_ = sCTkFrameLabeledSecondary
|
|
41
|
+
|
|
42
|
+
# state was never declared here, so the property did not reach the
|
|
43
|
+
# inspector at all -- even though the widget implements it fully, with its
|
|
44
|
+
# own state()/get_state() and a disabled_map that dims the border and the
|
|
45
|
+
# label. sCTkScrollableFramebo declares it the same way.
|
|
46
|
+
OPTIONS_CUSTOM = ("state",)
|
|
47
|
+
properties = CTkScrollableFrameBO.properties + OPTIONS_CUSTOM
|
|
48
|
+
|
|
49
|
+
OPTIONS_CUSTOM_DEFAULTS = {
|
|
50
|
+
"state": "normal",
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
def code_imports(self):
|
|
54
|
+
# should return an iterable of (module, classname/function) to import
|
|
55
|
+
# or None
|
|
56
|
+
imports = [(widget_namespace, widget_classname)]
|
|
57
|
+
imports.extend(self.code_extra_imports())
|
|
58
|
+
return imports
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
builder_id = f"{builder_namespace}.{widget_classname}"
|
|
62
|
+
register_widget(
|
|
63
|
+
builder_id, sCTkFrameLabeledSecondaryBO, widget_classname, ("ttk", section_name)
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
register_custom_property(
|
|
67
|
+
builder_id, "state", "choice", values=("normal", "disabled"),
|
|
68
|
+
state="readonly", default_value="normal",
|
|
69
|
+
help="Disabled dims the border and the label. The contents keep their own "
|
|
70
|
+
"state -- disabling the frame does not disable what is inside it."
|
|
71
|
+
)
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#!/usr/bin/python3
|
|
2
|
+
"""
|
|
3
|
+
sCTkFrame
|
|
4
|
+
|
|
5
|
+
subclass of Frame tuned for this ux
|
|
6
|
+
|
|
7
|
+
UI source file: sCTkFrame.ui
|
|
8
|
+
"""
|
|
9
|
+
import tkinter as tk
|
|
10
|
+
import tkinter.ttk as ttk
|
|
11
|
+
from customtkinter import CTkFrame
|
|
12
|
+
from pygubu.api.v1 import (
|
|
13
|
+
BuilderObject,
|
|
14
|
+
register_widget,
|
|
15
|
+
register_custom_property
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
from pygubu.plugins.customtkinter import nsctk
|
|
19
|
+
from pygubu.plugins.customtkinter.widgets import CTkFrameBO
|
|
20
|
+
from pygubu.api.v1 import copy_custom_property
|
|
21
|
+
|
|
22
|
+
from scustomtkinter.sctk_frame import sCTkFrame
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
#
|
|
26
|
+
# Builder definition section
|
|
27
|
+
#
|
|
28
|
+
widget_namespace = "scustomtkinter.sctk_frame"
|
|
29
|
+
widget_classname = "sCTkFrame"
|
|
30
|
+
builder_namespace = "scustomtkinter"
|
|
31
|
+
section_name = "sCustomTkinter"
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class sCTkFrameBO(CTkFrameBO):
|
|
35
|
+
class_ = sCTkFrame
|
|
36
|
+
|
|
37
|
+
def code_imports(self):
|
|
38
|
+
# should return an iterable of (module, classname/function) to import
|
|
39
|
+
# or None
|
|
40
|
+
return [(widget_namespace, widget_classname)]
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
builder_id = f"{builder_namespace}.{widget_classname}"
|
|
44
|
+
register_widget(
|
|
45
|
+
builder_id, sCTkFrameBO, widget_classname, ("ttk", section_name)
|
|
46
|
+
)
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
#!/usr/bin/python3
|
|
2
|
+
"""
|
|
3
|
+
sCTkFrequencyDisplay
|
|
4
|
+
|
|
5
|
+
Pygubu builder object for the grouped numeric readout.
|
|
6
|
+
"""
|
|
7
|
+
from pygubu.api.v1 import (
|
|
8
|
+
register_widget,
|
|
9
|
+
register_custom_property,
|
|
10
|
+
)
|
|
11
|
+
from pygubu.plugins.customtkinter.widgets import CTkFrameBO
|
|
12
|
+
|
|
13
|
+
from scustomtkinter.sctk_frequency_display import sCTkFrequencyDisplay
|
|
14
|
+
|
|
15
|
+
widget_namespace = "scustomtkinter.sctk_frequency_display"
|
|
16
|
+
widget_classname = "sCTkFrequencyDisplay"
|
|
17
|
+
builder_namespace = "scustomtkinter"
|
|
18
|
+
section_name = "sCustomTkinter"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class sCTkFrequencyDisplayBO(CTkFrameBO):
|
|
22
|
+
class_ = sCTkFrequencyDisplay
|
|
23
|
+
|
|
24
|
+
OPTIONS_CUSTOM = (
|
|
25
|
+
"digits", "signed", "value", "delimiter", "font_size",
|
|
26
|
+
"selectable", "min_digit", "state",
|
|
27
|
+
)
|
|
28
|
+
properties = CTkFrameBO.properties + OPTIONS_CUSTOM
|
|
29
|
+
command_properties = ("command",)
|
|
30
|
+
|
|
31
|
+
OPTIONS_CUSTOM_DEFAULTS = {
|
|
32
|
+
"digits": "10",
|
|
33
|
+
"signed": "False",
|
|
34
|
+
"value": "0",
|
|
35
|
+
"delimiter": ".",
|
|
36
|
+
"font_size": "34",
|
|
37
|
+
"selectable": "True",
|
|
38
|
+
"min_digit": "1",
|
|
39
|
+
"state": "normal",
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
container = False
|
|
43
|
+
|
|
44
|
+
def realize(self, parent, extra_init_args: dict = None):
|
|
45
|
+
"""
|
|
46
|
+
Builds the readout with its properties as constructor arguments.
|
|
47
|
+
|
|
48
|
+
digits and signed change the LAYOUT, so they have to arrive as real
|
|
49
|
+
values rather than being set afterwards -- a readout that builds at
|
|
50
|
+
ten digits and shrinks to four flickers through the wrong size on
|
|
51
|
+
every Designer repaint.
|
|
52
|
+
"""
|
|
53
|
+
if extra_init_args is None:
|
|
54
|
+
extra_init_args = {}
|
|
55
|
+
|
|
56
|
+
props = self.wmeta.properties
|
|
57
|
+
init_args = {
|
|
58
|
+
"digits": int(props.get("digits", 10) or 10),
|
|
59
|
+
"signed": self._as_bool(props.get("signed", "False")),
|
|
60
|
+
"value": int(props.get("value", 0) or 0),
|
|
61
|
+
"delimiter": props.get("delimiter", "."),
|
|
62
|
+
"font_size": int(props.get("font_size", 34) or 34),
|
|
63
|
+
"selectable": self._as_bool(props.get("selectable", "True")),
|
|
64
|
+
"min_digit": int(props.get("min_digit", 1) or 0),
|
|
65
|
+
"state": props.get("state", "normal"),
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
for prop in self.OPTIONS_CUSTOM:
|
|
69
|
+
extra_init_args.pop(prop, None)
|
|
70
|
+
init_args.update(extra_init_args)
|
|
71
|
+
|
|
72
|
+
real_master = parent.widget if hasattr(parent, "widget") else parent
|
|
73
|
+
self.widget = self.class_(real_master, **init_args)
|
|
74
|
+
return self.widget
|
|
75
|
+
|
|
76
|
+
@staticmethod
|
|
77
|
+
def _as_bool(value):
|
|
78
|
+
"""bool("False") is True, and the Designer sends strings."""
|
|
79
|
+
if isinstance(value, str):
|
|
80
|
+
return value.strip().lower() in ("true", "1", "yes", "on")
|
|
81
|
+
return bool(value)
|
|
82
|
+
|
|
83
|
+
def _process_property_value(self, pname, value):
|
|
84
|
+
if pname in ("digits", "value", "font_size", "min_digit"):
|
|
85
|
+
return int(value)
|
|
86
|
+
if pname in ("signed", "selectable"):
|
|
87
|
+
return self._as_bool(value)
|
|
88
|
+
return super()._process_property_value(pname, value)
|
|
89
|
+
|
|
90
|
+
def _code_set_property(self, targetid, pname, value, code_bag):
|
|
91
|
+
"""Numbers and booleans emit as tokens; the rest keep their quotes."""
|
|
92
|
+
if pname in ("digits", "value", "font_size", "min_digit",
|
|
93
|
+
"signed", "selectable"):
|
|
94
|
+
code_bag[pname] = str(value).strip("'\"")
|
|
95
|
+
elif pname in ("delimiter", "state"):
|
|
96
|
+
code_bag[pname] = f"'{str(value).strip(chr(39) + chr(34))}'"
|
|
97
|
+
else:
|
|
98
|
+
super()._code_set_property(targetid, pname, value, code_bag)
|
|
99
|
+
|
|
100
|
+
def _code_define_callback_args(self, cmd_pname, cmd):
|
|
101
|
+
"""
|
|
102
|
+
Declares that `command` receives the step, so the generated stub has
|
|
103
|
+
a matching parameter.
|
|
104
|
+
|
|
105
|
+
Without this a user writing a handler has no indication that the
|
|
106
|
+
selected digit's place value is being handed to them -- which is the
|
|
107
|
+
entire point of the callback.
|
|
108
|
+
"""
|
|
109
|
+
return ("step",)
|
|
110
|
+
|
|
111
|
+
def code_imports(self):
|
|
112
|
+
imports = [(widget_namespace, widget_classname)]
|
|
113
|
+
imports.extend(self.code_extra_imports())
|
|
114
|
+
return imports
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
builder_id = f"{builder_namespace}.{widget_classname}"
|
|
118
|
+
register_widget(builder_id, sCTkFrequencyDisplayBO, widget_classname,
|
|
119
|
+
("ttk", section_name))
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
# ---------------------------------------------------------------------------
|
|
123
|
+
# Inspector properties
|
|
124
|
+
# ---------------------------------------------------------------------------
|
|
125
|
+
register_custom_property(
|
|
126
|
+
builder_id, "digits", "naturalnumber", default_value="10",
|
|
127
|
+
help="How many digit positions. Ten reaches into the GHz as "
|
|
128
|
+
"x.xxx.xxx.xxx; four suits a signed offset. Leading groups are "
|
|
129
|
+
"hidden until they hold something, and the layout does not move "
|
|
130
|
+
"when one appears.")
|
|
131
|
+
|
|
132
|
+
register_custom_property(
|
|
133
|
+
builder_id, "signed", "choice", values=("True", "False"),
|
|
134
|
+
state="readonly", default_value="False",
|
|
135
|
+
help="Shows a leading + or -, for an offset rather than a frequency. "
|
|
136
|
+
"The sign is always drawn, even when the leading digits are not.")
|
|
137
|
+
|
|
138
|
+
register_custom_property(
|
|
139
|
+
builder_id, "value", "entry", default_value="0",
|
|
140
|
+
help="The value shown, as an integer -- Hz for a frequency.")
|
|
141
|
+
|
|
142
|
+
register_custom_property(
|
|
143
|
+
builder_id, "delimiter", "entry", default_value=".",
|
|
144
|
+
help="What separates the groups of three. Changeable at any time, "
|
|
145
|
+
"because it is a display preference the whole interface shares.")
|
|
146
|
+
|
|
147
|
+
register_custom_property(
|
|
148
|
+
builder_id, "font_size", "naturalnumber", default_value="34",
|
|
149
|
+
help="Point size of the digits. The FAMILY comes from the theme and "
|
|
150
|
+
"should stay fixed-width -- a proportional font makes 1 and 8 "
|
|
151
|
+
"different widths, so the digits shift as the numbers change.")
|
|
152
|
+
|
|
153
|
+
register_custom_property(
|
|
154
|
+
builder_id, "selectable", "choice", values=("True", "False"),
|
|
155
|
+
state="readonly", default_value="True",
|
|
156
|
+
help="Whether clicking a digit selects it. The selection IS the tuning "
|
|
157
|
+
"step, so a readout that is only a readout should set this False.")
|
|
158
|
+
|
|
159
|
+
register_custom_property(
|
|
160
|
+
builder_id, "min_digit", "naturalnumber", default_value="1",
|
|
161
|
+
help="The smallest selectable digit, as a power of ten. 1 means the "
|
|
162
|
+
"units digit is shown but cannot be tuned -- right for a rig that "
|
|
163
|
+
"steps in whole 10 Hz.")
|
|
164
|
+
|
|
165
|
+
register_custom_property(
|
|
166
|
+
builder_id, "state", "choice", values=("normal", "disabled"),
|
|
167
|
+
state="readonly", default_value="normal",
|
|
168
|
+
help="Disabled dims the digits and stops selection. The value keeps "
|
|
169
|
+
"updating: a display that froze while greyed would look like one "
|
|
170
|
+
"showing a current reading.")
|
|
171
|
+
|
|
172
|
+
register_custom_property(
|
|
173
|
+
builder_id, "command", "commandentry",
|
|
174
|
+
help="Called with the new step, in units, when the selected digit "
|
|
175
|
+
"changes. 100 means the hundreds digit -- 100 Hz per detent.")
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#!/usr/bin/python3
|
|
2
|
+
"""
|
|
3
|
+
sCTkLabelPrimary
|
|
4
|
+
|
|
5
|
+
The primary label used for headers etc.
|
|
6
|
+
|
|
7
|
+
UI source file: sCTkLabelPrimary.ui
|
|
8
|
+
"""
|
|
9
|
+
import tkinter as tk
|
|
10
|
+
import tkinter.ttk as ttk
|
|
11
|
+
from customtkinter import CTkLabel
|
|
12
|
+
from pygubu.api.v1 import (
|
|
13
|
+
BuilderObject,
|
|
14
|
+
register_widget,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
from scustomtkinter.sctk_label_primary import sCTkLabelPrimary
|
|
18
|
+
from pygubu.plugins.customtkinter.widgets import CTkLabelBO
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
#
|
|
22
|
+
# Builder definition section
|
|
23
|
+
#
|
|
24
|
+
widget_namespace = "scustomtkinter.sctk_label_primary"
|
|
25
|
+
widget_classname = "sCTkLabelPrimary"
|
|
26
|
+
builder_namespace = "scustomtkinter"
|
|
27
|
+
section_name = "sCustomTkinter"
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class sCTkLabelPrimaryBO(CTkLabelBO):
|
|
31
|
+
class_ = sCTkLabelPrimary
|
|
32
|
+
|
|
33
|
+
def code_imports(self):
|
|
34
|
+
# should return an iterable of (module, classname/function) to import
|
|
35
|
+
# or None
|
|
36
|
+
imports = [(widget_namespace, widget_classname)]
|
|
37
|
+
imports.extend(self.code_extra_imports())
|
|
38
|
+
return imports
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
builder_id = f"{builder_namespace}.{widget_classname}"
|
|
42
|
+
register_widget(
|
|
43
|
+
builder_id, sCTkLabelPrimaryBO, widget_classname, ("ttk", section_name)
|
|
44
|
+
)
|
|
45
|
+
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
#!/usr/bin/python3
|
|
2
|
+
"""
|
|
3
|
+
sCTkLabelSecondary
|
|
4
|
+
|
|
5
|
+
The secondary label used for general use.
|
|
6
|
+
|
|
7
|
+
UI source file: sCTkLabelSecondary.ui
|
|
8
|
+
"""
|
|
9
|
+
import tkinter as tk
|
|
10
|
+
import tkinter.ttk as ttk
|
|
11
|
+
from customtkinter import CTkLabel
|
|
12
|
+
from pygubu.api.v1 import (
|
|
13
|
+
BuilderObject,
|
|
14
|
+
register_widget,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
from pygubu.plugins.customtkinter.widgets import CTkLabelBO
|
|
18
|
+
from scustomtkinter.sctk_label_secondary import sCTkLabelSecondary
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
#
|
|
22
|
+
# Builder definition section
|
|
23
|
+
#
|
|
24
|
+
widget_namespace = "scustomtkinter.sctk_label_secondary"
|
|
25
|
+
widget_classname = "sCTkLabelSecondary"
|
|
26
|
+
builder_namespace = "scustomtkinter"
|
|
27
|
+
section_name = "sCustomTkinter"
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class sCTkLabelSecondaryBO(CTkLabelBO):
|
|
31
|
+
class_ = sCTkLabelSecondary
|
|
32
|
+
|
|
33
|
+
def code_imports(self):
|
|
34
|
+
# should return an iterable of (module, classname/function) to import
|
|
35
|
+
# or None
|
|
36
|
+
imports = [(widget_namespace, widget_classname)]
|
|
37
|
+
imports.extend(self.code_extra_imports())
|
|
38
|
+
return imports
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
builder_id = f"{builder_namespace}.{widget_classname}"
|
|
42
|
+
register_widget(
|
|
43
|
+
builder_id, sCTkLabelSecondaryBO, widget_classname, ("ttk", section_name)
|
|
44
|
+
)
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#!/usr/bin/python3
|
|
2
|
+
"""
|
|
3
|
+
sCTkLabelTertiary
|
|
4
|
+
|
|
5
|
+
3rd level Label used for notes
|
|
6
|
+
|
|
7
|
+
UI source file: sCTkLabelTertiary.ui
|
|
8
|
+
"""
|
|
9
|
+
import tkinter as tk
|
|
10
|
+
import tkinter.ttk as ttk
|
|
11
|
+
from customtkinter import CTkLabel
|
|
12
|
+
from pygubu.api.v1 import (
|
|
13
|
+
BuilderObject,
|
|
14
|
+
register_widget,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
from pygubu.plugins.customtkinter.widgets import CTkLabelBO
|
|
18
|
+
from scustomtkinter.sctk_label_tertiary import sCTkLabelTertiary
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
#
|
|
22
|
+
# Builder definition section
|
|
23
|
+
#
|
|
24
|
+
widget_namespace = "scustomtkinter.sctk_label_tertiary"
|
|
25
|
+
widget_classname = "sCTkLabelTertiary"
|
|
26
|
+
builder_namespace = "scustomtkinter"
|
|
27
|
+
section_name = "sCustomTkinter"
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class sCTkLabelTertiaryBO(CTkLabelBO):
|
|
31
|
+
class_ = sCTkLabelTertiary
|
|
32
|
+
|
|
33
|
+
def code_imports(self):
|
|
34
|
+
# should return an iterable of (module, classname/function) to import
|
|
35
|
+
# or None
|
|
36
|
+
imports = [(widget_namespace, widget_classname)]
|
|
37
|
+
imports.extend(self.code_extra_imports())
|
|
38
|
+
return imports
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
builder_id = f"{builder_namespace}.{widget_classname}"
|
|
42
|
+
register_widget(
|
|
43
|
+
builder_id, sCTkLabelTertiaryBO, widget_classname, ("ttk", section_name)
|
|
44
|
+
)
|
|
45
|
+
|