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.
Files changed (101) hide show
  1. scustomtkinter/__init__.py +81 -0
  2. scustomtkinter/assets/images/error.png +0 -0
  3. scustomtkinter/assets/images/info.png +0 -0
  4. scustomtkinter/assets/images/warning.png +0 -0
  5. scustomtkinter/assets/sCTkThemes.json +1963 -0
  6. scustomtkinter/license_morecustomtkinterwidgets.txt +22 -0
  7. scustomtkinter/sctk_button_primary.py +366 -0
  8. scustomtkinter/sctk_button_secondary.py +354 -0
  9. scustomtkinter/sctk_button_tertiary.py +375 -0
  10. scustomtkinter/sctk_checkbox.py +270 -0
  11. scustomtkinter/sctk_combobox.py +155 -0
  12. scustomtkinter/sctk_core.py +15 -0
  13. scustomtkinter/sctk_dial.py +1472 -0
  14. scustomtkinter/sctk_dialog.py +701 -0
  15. scustomtkinter/sctk_dialog_toplevel.py +268 -0
  16. scustomtkinter/sctk_entry_primary.py +400 -0
  17. scustomtkinter/sctk_entry_secondary.py +342 -0
  18. scustomtkinter/sctk_file_explorer.py +879 -0
  19. scustomtkinter/sctk_frame.py +210 -0
  20. scustomtkinter/sctk_frame_labeled_primary.py +667 -0
  21. scustomtkinter/sctk_frame_labeled_secondary.py +598 -0
  22. scustomtkinter/sctk_frequency_display.py +636 -0
  23. scustomtkinter/sctk_label_primary.py +283 -0
  24. scustomtkinter/sctk_label_secondary.py +275 -0
  25. scustomtkinter/sctk_label_tertiary.py +278 -0
  26. scustomtkinter/sctk_messagebox.py +275 -0
  27. scustomtkinter/sctk_notebook.py +1103 -0
  28. scustomtkinter/sctk_optionmenu_border_mixin.py +203 -0
  29. scustomtkinter/sctk_optionmenu_primary.py +378 -0
  30. scustomtkinter/sctk_optionmenu_secondary.py +346 -0
  31. scustomtkinter/sctk_path_chooser.py +516 -0
  32. scustomtkinter/sctk_progress_bar.py +274 -0
  33. scustomtkinter/sctk_radiobutton.py +360 -0
  34. scustomtkinter/sctk_scroll_mixin.py +546 -0
  35. scustomtkinter/sctk_scrollable_frame.py +795 -0
  36. scustomtkinter/sctk_scrollbar.py +313 -0
  37. scustomtkinter/sctk_segmentedbutton.py +424 -0
  38. scustomtkinter/sctk_selector.py +581 -0
  39. scustomtkinter/sctk_separator.py +308 -0
  40. scustomtkinter/sctk_slider.py +264 -0
  41. scustomtkinter/sctk_smeter.py +405 -0
  42. scustomtkinter/sctk_smeter_bar.py +557 -0
  43. scustomtkinter/sctk_spinbox.py +664 -0
  44. scustomtkinter/sctk_switch.py +463 -0
  45. scustomtkinter/sctk_tableview.py +869 -0
  46. scustomtkinter/sctk_tabview.py +409 -0
  47. scustomtkinter/sctk_textbox_primary.py +291 -0
  48. scustomtkinter/sctk_textbox_secondary.py +225 -0
  49. scustomtkinter/sctk_toplevel.py +153 -0
  50. scustomtkinter/themeable_widget.py +938 -0
  51. scustomtkinter-0.2.1.dist-info/METADATA +336 -0
  52. scustomtkinter-0.2.1.dist-info/RECORD +101 -0
  53. scustomtkinter-0.2.1.dist-info/WHEEL +5 -0
  54. scustomtkinter-0.2.1.dist-info/entry_points.txt +2 -0
  55. scustomtkinter-0.2.1.dist-info/licenses/LICENSE +21 -0
  56. scustomtkinter-0.2.1.dist-info/licenses/scustomtkinter/license_morecustomtkinterwidgets.txt +22 -0
  57. scustomtkinter-0.2.1.dist-info/top_level.txt +2 -0
  58. scustomtkinter_pygubu/__init__.py +1 -0
  59. scustomtkinter_pygubu/designer/__init__.py +0 -0
  60. scustomtkinter_pygubu/designer/plugin.py +1854 -0
  61. scustomtkinter_pygubu/designer/properties.py +247 -0
  62. scustomtkinter_pygubu/sCTkButtonPrimarybo.py +46 -0
  63. scustomtkinter_pygubu/sCTkButtonSecondarybo.py +45 -0
  64. scustomtkinter_pygubu/sCTkButtonTertiarybo.py +44 -0
  65. scustomtkinter_pygubu/sCTkCheckBoxbo.py +45 -0
  66. scustomtkinter_pygubu/sCTkComboBoxbo.py +45 -0
  67. scustomtkinter_pygubu/sCTkCorebo.py +120 -0
  68. scustomtkinter_pygubu/sCTkDialbo.py +371 -0
  69. scustomtkinter_pygubu/sCTkDialogbo.py +397 -0
  70. scustomtkinter_pygubu/sCTkEntryPrimarybo.py +100 -0
  71. scustomtkinter_pygubu/sCTkEntrySecondarybo.py +98 -0
  72. scustomtkinter_pygubu/sCTkFileExplorerbo.py +189 -0
  73. scustomtkinter_pygubu/sCTkFrameLabeledPrimarybo.py +69 -0
  74. scustomtkinter_pygubu/sCTkFrameLabeledSecondarybo.py +71 -0
  75. scustomtkinter_pygubu/sCTkFramebo.py +46 -0
  76. scustomtkinter_pygubu/sCTkFrequencyDisplaybo.py +175 -0
  77. scustomtkinter_pygubu/sCTkLabelPrimarybo.py +45 -0
  78. scustomtkinter_pygubu/sCTkLabelSecondarybo.py +44 -0
  79. scustomtkinter_pygubu/sCTkLabelTertiarybo.py +45 -0
  80. scustomtkinter_pygubu/sCTkNotebookbo.py +392 -0
  81. scustomtkinter_pygubu/sCTkOptionMenuPrimarybo.py +45 -0
  82. scustomtkinter_pygubu/sCTkOptionMenuSecondarybo.py +39 -0
  83. scustomtkinter_pygubu/sCTkPathChooserbo.py +204 -0
  84. scustomtkinter_pygubu/sCTkProgressBarbo.py +45 -0
  85. scustomtkinter_pygubu/sCTkRadioButtonbo.py +45 -0
  86. scustomtkinter_pygubu/sCTkSMeterBarbo.py +153 -0
  87. scustomtkinter_pygubu/sCTkSMeterbo.py +101 -0
  88. scustomtkinter_pygubu/sCTkScrollableFramebo.py +66 -0
  89. scustomtkinter_pygubu/sCTkScrollbarbo.py +48 -0
  90. scustomtkinter_pygubu/sCTkSegmentedButtonbo.py +47 -0
  91. scustomtkinter_pygubu/sCTkSelectorbo.py +167 -0
  92. scustomtkinter_pygubu/sCTkSeparatorbo.py +141 -0
  93. scustomtkinter_pygubu/sCTkSliderbo.py +45 -0
  94. scustomtkinter_pygubu/sCTkSpinboxbo.py +200 -0
  95. scustomtkinter_pygubu/sCTkSwitchbo.py +45 -0
  96. scustomtkinter_pygubu/sCTkTableviewbo.py +188 -0
  97. scustomtkinter_pygubu/sCTkTabviewbo.py +226 -0
  98. scustomtkinter_pygubu/sCTkTextboxPrimarybo.py +45 -0
  99. scustomtkinter_pygubu/sCTkTextboxSecondarybo.py +45 -0
  100. scustomtkinter_pygubu/sCTkToplevelbo.py +55 -0
  101. scustomtkinter_pygubu/sCTkWidgetSetForPygubuDesigner.py +141 -0
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/python3
2
+ """
3
+ sCTkProgressBar.
4
+
5
+ derived from progressBar
6
+
7
+ UI source file: sCTkProgressBar.ui
8
+ """
9
+ import tkinter as tk
10
+ import tkinter.ttk as ttk
11
+ from customtkinter import CTkProgressBar
12
+ from pygubu.api.v1 import (
13
+ BuilderObject,
14
+ register_widget,
15
+ )
16
+
17
+ from pygubu.plugins.customtkinter.widgets import CTkProgressBarBO
18
+ from scustomtkinter.sctk_progress_bar import sCTkProgressBar
19
+
20
+
21
+ #
22
+ # Builder definition section
23
+ #
24
+ widget_namespace = "scustomtkinter.sctk_progress_bar"
25
+ widget_classname = "sCTkProgressBar"
26
+ builder_namespace = "scustomtkinter"
27
+ section_name = "sCustomTkinter"
28
+
29
+
30
+ class sCTkProgressBarBO(CTkProgressBarBO):
31
+ class_ = sCTkProgressBar
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, sCTkProgressBarBO, widget_classname, ("ttk", section_name)
44
+ )
45
+
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/python3
2
+ """
3
+ sCTkRadioButton
4
+
5
+ derived from radioButton
6
+
7
+ UI source file: sCTkRadioButton.ui
8
+ """
9
+ import tkinter as tk
10
+ import tkinter.ttk as ttk
11
+ from customtkinter import CTkRadioButton
12
+ from pygubu.api.v1 import (
13
+ BuilderObject,
14
+ register_widget,
15
+ )
16
+
17
+ from pygubu.plugins.customtkinter.widgets import CTkRadioButtonBO
18
+ from scustomtkinter.sctk_radiobutton import sCTkRadioButton
19
+
20
+
21
+ #
22
+ # Builder definition section
23
+ #
24
+ widget_namespace = "scustomtkinter.sctk_radiobutton"
25
+ widget_classname = "sCTkRadioButton"
26
+ builder_namespace = "scustomtkinter"
27
+ section_name = "sCustomTkinter"
28
+
29
+
30
+ class sCTkRadioButtonBO(CTkRadioButtonBO):
31
+ class_ = sCTkRadioButton
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, sCTkRadioButtonBO, widget_classname, ("ttk", section_name)
44
+ )
45
+
@@ -0,0 +1,153 @@
1
+ #!/usr/bin/python3
2
+ """
3
+ sCTkSMeterBar
4
+
5
+ Pygubu Builder Object for a bar style s-meter, pwr and swr.
6
+ """
7
+ import ast
8
+ import pygubu
9
+
10
+ from pygubu.api.v1 import (
11
+ BuilderObject,
12
+ register_widget,
13
+ register_custom_property
14
+ )
15
+
16
+ # Import the native custom class
17
+ from scustomtkinter.themeable_widget import parse_font_property
18
+ from scustomtkinter.sctk_smeter_bar import sCTkSMeterBar
19
+
20
+ #
21
+ # Builder definition section
22
+ #
23
+ widget_namespace = "scustomtkinter.sctk_smeter_bar"
24
+ widget_classname = "sCTkSMeterBar"
25
+ builder_namespace = "scustomtkinter"
26
+ section_name = "sCustomTkinter"
27
+
28
+
29
+ class sCTkSMeterBarBO(BuilderObject):
30
+ class_ = sCTkSMeterBar
31
+
32
+ # Expose custom compound parameters alongside theme state configurations
33
+ OPTIONS_CUSTOM = ("width", "height", "fg_color", "swr_max_value", "swr_visible", "pwr_visible", "hide_lower_row", "hide_sig_row", "font", "scale_font")
34
+
35
+ # NOT CTkFrameBO.properties.
36
+ #
37
+ # Folding them in was tried and taken back out. The meter draws on a canvas
38
+ # that covers the whole widget, so the frame underneath is never visible:
39
+ # border_color, border_width and corner_radius appeared in the inspector
40
+ # and did nothing at all. A property that cannot work is worse than an
41
+ # absent one.
42
+ #
43
+ # fg_color IS listed above, because the widget paints the CANVAS with it --
44
+ # see sCTkSMeterBar.configure(). It was reaching sCTkSMeter and not this
45
+ # widget before, inherited from somewhere rather than declared, so the pair
46
+ # disagreed about a property they both support.
47
+ #
48
+ # corner_radius is the real loss: rounding the meter would mean rounding
49
+ # the canvas, which Tk cannot do to a canvas widget. It would have to be
50
+ # drawn -- a rounded rectangle filling the canvas in the parent's colour,
51
+ # masking the corners. Possible, not free.
52
+ properties = OPTIONS_CUSTOM
53
+
54
+ def _process_property_value(self, pname, value):
55
+ if pname in ("font", "scale_font"):
56
+ # Shared parser: Pygubu's fontentry emits a Tk font STRING, and
57
+ # "{}" for "no style selected" -- passed through, that reaches a
58
+ # canvas item as TclError: unknown font style "".
59
+ return parse_font_property(value)
60
+ if pname in ("width", "height"):
61
+ return int(value)
62
+ elif pname == "swr_max_value":
63
+ return float(value)
64
+ elif pname in ("swr_visible", "pwr_visible", "hide_lower_row", "hide_sig_row"):
65
+ if value == "True":
66
+ return True
67
+ else:
68
+ return False
69
+
70
+ return super()._process_property_value(pname, value)
71
+
72
+
73
+ # Register the widget into Pygubu's parsing engine
74
+ builder_id = f"{builder_namespace}.{widget_classname}"
75
+
76
+ register_widget(builder_id, sCTkSMeterBarBO, 'sCTkSMeterBar', ("ttk", section_name))
77
+
78
+
79
+
80
+ # Register custom attribute fields to display inside the Designer properties panel
81
+
82
+ register_custom_property(
83
+ builder_id,
84
+ "width",
85
+ "naturalnumber",
86
+ help="Set total width in pixels of the meter"
87
+ )
88
+
89
+ register_custom_property(
90
+ builder_id,
91
+ "height",
92
+ "naturalnumber",
93
+ help="Set height in pixels of the meter"
94
+ )
95
+
96
+
97
+ register_custom_property(
98
+ builder_id,
99
+ "swr_max_value",
100
+ "realnumber",
101
+ help="largest value for signal on scale"
102
+ )
103
+
104
+ register_custom_property(
105
+ builder_id,
106
+ "swr_visible",
107
+ "choice",values=("True","False"),
108
+ default_value="True",
109
+ help="Controls the visability of the SWR meter"
110
+ )
111
+
112
+ register_custom_property(
113
+ builder_id,
114
+ "pwr_visible",
115
+ "choice",values=("True","False"),
116
+ default_value="True",
117
+ help="Controls the visability of the SWR meter"
118
+ )
119
+
120
+
121
+ register_custom_property(
122
+ builder_id,
123
+ "hide_lower_row",
124
+ "choice",values=("True","False"),
125
+ default_value="False",
126
+ help="Hides the PWR/SWR if True"
127
+ )
128
+
129
+ register_custom_property(
130
+ builder_id,
131
+ "hide_sig_row",
132
+ "choice", values=("True","False"),
133
+ default_value="False",
134
+ help="Hides the S row, leaving SWR and PWR. The mirror of hide_lower_row: "
135
+ "the two together let one meter be split across two panels -- signal "
136
+ "under the receive frequency, power under the transmit one."
137
+ )
138
+
139
+ register_custom_property(
140
+ builder_id, "font", "fontentry",
141
+ help='Font for the captions -- SIGNAL, SIG, SWR and PWR. Blank uses the theme font.'
142
+ )
143
+ register_custom_property(
144
+ builder_id, "scale_font", "fontentry",
145
+ help='Font for the scale tick labels. Blank uses the theme scale_font. Larger values can overlap on a narrow meter.'
146
+ )
147
+
148
+ register_custom_property(
149
+ builder_id, "fg_color", "colorentry",
150
+ help="Background the meter is drawn on. This paints the CANVAS, not the "
151
+ "frame behind it -- the canvas covers the whole widget. Blank uses "
152
+ "the theme's fg_color."
153
+ )
@@ -0,0 +1,101 @@
1
+ #!/usr/bin/python3
2
+ """
3
+ sCTkSMeter.py
4
+
5
+ Pygubu Builder Object for a S Meter.
6
+ """
7
+ import ast
8
+ import pygubu
9
+
10
+ from pygubu.api.v1 import (
11
+ BuilderObject,
12
+ register_widget,
13
+ register_custom_property
14
+ )
15
+
16
+ # Import the native custom class
17
+ from scustomtkinter.themeable_widget import parse_font_property
18
+ from scustomtkinter.sctk_smeter import sCTkSMeter
19
+
20
+
21
+ #
22
+ # Builder definition section
23
+ #
24
+ widget_namespace = "scustomtkinter.sctk_smeter"
25
+ widget_classname = "sCTkSMeter"
26
+ builder_namespace = "scustomtkinter"
27
+ section_name = "sCustomTkinter"
28
+
29
+
30
+ class sCTkSMeterBO(BuilderObject):
31
+ class_ = sCTkSMeter
32
+
33
+ # Expose custom compound parameters alongside theme state configurations
34
+ OPTIONS_CUSTOM = ("width", "height", "fg_color", "font", "scale_font")
35
+
36
+ # NOT CTkFrameBO.properties.
37
+ #
38
+ # Folding them in was tried and taken back out. The meter draws on a canvas
39
+ # that covers the whole widget, so the frame underneath is never visible:
40
+ # border_color, border_width and corner_radius appeared in the inspector
41
+ # and did nothing at all. A property that cannot work is worse than an
42
+ # absent one.
43
+ #
44
+ # fg_color IS listed, because the widget paints the canvas with it -- see
45
+ # sCTkSMeter.configure(). It was reaching only one of the two meters
46
+ # before, inherited from somewhere rather than declared, so the pair
47
+ # disagreed about a property they both support.
48
+ #
49
+ # corner_radius is the real loss: rounding the meter would mean rounding
50
+ # the canvas, which Tk cannot do to a canvas widget. It would have to be
51
+ # drawn -- a rounded rectangle filling the canvas in the parent's colour,
52
+ # masking the corners. Possible, not free.
53
+ properties = OPTIONS_CUSTOM
54
+
55
+ def _process_property_value(self, pname, value):
56
+ if pname in ("font", "scale_font"):
57
+ # Shared parser: Pygubu's fontentry emits a Tk font STRING, and
58
+ # "{}" for "no style selected" -- passed through, that reaches a
59
+ # canvas item as TclError: unknown font style "".
60
+ return parse_font_property(value)
61
+ if pname in ("width", "height"):
62
+ return int(value)
63
+ return super()._process_property_value(pname, value)
64
+
65
+
66
+ # Register the widget into Pygubu's parsing engine
67
+ builder_id = f"{builder_namespace}.{widget_classname}"
68
+
69
+ register_widget(builder_id, sCTkSMeterBO, 'sCTkSMeter', ("ttk", section_name))
70
+
71
+
72
+
73
+ # Register custom attribute fields to display inside the Designer properties panel
74
+
75
+ register_custom_property(
76
+ builder_id,
77
+ "width",
78
+ "naturalnumber",
79
+ help="Set total width in pixels of the meter"
80
+ )
81
+
82
+ register_custom_property(
83
+ builder_id,
84
+ "height",
85
+ "naturalnumber",
86
+ help="Set height in pixels of the meter"
87
+ )
88
+
89
+ register_custom_property(
90
+ builder_id, "font", "fontentry",
91
+ help='Font for the captions -- SIGNAL, SIG, SWR and PWR. Blank uses the theme font.'
92
+ )
93
+ register_custom_property(
94
+ builder_id, "scale_font", "fontentry",
95
+ help='Font for the scale tick labels. Blank uses the theme scale_font. Larger values can overlap on a narrow meter.'
96
+ )
97
+
98
+ register_custom_property(
99
+ builder_id, "fg_color", "colorentry",
100
+ help="Background the meter is drawn on. This paints the CANVAS, not the frame behind it -- the canvas covers the whole widget. Blank uses the theme's fg_color."
101
+ )
@@ -0,0 +1,66 @@
1
+ #!/usr/bin/python3
2
+ """
3
+ sCTkScrollableFrame
4
+
5
+ subclass of ScrollableFrame tuned for this ux
6
+
7
+ UI source file: sCTkScrollableFrame.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_scrollable_frame import sCTkScrollableFrame
23
+
24
+
25
+ #
26
+ # Builder definition section
27
+ #
28
+ widget_namespace = "scustomtkinter.sctk_scrollable_frame"
29
+ widget_classname = "sCTkScrollableFrame"
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 sCTkScrollableFrameBO(CTkScrollableFrameBO):
40
+ class_ = sCTkScrollableFrame
41
+
42
+ OPTIONS_CUSTOM = ('state',)
43
+ properties = CTkScrollableFrameBO.properties + OPTIONS_CUSTOM
44
+
45
+ OPTIONS_CUSTOM_DEFAULTS = {
46
+ 'state': 'normal'
47
+ }
48
+
49
+ def code_imports(self):
50
+ # should return an iterable of (module, classname/function) to import
51
+ # or None
52
+ imports = [(widget_namespace, widget_classname)]
53
+ imports.extend(self.code_extra_imports())
54
+ return imports
55
+
56
+ builder_id = f"{builder_namespace}.{widget_classname}"
57
+ register_widget(
58
+ builder_id, sCTkScrollableFrameBO, widget_classname, ("ttk", section_name)
59
+ )
60
+
61
+
62
+ # -----------------------------------------------------------------
63
+ # EXPOSE CUSTOM 'STATE' CHANNELS INSIDE PYGUBU DESIGNER PANEL
64
+ # -----------------------------------------------------------------
65
+ # 1. Define the UI element type mapping definitions
66
+ register_custom_property(builder_id,"state", "choice", values=("normal", "disabled"))
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/python3
2
+ """
3
+ sCTkScrollbar
4
+
5
+ scrollbar
6
+
7
+ UI source file: sCTkScrollbar.ui
8
+ """
9
+ import tkinter as tk
10
+ import tkinter.ttk as ttk
11
+ from customtkinter import CTkScrollbar
12
+ from pygubu.api.v1 import (
13
+ BuilderObject,
14
+ register_widget,
15
+ )
16
+
17
+ from pygubu.plugins.customtkinter import nsctk
18
+ from pygubu.plugins.customtkinter.widgets import CTkScrollbarBO
19
+ from pygubu.api.v1 import copy_custom_property
20
+
21
+ from scustomtkinter.sctk_scrollbar import sCTkScrollbar
22
+
23
+
24
+ #
25
+ # Builder definition section
26
+ #
27
+ widget_namespace = "scustomtkinter.sctk_scrollbar"
28
+ widget_classname = "sCTkScrollbar"
29
+ builder_namespace = "scustomtkinter"
30
+ section_name = "sCustomTkinter"
31
+
32
+
33
+ class sCTkScrollbarBO(CTkScrollbarBO):
34
+ class_ = sCTkScrollbar
35
+
36
+ def code_imports(self):
37
+ # should return an iterable of (module, classname/function) to import
38
+ # or None
39
+ imports = [(widget_namespace, widget_classname)]
40
+ imports.extend(self.code_extra_imports())
41
+ return imports
42
+
43
+
44
+ builder_id = f"{builder_namespace}.{widget_classname}"
45
+ register_widget(
46
+ builder_id, sCTkScrollbarBO, widget_classname, ("ttk", section_name)
47
+ )
48
+
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/python3
2
+ """
3
+ sCTkSegmentedButton
4
+
5
+ segmentedButton
6
+
7
+ UI source file: sCTkSegmentedButton.ui
8
+ """
9
+ import tkinter as tk
10
+ import tkinter.ttk as ttk
11
+ from customtkinter import CTkSegmentedButton
12
+ from pygubu.api.v1 import (
13
+ BuilderObject,
14
+ register_widget,
15
+ )
16
+
17
+ from pygubu.plugins.customtkinter import nsctk
18
+ from pygubu.plugins.customtkinter.widgets import CTkSegmentedButtonBO
19
+ from pygubu.api.v1 import copy_custom_property
20
+
21
+ from scustomtkinter.sctk_segmentedbutton import sCTkSegmentedButton
22
+
23
+
24
+ #
25
+ # Builder definition section
26
+ #
27
+ widget_namespace = "scustomtkinter.sctk_segmentedbutton"
28
+ widget_classname = "sCTkSegmentedButton"
29
+ builder_namespace = "scustomtkinter"
30
+ section_name = "sCustomTkinter"
31
+
32
+
33
+ class sCTkSegmentedButtonBO(CTkSegmentedButtonBO):
34
+ class_ = sCTkSegmentedButton
35
+
36
+ def code_imports(self):
37
+ # should return an iterable of (module, classname/function) to import
38
+ # or None
39
+ imports = [(widget_namespace, widget_classname)]
40
+ imports.extend(self.code_extra_imports())
41
+ return imports
42
+
43
+
44
+ builder_id = f"{builder_namespace}.{widget_classname}"
45
+ register_widget(
46
+ builder_id, sCTkSegmentedButtonBO, widget_classname, ("ttk", section_name)
47
+ )
@@ -0,0 +1,167 @@
1
+ #!/usr/bin/python3
2
+ """
3
+ sCTkSelector Builder Object
4
+ """
5
+ import pygubu
6
+ from pygubu.api.v1 import (
7
+ BuilderObject,
8
+ register_widget,
9
+ register_custom_property
10
+ )
11
+ from scustomtkinter.sctk_selector import sCTkSelector
12
+ from scustomtkinter.themeable_widget import parse_list_property
13
+ from pygubu.plugins.customtkinter.widgets import CTkFrameBO
14
+
15
+ widget_namespace = "scustomtkinter.sctk_selector"
16
+ widget_classname = "sCTkSelector"
17
+ builder_namespace = "scustomtkinter"
18
+ section_name = "sCustomTkinter"
19
+
20
+
21
+ class sCTkSelectorBO(BuilderObject):
22
+ class_ = sCTkSelector
23
+
24
+ # OPTIONS_STANDARD = ('height', 'width')
25
+ # 1. Append 'state' to your custom options tuple array
26
+ # grid_propagate is deliberately absent. pack_propagate() and
27
+ # grid_propagate() control whether a container resizes to fit its CHILDREN,
28
+ # and which applies depends on how those children are managed -- this
29
+ # widget packs its own, so grid_propagate could never have an effect. It
30
+ # was offered anyway, which made it look like a knob that did nothing.
31
+ OPTIONS_CUSTOM = ('items', 'multiple_choices', 'pack_propagate', 'state')
32
+ properties = CTkFrameBO.properties + OPTIONS_CUSTOM
33
+
34
+ OPTIONS_CUSTOM_DEFAULTS = {
35
+ 'multiple_choices': 'True',
36
+ 'items': '["Item 1", "Item 2"]',
37
+ 'pack_propagate': 'True',
38
+ 'state': 'normal'
39
+ }
40
+
41
+ # NOT a container. sCTkSelector builds and manages its own checkbox list
42
+ # from the `items` property, laying them out inside its internal
43
+ # checkboxes_frame. A child dropped in from the Designer would land in an
44
+ # unmanaged position and be destroyed by the next rebuild -- which happens
45
+ # whenever `items` changes. It inherits sCTkFrame and composes an
46
+ # sCTkScrollableFrame internally, which is what made it LOOK like a
47
+ # container to the Designer.
48
+ container = False
49
+ container_layout = False
50
+
51
+ def realize(self, parent, extra_init_args: dict = None):
52
+ if extra_init_args is None:
53
+ extra_init_args = {}
54
+
55
+ # Shared parser: accepts the quoted-list form, a bare comma-separated
56
+ # string, or a real list -- see parse_list_property(). The inspector
57
+ # default is the quoted-list form, which is what Pygubu Designer users
58
+ # expect and is the only one of the two text forms that can express a
59
+ # value containing a comma.
60
+ items_val = self.wmeta.properties.get('items', '["Item 1", "Item 2"]')
61
+ items_arg = parse_list_property(items_val, default=["Item 1", "Item 2"])
62
+
63
+ mult_choice = self.wmeta.properties.get('multiple_choices', 'True')
64
+ mult_choice_arg = str(mult_choice).lower() in ['true', '1', 'yes']
65
+
66
+ p_prop = self.wmeta.properties.get('pack_propagate', 'True')
67
+ p_prop_arg = str(p_prop).lower() in ['true', '1', 'yes']
68
+
69
+ # 2. Extract designer state choice
70
+ state_arg = self.wmeta.properties.get('state', 'normal')
71
+
72
+ init_args = {
73
+ 'items': items_arg,
74
+ 'multiple_choices': mult_choice_arg,
75
+ 'pack_propagate': p_prop_arg,
76
+ 'state': state_arg
77
+ }
78
+
79
+ for prop in self.OPTIONS_CUSTOM:
80
+ extra_init_args.pop(prop, None)
81
+
82
+ init_args.update(extra_init_args)
83
+ real_master = parent.widget if hasattr(parent, 'widget') else parent
84
+ self.widget = self.class_(real_master, **init_args)
85
+ return self.widget
86
+
87
+ def _set_property(self, target_widget, pname, value):
88
+ """
89
+ Rebuilds the widget after a structural change.
90
+
91
+ Some properties cannot be expressed by configuring the existing
92
+ widget. A size only takes effect once Tk runs a geometry pass, and
93
+ turning pack_propagate back on merely tells it what to do at the next
94
+ one -- in an application the next event triggers that invisibly, but in
95
+ the Designer nothing else happens, so clearing a height appeared to do
96
+ nothing until an unrelated edit forced a repaint. `items` rebuilds the
97
+ checkbox list outright.
98
+
99
+ recreate_widget() is what the Designer itself does when you add or
100
+ delete a widget, which is why doing that by hand made the change
101
+ appear.
102
+
103
+ This hangs off _set_property, NOT set_property. The Designer edits a
104
+ property through the former -- confirmed by tracing, and it is the one
105
+ named in its own error messages ("Failed to set property 'x' on class
106
+ ..."). set_property is never called, so sCTkTableviewBO's identical
107
+ rebuild, which hangs off that, has probably never fired either.
108
+
109
+ Deliberately NOT used for colours: rebuilding on every keystroke in a
110
+ colour field would be unpleasant, and a colour needs no rebuild.
111
+ """
112
+ super()._set_property(target_widget, pname, value)
113
+
114
+ if pname in ("width", "height", "items", "pack_propagate"):
115
+ if hasattr(self, "builder") and hasattr(self.builder, "recreate_widget"):
116
+ try:
117
+ self.builder.recreate_widget(self)
118
+ except Exception:
119
+ # A widget not yet realized, or a builder that does not
120
+ # offer the call. Losing the rebuild costs a stale canvas,
121
+ # not correctness -- the .ui data is already updated.
122
+ pass
123
+
124
+ def _code_set_property(self, targetid, pname, value, code_bag):
125
+ """
126
+ The low-level code generation interception layer.
127
+ Ensures lists and booleans write as raw tokens, while text properties
128
+ like 'state' write out with proper Python string quotes.
129
+ """
130
+ # 1. Handle properties that MUST be generated as raw unquoted Python code/tokens
131
+ if pname in ('items', 'multiple_choices', 'pack_propagate'):
132
+ clean_string = str(value).strip("'\"")
133
+ code_bag[pname] = clean_string
134
+
135
+ # 2. FIXED: Handle properties that MUST keep their string quote wrappers
136
+ elif pname == 'state':
137
+ # Force it to explicitly keep single quotes, preventing NameErrors at runtime
138
+ clean_string = str(value).strip("'\"")
139
+ code_bag[pname] = f"'{clean_string}'"
140
+
141
+ else:
142
+ super()._code_set_property(targetid, pname, value, code_bag)
143
+
144
+
145
+ builder_id = f"{builder_namespace}.{widget_classname}"
146
+
147
+ register_widget(
148
+ builder_id, sCTkSelectorBO, widget_classname, ("ttk", section_name)
149
+ )
150
+
151
+ register_custom_property(
152
+ builder_id,
153
+ 'items',
154
+ 'entry',
155
+ help='Preferred: ["A", "B", "C"]. Bare comma-separated (A, B, C) also works, but cannot contain a comma inside a value.'
156
+ )
157
+
158
+ register_custom_property(builder_id, 'multiple_choices', 'choice', values=('True', 'False'))
159
+ # 4. Register the new UI type as a dropdown option selection field
160
+ register_custom_property(builder_id, 'state', 'choice', values=('normal', 'disabled'))
161
+
162
+ # 2. Register custom UI types as standard True/False dropdown pickers
163
+ register_custom_property(
164
+ builder_id, 'pack_propagate', 'choice', values=('True', 'False'),
165
+ help="False stops the widget resizing to fit its checkboxes, so an "
166
+ "explicit width and height are honoured."
167
+ )