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.
Files changed (29) hide show
  1. {swiftgui-0.2.1 → swiftgui-0.2.2}/PKG-INFO +1 -1
  2. {swiftgui-0.2.1 → swiftgui-0.2.2}/pyproject.toml +1 -1
  3. {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/GlobalOptions.py +5 -0
  4. {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/Literals.py +3 -0
  5. swiftgui-0.2.2/src/SwiftGUI/WidgetsAdvanced/FileBrowseButton.py +249 -0
  6. {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/Windows.py +28 -21
  7. {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/__init__.py +2 -1
  8. {swiftgui-0.2.1 → swiftgui-0.2.2}/LICENSE +0 -0
  9. {swiftgui-0.2.1 → swiftgui-0.2.2}/README.md +0 -0
  10. {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/Base.py +0 -0
  11. {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/Colors.py +0 -0
  12. {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/ElementFlags.py +0 -0
  13. {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/Events.py +0 -0
  14. {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/Examples.py +0 -0
  15. {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/Fonts.py +0 -0
  16. {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/KeyFunctions.py +0 -0
  17. {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/KeyManager.py +0 -0
  18. {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/Popups.py +0 -0
  19. {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/Themes.py +0 -0
  20. {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/Tools.py +0 -0
  21. {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/Widgets/Button.py +0 -0
  22. {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/Widgets/Checkbox.py +0 -0
  23. {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/Widgets/Frame.py +0 -0
  24. {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/Widgets/Input.py +0 -0
  25. {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/Widgets/Listbox.py +0 -0
  26. {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/Widgets/Separator.py +0 -0
  27. {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/Widgets/Spacer.py +0 -0
  28. {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/Widgets/Text.py +0 -0
  29. {swiftgui-0.2.1 → swiftgui-0.2.2}/src/SwiftGUI/WidgetsAdvanced/Form.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: SwiftGUI
3
- Version: 0.2.1
3
+ Version: 0.2.2
4
4
  Summary: An easy-to-use package for creating and using simple GUIs
5
5
  License: Apache-2.0
6
6
  Author: Eric aka LeButch
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "SwiftGUI"
3
- version = "0.2.1"
3
+ version = "0.2.2"
4
4
  packages = [
5
5
  { include = "SwiftGUI", from = "src" }
6
6
  ]
@@ -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
- self.refresh_values()
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
- for x in ftks:
303
- x()
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