SwiftGUI 0.2.1__tar.gz → 0.2.2__tar.gz
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.
- {swiftgui-0.2.1 → swiftgui-0.2.2}/PKG-INFO +1 -1
- {swiftgui-0.2.1 → swiftgui-0.2.2}/pyproject.toml +1 -1
- {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/GlobalOptions.py +5 -0
- {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/Literals.py +3 -0
- swiftgui-0.2.2/src/SwiftGUI/WidgetsAdvanced/FileBrowseButton.py +249 -0
- {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/Windows.py +28 -21
- {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/__init__.py +2 -1
- {swiftgui-0.2.1 → swiftgui-0.2.2}/LICENSE +0 -0
- {swiftgui-0.2.1 → swiftgui-0.2.2}/README.md +0 -0
- {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/Base.py +0 -0
- {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/Colors.py +0 -0
- {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/ElementFlags.py +0 -0
- {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/Events.py +0 -0
- {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/Examples.py +0 -0
- {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/Fonts.py +0 -0
- {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/KeyFunctions.py +0 -0
- {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/KeyManager.py +0 -0
- {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/Popups.py +0 -0
- {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/Themes.py +0 -0
- {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/Tools.py +0 -0
- {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/Widgets/Button.py +0 -0
- {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/Widgets/Checkbox.py +0 -0
- {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/Widgets/Frame.py +0 -0
- {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/Widgets/Input.py +0 -0
- {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/Widgets/Listbox.py +0 -0
- {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/Widgets/Separator.py +0 -0
- {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/Widgets/Spacer.py +0 -0
- {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/Widgets/Text.py +0 -0
- {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/WidgetsAdvanced/Form.py +0 -0
|
@@ -291,6 +291,11 @@ class Listbox(Common,Common_Textual):
|
|
|
291
291
|
highlightcolor: str | Color = None
|
|
292
292
|
highlightthickness: int = None
|
|
293
293
|
|
|
294
|
+
class FileBrowseButton(Button):
|
|
295
|
+
file_browse_type: Literals.file_browse_types = "open_single"
|
|
296
|
+
file_browse_filetypes: Literals.file_browse_filetypes = (("All files","*"),)
|
|
297
|
+
dont_change_on_abort: bool = False
|
|
298
|
+
|
|
294
299
|
def reset_all_options():
|
|
295
300
|
"""
|
|
296
301
|
Reset everything done to the global options on runtime.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from collections.abc import Iterable
|
|
1
2
|
from typing import Literal
|
|
2
3
|
|
|
3
4
|
# Not only literals, but typehints in General...
|
|
@@ -24,3 +25,5 @@ activestyle = Literal["none","underline","dotbox"]
|
|
|
24
25
|
selectmode_single = Literal["browse","single"]
|
|
25
26
|
selectmode_multiple = Literal["browse","single","multiple","extended"]
|
|
26
27
|
|
|
28
|
+
file_browse_types = Literal["open_single","open_multiple","open_directory","save_single"]
|
|
29
|
+
file_browse_filetypes = Iterable[tuple[str, str | list[str] | tuple[str, ...]]]
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
import inspect
|
|
2
|
+
import tkinter as tk
|
|
3
|
+
from os import PathLike
|
|
4
|
+
from tkinter import filedialog as fd
|
|
5
|
+
import tkinter.font as font
|
|
6
|
+
from collections.abc import Iterable, Callable
|
|
7
|
+
from typing import Literal
|
|
8
|
+
|
|
9
|
+
from SwiftGUI import BaseElement, ElementFlag, BaseWidget, BaseWidgetContainer, GlobalOptions, Literals, Color
|
|
10
|
+
from SwiftGUI.Widgets.Button import Button
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class FileBrowseButton(Button):
|
|
14
|
+
"""
|
|
15
|
+
Copy this class ot create your own Widget
|
|
16
|
+
|
|
17
|
+
The following methods are to be overwritten if needed:
|
|
18
|
+
_get_value (determines the value returned by this widget)
|
|
19
|
+
_init_widget_for_inherrit (Initializes the widget)
|
|
20
|
+
"""
|
|
21
|
+
tk_widget:tk.Button
|
|
22
|
+
_tk_widget_class:type = tk.Button # Class of the connected widget
|
|
23
|
+
defaults = GlobalOptions.FileBrowseButton
|
|
24
|
+
|
|
25
|
+
def __init__(
|
|
26
|
+
# https://anzeljg.github.io/rin2/book2/2405/docs/tkinter/button.html
|
|
27
|
+
|
|
28
|
+
self,
|
|
29
|
+
# Add here
|
|
30
|
+
text:str = "",
|
|
31
|
+
/,
|
|
32
|
+
key:any = None,
|
|
33
|
+
key_function:Callable|Iterable[Callable] = None,
|
|
34
|
+
|
|
35
|
+
file_browse_type:Literals.file_browse_types = None, #{"defaultextension","parent","title"}
|
|
36
|
+
file_browse_initial_dir: PathLike|str = None, # initialdir
|
|
37
|
+
file_browse_filetypes: Literals.file_browse_filetypes = None, # filetypes
|
|
38
|
+
file_browse_initial_file: str = None, # initialfile
|
|
39
|
+
file_browse_title: str = None, # title
|
|
40
|
+
file_browse_save_defaultextension: str = None, # defaultextension
|
|
41
|
+
# Todo: parent
|
|
42
|
+
dont_change_on_abort: bool = None,
|
|
43
|
+
|
|
44
|
+
borderwidth:int = None,
|
|
45
|
+
|
|
46
|
+
bitmap:Literals.bitmap = None,
|
|
47
|
+
disabled:bool = None,
|
|
48
|
+
text_color_disabled: str | Color = None,
|
|
49
|
+
background_color_active: str | Color = None,
|
|
50
|
+
text_color_active: str | Color = None,
|
|
51
|
+
|
|
52
|
+
width: int = None,
|
|
53
|
+
height: int = None,
|
|
54
|
+
padx:int = None,
|
|
55
|
+
pady:int = None,
|
|
56
|
+
|
|
57
|
+
cursor: Literals.cursor = None,
|
|
58
|
+
takefocus: bool = None,
|
|
59
|
+
|
|
60
|
+
underline: int = None,
|
|
61
|
+
anchor: Literals.anchor = None,
|
|
62
|
+
justify: Literal["left", "right", "center"] = None,
|
|
63
|
+
background_color: str | Color = None,
|
|
64
|
+
overrelief: Literals.relief = None,
|
|
65
|
+
text_color: str | Color = None,
|
|
66
|
+
# Todo: image
|
|
67
|
+
relief: Literals.relief = None,
|
|
68
|
+
|
|
69
|
+
repeatdelay:int = None,
|
|
70
|
+
repeatinterval:int = None,
|
|
71
|
+
|
|
72
|
+
# # Mixed options
|
|
73
|
+
fonttype: str = None,
|
|
74
|
+
fontsize: int = None,
|
|
75
|
+
font_bold: bool = None,
|
|
76
|
+
font_italic: bool = None,
|
|
77
|
+
font_underline: bool = None,
|
|
78
|
+
font_overstrike: bool = None,
|
|
79
|
+
|
|
80
|
+
expand: bool = None,
|
|
81
|
+
tk_kwargs: dict[str:any] = None
|
|
82
|
+
):
|
|
83
|
+
"""
|
|
84
|
+
A button that throws an event every time it is pushed
|
|
85
|
+
|
|
86
|
+
:param text: Text the button displays
|
|
87
|
+
:param key: (See docs for more details)
|
|
88
|
+
:param key_function: (See docs for more details)
|
|
89
|
+
|
|
90
|
+
:param file_browse_type: Type of filebrowser (e.g. getting a single file, saving a file, etc.)
|
|
91
|
+
:param file_browse_initial_dir: Directory to start browsing in. "." to start in the working dir, ".." for the dir above.
|
|
92
|
+
:param file_browse_filetypes: Possible types when reading files. Format like this: (("Description1":".extension1"), ("Description2":".extension2"))
|
|
93
|
+
:param file_browse_initial_file: IT WON'T SELECT THE FILE, just put the filename inside the box on the bottom
|
|
94
|
+
:param file_browse_title: Title of the file-browse-window
|
|
95
|
+
:param file_browse_save_defaultextension: When saving, this extension will be added if the user doesn't provide an extension
|
|
96
|
+
:param dont_change_on_abort: If True, the value will not change when the user cancels/closes the file-browse
|
|
97
|
+
|
|
98
|
+
:param borderwidth: Border-Thickness in pixels. Default is 2
|
|
99
|
+
:param bitmap: The are a couple of icons builtin. If you are using PyCharm, they should be suggested when pressing "ctrl+space"
|
|
100
|
+
:param disabled: True, if this button should not be pressable
|
|
101
|
+
:param text_color_disabled: Text color, if disabled = True
|
|
102
|
+
:param background_color_active: Background color shown only when the button is held down
|
|
103
|
+
:param text_color_active: Text color only shown when the button is held down
|
|
104
|
+
:param width: Button-size in x-direction in text-characters
|
|
105
|
+
:param height: Button-height in text-rows
|
|
106
|
+
:param padx: Adds space to both sides not filled with text. Should not be combined with "width". The value is given in characters
|
|
107
|
+
:param pady: Adds space to the top and bottom not filled with text. Should not be combined with "height". The value is given in rows
|
|
108
|
+
:param cursor: How the cursor should look when hovering over this element.
|
|
109
|
+
:param takefocus: True, if this element should be able to get focus (e.g. by pressing tab)
|
|
110
|
+
:param underline: Underlines the single character at this index
|
|
111
|
+
:param anchor: Specifies, where the text in this element should be placed (See docs for more details)
|
|
112
|
+
:param justify: When the text is multiple rows long, this will specify where the new rows begin.
|
|
113
|
+
:param background_color: Background-color for the non-pressed state
|
|
114
|
+
:param overrelief: Relief when the mouse hovers over the element
|
|
115
|
+
:param text_color: Text-color in non-pressed state
|
|
116
|
+
:param relief: Relief in non-pressed state
|
|
117
|
+
:param repeatdelay: How long to hold the button until repeation starts (doesn't work without "repeatinterval")
|
|
118
|
+
:param repeatinterval: How long to wait between repetitions (doesn't work without "repeatdelay")
|
|
119
|
+
:param fonttype: Use sg.font_windows. ... to select some fancy font. Personally, I like sg.font_windows.Small_Fonts
|
|
120
|
+
:param fontsize: Size (height) of the font in pixels
|
|
121
|
+
:param font_bold: True, if thicc text
|
|
122
|
+
:param font_italic: True, if italic text
|
|
123
|
+
:param font_underline: True, if the text should be underlined
|
|
124
|
+
:param font_overstrike: True, if the text should be overstruck
|
|
125
|
+
:param tk_kwargs: (Only if you know tkinter) Pass more kwargs directly to the tk-widget
|
|
126
|
+
"""
|
|
127
|
+
if callable(key_function):
|
|
128
|
+
key_function = (self._button_callback,key_function)
|
|
129
|
+
elif key_function:
|
|
130
|
+
key_function = (self._button_callback,*tuple(key_function))
|
|
131
|
+
else:
|
|
132
|
+
key_function = self._button_callback
|
|
133
|
+
|
|
134
|
+
super().__init__(
|
|
135
|
+
text,
|
|
136
|
+
key=key,
|
|
137
|
+
key_function=key_function,
|
|
138
|
+
borderwidth=borderwidth,
|
|
139
|
+
bitmap=bitmap,
|
|
140
|
+
disabled=disabled,
|
|
141
|
+
text_color_disabled=text_color_disabled,
|
|
142
|
+
background_color_active=background_color_active,
|
|
143
|
+
text_color_active=text_color_active,
|
|
144
|
+
width=width,
|
|
145
|
+
height=height,
|
|
146
|
+
padx=padx,
|
|
147
|
+
pady=pady,
|
|
148
|
+
cursor=cursor,
|
|
149
|
+
takefocus=takefocus,
|
|
150
|
+
underline=underline,
|
|
151
|
+
anchor=anchor,
|
|
152
|
+
justify=justify,
|
|
153
|
+
background_color=background_color,
|
|
154
|
+
overrelief=overrelief,
|
|
155
|
+
text_color=text_color,
|
|
156
|
+
relief=relief,
|
|
157
|
+
repeatdelay=repeatdelay,
|
|
158
|
+
repeatinterval=repeatinterval,
|
|
159
|
+
fonttype=fonttype,
|
|
160
|
+
fontsize=fontsize,
|
|
161
|
+
font_bold=font_bold,
|
|
162
|
+
font_italic=font_italic,
|
|
163
|
+
font_underline=font_underline,
|
|
164
|
+
font_overstrike=font_overstrike,
|
|
165
|
+
expand=expand,
|
|
166
|
+
tk_kwargs=tk_kwargs,
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
self._file_function_kwargs = dict()
|
|
170
|
+
|
|
171
|
+
self.update(
|
|
172
|
+
file_browse_type = file_browse_type,
|
|
173
|
+
file_browse_initial_dir = file_browse_initial_dir,
|
|
174
|
+
file_browse_filetypes = file_browse_filetypes,
|
|
175
|
+
file_browse_initial_file = file_browse_initial_file,
|
|
176
|
+
file_browse_title = file_browse_title,
|
|
177
|
+
file_browse_save_defaultextension = file_browse_save_defaultextension,
|
|
178
|
+
|
|
179
|
+
dont_change_on_abort=dont_change_on_abort,
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
_prev_val:str|tuple[str] = None
|
|
183
|
+
_file_function_wanted = None
|
|
184
|
+
_dont_change_on_abort = None # If the value should be unchanged if the user just closes the window
|
|
185
|
+
def _button_callback(self):
|
|
186
|
+
if self._file_function is None:
|
|
187
|
+
return
|
|
188
|
+
|
|
189
|
+
# Only provide arguments the file-function actually wants
|
|
190
|
+
kwargs = self._file_function_kwargs
|
|
191
|
+
offers = kwargs.fromkeys(kwargs.keys() & self._file_function_wanted)
|
|
192
|
+
offers = {i:kwargs[i] for i in offers}
|
|
193
|
+
|
|
194
|
+
# Call the file-dialogue
|
|
195
|
+
temp = self._file_function(**offers)
|
|
196
|
+
|
|
197
|
+
if self._dont_change_on_abort and not temp:
|
|
198
|
+
return
|
|
199
|
+
|
|
200
|
+
self._prev_val = temp
|
|
201
|
+
return True # Refresh values for coming key_functions
|
|
202
|
+
|
|
203
|
+
def _get_value(self) -> any:
|
|
204
|
+
return self._prev_val
|
|
205
|
+
|
|
206
|
+
def set_value(self,val:any):
|
|
207
|
+
self._prev_val = val
|
|
208
|
+
|
|
209
|
+
_file_function: Callable = None
|
|
210
|
+
_file_function_kwargs: dict
|
|
211
|
+
def _update_special_key(self,key:str,new_val:any) -> bool|None:
|
|
212
|
+
if super()._update_special_key(key,new_val):
|
|
213
|
+
return True
|
|
214
|
+
|
|
215
|
+
match key:
|
|
216
|
+
case "file_browse_type":
|
|
217
|
+
self._file_function = {
|
|
218
|
+
"open_single": fd.askopenfilename,
|
|
219
|
+
"open_multiple": fd.askopenfilenames,
|
|
220
|
+
"open_directory": fd.askdirectory,
|
|
221
|
+
"save_single": fd.asksaveasfilename,
|
|
222
|
+
}[new_val]
|
|
223
|
+
self._file_function_wanted = {
|
|
224
|
+
"open_single": {"defaultextension","filetypes","initialdir","initialfile","parent","title"},
|
|
225
|
+
"open_multiple": {"defaultextension","filetypes","initialdir","initialfile","parent","title"},
|
|
226
|
+
"open_directory": {"initialdir","mustexist","parent","title"},
|
|
227
|
+
"save_single": {"defaultextension","filetypes","initialdir","initialfile","parent","title"},
|
|
228
|
+
}[new_val]
|
|
229
|
+
|
|
230
|
+
case "file_browse_initial_dir":
|
|
231
|
+
self._file_function_kwargs["initialdir"] = new_val
|
|
232
|
+
case "file_browse_filetypes":
|
|
233
|
+
self._file_function_kwargs["filetypes"] = new_val
|
|
234
|
+
case "file_browse_initial_file":
|
|
235
|
+
self._file_function_kwargs["initialfile"] = new_val
|
|
236
|
+
case "dont_change_on_abort":
|
|
237
|
+
self._dont_change_on_abort = new_val
|
|
238
|
+
case "file_browse_title":
|
|
239
|
+
self._file_function_kwargs["title"] = new_val
|
|
240
|
+
case "file_browse_save_defaultextension":
|
|
241
|
+
self._file_function_kwargs["file_browse_save_defaultextension"] = new_val
|
|
242
|
+
case _:
|
|
243
|
+
return False
|
|
244
|
+
|
|
245
|
+
return True
|
|
246
|
+
|
|
247
|
+
def _personal_init_inherit(self):
|
|
248
|
+
pass # Avoid creating a target variable for this button, so the text can be changed with .update(text="...")
|
|
249
|
+
|
|
@@ -278,31 +278,38 @@ class Window(BaseElement):
|
|
|
278
278
|
if (key_function is not None) and not hasattr(key_function, "__iter__"):
|
|
279
279
|
key_function = (key_function,)
|
|
280
280
|
|
|
281
|
-
ftks = []
|
|
282
|
-
if key_function: # Call key-functions
|
|
283
|
-
kwargs = { # Possible parameters for function
|
|
284
|
-
"w": self, # Reference to main window
|
|
285
|
-
"e": key, # Event-key, if there is one
|
|
286
|
-
"v": self.values, # All values
|
|
287
|
-
"val": me.value, # Value of element that caused the event
|
|
288
|
-
"elem": me,
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
for fkt in key_function:
|
|
292
|
-
wanted = set(inspect.signature(fkt).parameters.keys())
|
|
293
|
-
offers = kwargs.fromkeys(kwargs.keys() & wanted)
|
|
294
|
-
args = {i:kwargs[i] for i in offers}
|
|
295
|
-
ftks.append(lambda: fkt(**args))
|
|
296
|
-
|
|
297
|
-
self.refresh_values() # In case you change values with the key-functions
|
|
298
|
-
|
|
299
281
|
def single_event(*_):
|
|
300
|
-
|
|
282
|
+
did_refresh = False
|
|
283
|
+
|
|
284
|
+
if key_function: # Call key-functions
|
|
285
|
+
self.refresh_values()
|
|
286
|
+
|
|
287
|
+
kwargs = { # Possible parameters for function
|
|
288
|
+
"w": self, # Reference to main window
|
|
289
|
+
"e": key, # Event-key, if there is one
|
|
290
|
+
"v": self.values, # All values
|
|
291
|
+
"val": me.value, # Value of element that caused the event
|
|
292
|
+
"elem": me,
|
|
293
|
+
}
|
|
301
294
|
|
|
302
|
-
|
|
303
|
-
|
|
295
|
+
for fkt in key_function:
|
|
296
|
+
wanted = set(inspect.signature(fkt).parameters.keys())
|
|
297
|
+
offers = kwargs.fromkeys(kwargs.keys() & wanted)
|
|
298
|
+
did_refresh = False
|
|
299
|
+
|
|
300
|
+
if fkt(**{i:kwargs[i] for i in offers}) is not None:
|
|
301
|
+
kwargs["val"] = me.value
|
|
302
|
+
self.refresh_values()
|
|
303
|
+
did_refresh = True
|
|
304
|
+
|
|
305
|
+
if not did_refresh:
|
|
306
|
+
self.refresh_values() # In case you change values with the key-functions
|
|
307
|
+
did_refresh = True
|
|
304
308
|
|
|
305
309
|
if key is not None: # Call named event
|
|
310
|
+
if not did_refresh: # Not redundant, keep it!
|
|
311
|
+
self.refresh_values()
|
|
312
|
+
|
|
306
313
|
self._receive_event(key)
|
|
307
314
|
|
|
308
315
|
return single_event
|
|
@@ -18,6 +18,7 @@ from .Widgets.Spacer import Spacer
|
|
|
18
18
|
from .Widgets.Listbox import Listbox
|
|
19
19
|
|
|
20
20
|
from .WidgetsAdvanced.Form import Form
|
|
21
|
+
from .WidgetsAdvanced.FileBrowseButton import FileBrowseButton
|
|
21
22
|
|
|
22
23
|
T = Text
|
|
23
24
|
|
|
@@ -31,7 +32,7 @@ Check = Checkbox
|
|
|
31
32
|
|
|
32
33
|
Column = Frame
|
|
33
34
|
|
|
34
|
-
AnyElement = BaseElement | BaseWidget | Text | Button | Checkbox | Frame | Input | VerticalSeparator | HorizontalSeparator | Spacer | Form | Listbox
|
|
35
|
+
AnyElement = BaseElement | BaseWidget | Text | Button | Checkbox | Frame | Input | VerticalSeparator | HorizontalSeparator | Spacer | Form | Listbox | FileBrowseButton
|
|
35
36
|
|
|
36
37
|
from .Windows import Window
|
|
37
38
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|