KL-Py 0.0.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 (125) hide show
  1. KL_Py/KL_Py.py +4400 -0
  2. KL_Py/__init__.py +1 -0
  3. KL_Py/hindGui/__init__.py +16529 -0
  4. KL_Py/hindGui/_utils.py +140 -0
  5. KL_Py/hindGui/elements/base.py +1055 -0
  6. KL_Py/hindGui/elements/button.py +947 -0
  7. KL_Py/hindGui/elements/calendar.py +222 -0
  8. KL_Py/hindGui/elements/canvas.py +122 -0
  9. KL_Py/hindGui/elements/center.py +44 -0
  10. KL_Py/hindGui/elements/checkbox.py +240 -0
  11. KL_Py/hindGui/elements/column.py +443 -0
  12. KL_Py/hindGui/elements/combo.py +329 -0
  13. KL_Py/hindGui/elements/error.py +47 -0
  14. KL_Py/hindGui/elements/frame.py +273 -0
  15. KL_Py/hindGui/elements/graph.py +817 -0
  16. KL_Py/hindGui/elements/helpers.py +202 -0
  17. KL_Py/hindGui/elements/image.py +324 -0
  18. KL_Py/hindGui/elements/input.py +310 -0
  19. KL_Py/hindGui/elements/list_box.py +392 -0
  20. KL_Py/hindGui/elements/menu.py +192 -0
  21. KL_Py/hindGui/elements/multiline.py +685 -0
  22. KL_Py/hindGui/elements/option_menu.py +168 -0
  23. KL_Py/hindGui/elements/pane.py +127 -0
  24. KL_Py/hindGui/elements/progress_bar.py +304 -0
  25. KL_Py/hindGui/elements/radio.py +252 -0
  26. KL_Py/hindGui/elements/separator.py +64 -0
  27. KL_Py/hindGui/elements/sizegrip.py +34 -0
  28. KL_Py/hindGui/elements/slider.py +199 -0
  29. KL_Py/hindGui/elements/spin.py +252 -0
  30. KL_Py/hindGui/elements/status_bar.py +165 -0
  31. KL_Py/hindGui/elements/stretch.py +26 -0
  32. KL_Py/hindGui/elements/tab.py +697 -0
  33. KL_Py/hindGui/elements/table.py +463 -0
  34. KL_Py/hindGui/elements/text.py +413 -0
  35. KL_Py/hindGui/elements/tree.py +493 -0
  36. KL_Py/hindGui/replace.py +45 -0
  37. KL_Py/hindGui/tray.py +358 -0
  38. KL_Py/hindGui/window.py +2906 -0
  39. KL_Py/requests/__init__.py +184 -0
  40. KL_Py/requests/__version__.py +14 -0
  41. KL_Py/requests/_internal_utils.py +50 -0
  42. KL_Py/requests/adapters.py +719 -0
  43. KL_Py/requests/api.py +157 -0
  44. KL_Py/requests/auth.py +314 -0
  45. KL_Py/requests/certifi/__init__.py +4 -0
  46. KL_Py/requests/certifi/__main__.py +12 -0
  47. KL_Py/requests/certifi/core.py +83 -0
  48. KL_Py/requests/certifi/py.typed +0 -0
  49. KL_Py/requests/certs.py +17 -0
  50. KL_Py/requests/charset_normalizer/__init__.py +48 -0
  51. KL_Py/requests/charset_normalizer/__main__.py +6 -0
  52. KL_Py/requests/charset_normalizer/api.py +671 -0
  53. KL_Py/requests/charset_normalizer/cd.py +421 -0
  54. KL_Py/requests/charset_normalizer/cli/__init__.py +8 -0
  55. KL_Py/requests/charset_normalizer/cli/__main__.py +363 -0
  56. KL_Py/requests/charset_normalizer/constant.py +2031 -0
  57. KL_Py/requests/charset_normalizer/legacy.py +80 -0
  58. KL_Py/requests/charset_normalizer/md.py +744 -0
  59. KL_Py/requests/charset_normalizer/models.py +359 -0
  60. KL_Py/requests/charset_normalizer/py.typed +0 -0
  61. KL_Py/requests/charset_normalizer/utils.py +420 -0
  62. KL_Py/requests/charset_normalizer/version.py +8 -0
  63. KL_Py/requests/compat.py +106 -0
  64. KL_Py/requests/cookies.py +561 -0
  65. KL_Py/requests/exceptions.py +151 -0
  66. KL_Py/requests/help.py +134 -0
  67. KL_Py/requests/hooks.py +33 -0
  68. KL_Py/requests/idna/__init__.py +45 -0
  69. KL_Py/requests/idna/codec.py +122 -0
  70. KL_Py/requests/idna/compat.py +15 -0
  71. KL_Py/requests/idna/core.py +437 -0
  72. KL_Py/requests/idna/idnadata.py +4309 -0
  73. KL_Py/requests/idna/intranges.py +57 -0
  74. KL_Py/requests/idna/package_data.py +1 -0
  75. KL_Py/requests/idna/py.typed +0 -0
  76. KL_Py/requests/idna/uts46data.py +8841 -0
  77. KL_Py/requests/models.py +1039 -0
  78. KL_Py/requests/packages.py +23 -0
  79. KL_Py/requests/sessions.py +831 -0
  80. KL_Py/requests/status_codes.py +128 -0
  81. KL_Py/requests/structures.py +99 -0
  82. KL_Py/requests/urllib3/__init__.py +211 -0
  83. KL_Py/requests/urllib3/_base_connection.py +165 -0
  84. KL_Py/requests/urllib3/_collections.py +487 -0
  85. KL_Py/requests/urllib3/_request_methods.py +278 -0
  86. KL_Py/requests/urllib3/_version.py +34 -0
  87. KL_Py/requests/urllib3/connection.py +1099 -0
  88. KL_Py/requests/urllib3/connectionpool.py +1178 -0
  89. KL_Py/requests/urllib3/contrib/__init__.py +0 -0
  90. KL_Py/requests/urllib3/contrib/emscripten/__init__.py +17 -0
  91. KL_Py/requests/urllib3/contrib/emscripten/connection.py +260 -0
  92. KL_Py/requests/urllib3/contrib/emscripten/fetch.py +726 -0
  93. KL_Py/requests/urllib3/contrib/emscripten/request.py +22 -0
  94. KL_Py/requests/urllib3/contrib/emscripten/response.py +277 -0
  95. KL_Py/requests/urllib3/contrib/pyopenssl.py +564 -0
  96. KL_Py/requests/urllib3/contrib/socks.py +228 -0
  97. KL_Py/requests/urllib3/exceptions.py +335 -0
  98. KL_Py/requests/urllib3/fields.py +341 -0
  99. KL_Py/requests/urllib3/filepost.py +89 -0
  100. KL_Py/requests/urllib3/http2/__init__.py +53 -0
  101. KL_Py/requests/urllib3/http2/connection.py +356 -0
  102. KL_Py/requests/urllib3/http2/probe.py +87 -0
  103. KL_Py/requests/urllib3/poolmanager.py +651 -0
  104. KL_Py/requests/urllib3/py.typed +2 -0
  105. KL_Py/requests/urllib3/response.py +1480 -0
  106. KL_Py/requests/urllib3/util/__init__.py +42 -0
  107. KL_Py/requests/urllib3/util/connection.py +137 -0
  108. KL_Py/requests/urllib3/util/proxy.py +43 -0
  109. KL_Py/requests/urllib3/util/request.py +263 -0
  110. KL_Py/requests/urllib3/util/response.py +101 -0
  111. KL_Py/requests/urllib3/util/retry.py +549 -0
  112. KL_Py/requests/urllib3/util/ssl_.py +527 -0
  113. KL_Py/requests/urllib3/util/ssl_match_hostname.py +159 -0
  114. KL_Py/requests/urllib3/util/ssltransport.py +271 -0
  115. KL_Py/requests/urllib3/util/timeout.py +275 -0
  116. KL_Py/requests/urllib3/util/url.py +469 -0
  117. KL_Py/requests/urllib3/util/util.py +42 -0
  118. KL_Py/requests/urllib3/util/wait.py +124 -0
  119. KL_Py/requests/utils.py +1086 -0
  120. KL_Py/when.py +144 -0
  121. kl_py-0.0.1.dist-info/METADATA +15 -0
  122. kl_py-0.0.1.dist-info/RECORD +125 -0
  123. kl_py-0.0.1.dist-info/WHEEL +5 -0
  124. kl_py-0.0.1.dist-info/licenses/LICENSE +21 -0
  125. kl_py-0.0.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,697 @@
1
+ from __future__ import annotations
2
+
3
+ import tkinter as tk
4
+ import warnings
5
+ from tkinter import ttk
6
+
7
+ import hindGui
8
+ from hindGui import _add_right_click_menu
9
+ from hindGui import _random_error_emoji
10
+ from hindGui import COLOR_SYSTEM_DEFAULT
11
+ from hindGui import ELEM_TYPE_TAB
12
+ from hindGui import ELEM_TYPE_TAB_GROUP
13
+ from hindGui import Element
14
+ from hindGui import LOOK_AND_FEEL_TABLE
15
+ from hindGui import PackFormIntoFrame
16
+ from hindGui import error
17
+ from hindGui import error_with_traceback
18
+ from hindGui import Hover
19
+ from hindGui._utils import _error_popup_with_traceback
20
+ from hindGui.window import Window
21
+
22
+
23
+ class Tab(Element):
24
+ """
25
+ Tab Element is another "Container" element that holds a layout and displays a tab with text. Used with TabGroup only
26
+ Tabs are never placed directly into a layout. They are always "Contained" in a TabGroup layout
27
+ """
28
+
29
+ def __init__(
30
+ self,
31
+ title,
32
+ layout,
33
+ title_color=None,
34
+ background_color=None,
35
+ font=None,
36
+ pad=None,
37
+ p=None,
38
+ disabled=False,
39
+ border_width=None,
40
+ action=None,
41
+ k=None,
42
+ ke_upar=None,
43
+ right_click_menu=None,
44
+ expand_x=False,
45
+ expand_y=False,
46
+ nazar=True,
47
+ element_justification='left',
48
+ image_source=None,
49
+ image_subsample=None,
50
+ image_zoom=None,
51
+ metadata=None,
52
+ ):
53
+ """
54
+ :param title: text to show on the tab
55
+ :type title: (str)
56
+ :param layout: The element layout that will be shown in the tab
57
+ :type layout: List[List[Element]]
58
+ :param title_color: color of the tab text (note not currently working on tkinter)
59
+ :type title_color: (str)
60
+ :param background_color: color of background of the entire layout
61
+ :type background_color: (str)
62
+ :param font: NOT USED in the tkinter port
63
+ :type font: (str or (str, int[, str]) or None)
64
+ :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
65
+ :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
66
+ :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
67
+ :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
68
+ :param disabled: If True button will be created disabled
69
+ :type disabled: (bool)
70
+ :param border_width: NOT USED in tkinter port
71
+ :type border_width: (int)
72
+ :param action: Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window
73
+ :type action: str | int | tuple | object
74
+ :param k: Same as the Key. You can use either k or action. Which ever is set will be used.
75
+ :type k: str | int | tuple | object
76
+ :param ke_upar: text, that will appear when mouse hovers over the element
77
+ :type ke_upar: (str)
78
+ :param right_click_menu: A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.
79
+ :type right_click_menu: List[List[ List[str] | str ]]
80
+ :param expand_x: If True the element will automatically expand in the X direction to fill available space
81
+ :type expand_x: (bool)
82
+ :param expand_y: If True the element will automatically expand in the Y direction to fill available space
83
+ :type expand_y: (bool)
84
+ :param nazar: set visibility state of the element
85
+ :type nazar: (bool)
86
+ :param element_justification: All elements inside the Tab will have this justification 'left', 'right', 'center' are valid values
87
+ :type element_justification: (str)
88
+ :param image_source: A filename or a base64 bytes of an image to place on the Tab
89
+ :type image_source: str | bytes | None
90
+ :param image_subsample: amount to reduce the size of the image. Divides the size by this number. 2=1/2, 3=1/3, 4=1/4, etc
91
+ :type image_subsample: (int)
92
+ :param image_zoom: amount to increase the size of the image. 2=twice size, 3=3 times, etc
93
+ :type image_zoom: (int)
94
+ :param metadata: User metadata that can be set to ANYTHING
95
+ :type metadata: (Any)
96
+ """
97
+
98
+ filename = data = None
99
+ if image_source is not None:
100
+ if isinstance(image_source, bytes):
101
+ data = image_source
102
+ elif isinstance(image_source, str):
103
+ filename = image_source
104
+ else:
105
+ warnings.warn(f'Image element - source is not a valid type: {type(image_source)}', UserWarning)
106
+
107
+ self.Filename = filename
108
+ self.Data = data
109
+ self.ImageSubsample = image_subsample
110
+ self.zoom = int(image_zoom) if image_zoom is not None else None
111
+ self.UseDictionary = False
112
+ self.ReturnValues = None
113
+ self.ReturnValuesList = []
114
+ self.ReturnValuesDictionary = {}
115
+ self.DictionaryKeyCounter = 0
116
+ self.ParentWindow = None
117
+ self.Rows = []
118
+ self.TKFrame = None
119
+ self.Widget = None # type: tk.Frame
120
+ self.Title = title
121
+ self.BorderWidth = border_width
122
+ self.Disabled = disabled
123
+ self.ParentNotebook = None
124
+ self.TabID = None
125
+ self.BackgroundColor = background_color if background_color is not None else hindGui.DEFAULT_BACKGROUND_COLOR
126
+ self.RightClickMenu = right_click_menu
127
+ self.ContainerElemementNumber = Window._GetAContainerNumber()
128
+ self.ElementJustification = element_justification
129
+ action = action if action is not None else k
130
+ pad = pad if pad is not None else p
131
+ self.expand_x = expand_x
132
+ self.expand_y = expand_y
133
+
134
+ self.Layout(layout)
135
+
136
+ super().__init__(
137
+ ELEM_TYPE_TAB,
138
+ background_color=background_color,
139
+ text_color=title_color,
140
+ font=font,
141
+ pad=pad,
142
+ action=action,
143
+ ke_upar=ke_upar,
144
+ nazar=nazar,
145
+ metadata=metadata,
146
+ )
147
+ return
148
+
149
+ def add_row(self, *args):
150
+ """
151
+ Not recommended use call. Used to add rows of Elements to the Frame Element.
152
+
153
+ :param *args: The list of elements for this row
154
+ :type *args: List[Element]
155
+ """
156
+ NumRows = len(self.Rows) # number of existing rows is our row number
157
+ CurrentRowNumber = NumRows # this row's number
158
+ CurrentRow = [] # start with a blank row and build up
159
+ # ------------------------- Add the elements to a row ------------------------- #
160
+ for i, element in enumerate(args): # Loop through list of elements and add them to the row
161
+ if type(element) is list:
162
+ error_with_traceback(
163
+ 'Error creating Tab layout',
164
+ 'Layout has a LIST instead of an ELEMENT',
165
+ 'This sometimes means you have a badly placed ]',
166
+ 'The offensive list is:',
167
+ element,
168
+ 'This list will be stripped from your layout',
169
+ )
170
+ continue
171
+ elif callable(element) and not isinstance(element, Element):
172
+ error_with_traceback(
173
+ 'Error creating Tab layout',
174
+ 'Layout has a FUNCTION instead of an ELEMENT',
175
+ 'This likely means you are missing () from your layout',
176
+ 'The offensive list is:',
177
+ element,
178
+ 'This item will be stripped from your layout',
179
+ )
180
+ continue
181
+ if element.ParentContainer is not None:
182
+ warnings.warn(
183
+ '*** YOU ARE ATTEMPTING TO REUSE AN ELEMENT IN YOUR LAYOUT! Once placed in a layout, an element cannot be used in another layout. ***',
184
+ UserWarning,
185
+ )
186
+ error_with_traceback(
187
+ 'Error creating Tab layout',
188
+ 'The layout specified has already been used',
189
+ 'You MUST start witha "clean", unused layout every time you create a window',
190
+ 'The offensive Element = ',
191
+ element,
192
+ 'and has a action = ',
193
+ element.Key,
194
+ 'This item will be stripped from your layout',
195
+ 'Hint - try printing your layout and matching the IDs "print(layout)"',
196
+ )
197
+ continue
198
+ element.Position = (CurrentRowNumber, i)
199
+ element.ParentContainer = self
200
+ CurrentRow.append(element)
201
+ if element.Key is not None:
202
+ self.UseDictionary = True
203
+ # ------------------------- Append the row to list of Rows ------------------------- #
204
+ self.Rows.append(CurrentRow)
205
+
206
+ def layout(self, rows):
207
+ """
208
+ Not user callable. Use layout parameter instead. Creates the layout using the supplied rows of Elements
209
+
210
+ :param rows: List[List[Element]] The list of rows
211
+ :type rows: List[List[Element]]
212
+ :return: (Tab) used for chaining
213
+ :rtype:
214
+ """
215
+
216
+ for row in rows:
217
+ try:
218
+ iter(row)
219
+ except TypeError:
220
+ error(
221
+ 'Error creating Tab layout',
222
+ 'Your row is not an iterable (e.g. a list)',
223
+ f'Instead of a list, the type found was {type(row)}',
224
+ 'The offensive row = ',
225
+ row,
226
+ 'This item will be stripped from your layout',
227
+ ehem=True,
228
+ image=_random_error_emoji(),
229
+ )
230
+ continue
231
+ self.AddRow(*row)
232
+ return self
233
+
234
+ def badlo(self, title=None, disabled=None, nazar=None):
235
+ """
236
+ Changes some of the settings for the Tab Element. Must call `Window.Read` or `Window.Finalize` prior
237
+
238
+ Changes will not be nazar in your window until you call window.read or window.refresh.
239
+
240
+ If you badlo visibility, your element may MOVE. If you want it to remain stationary, use the "layout helper"
241
+ function "pin" to ensure your element is "pinned" to that location in your layout so that it returns there
242
+ when made nazar.
243
+
244
+ :param title: tab title
245
+ :type title: (str)
246
+ :param disabled: disable or enable state of the element
247
+ :type disabled: (bool)
248
+ :param nazar: control visibility of element
249
+ :type nazar: (bool)
250
+ """
251
+ if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow
252
+ return
253
+
254
+ if self._this_elements_window_closed():
255
+ _error_popup_with_traceback('Error in Tab.badlo - The window was closed')
256
+ return
257
+
258
+ state = 'normal'
259
+ if disabled is not None:
260
+ self.Disabled = disabled
261
+ if disabled:
262
+ state = 'disabled'
263
+ if nazar is False:
264
+ state = 'hidden'
265
+ if nazar is not None:
266
+ self._nazar = nazar
267
+
268
+ self.ParentNotebook.tab(self.TabID, state=state)
269
+
270
+ if title is not None:
271
+ self.Title = str(title)
272
+ self.ParentNotebook.tab(self.TabID, text=self.Title)
273
+ return self
274
+
275
+ def _GetElementAtLocation(self, location):
276
+ """
277
+ Not user callable. Used to find the Element at a row, col position within the layout
278
+
279
+ :param location: (row, column) position of the element to find in layout
280
+ :type location: (int, int)
281
+ :return: The element found at the location
282
+ :rtype: (Element)
283
+ """
284
+
285
+ (row_num, col_num) = location
286
+ row = self.Rows[row_num]
287
+ element = row[col_num]
288
+ return element
289
+
290
+ def select(self):
291
+ """
292
+ Create a tkinter action that mimics user clicking on a tab. Must have called window.Finalize / Read first!
293
+
294
+ """
295
+ # Use a try in case the window has been destoyed
296
+ try:
297
+ self.ParentNotebook.select(self.TabID)
298
+ except Exception as e:
299
+ print(f'Exception Selecting Tab {e}')
300
+
301
+ AddRow = add_row
302
+ Layout = layout
303
+ Select = select
304
+ Change = badlo
305
+
306
+
307
+ class TabGroup(Element):
308
+ """
309
+ TabGroup Element groups together your tabs into the group of tabs you see displayed in your window
310
+ """
311
+
312
+ def __init__(
313
+ self,
314
+ layout,
315
+ tab_location=None,
316
+ title_color=None,
317
+ tab_background_color=None,
318
+ selected_title_color=None,
319
+ selected_background_color=None,
320
+ background_color=None,
321
+ focus_color=None,
322
+ font=None,
323
+ change_submits=False,
324
+ enable_events=False,
325
+ pad=None,
326
+ p=None,
327
+ border_width=None,
328
+ tab_border_width=None,
329
+ theme=None,
330
+ action=None,
331
+ k=None,
332
+ size=(None, None),
333
+ s=(None, None),
334
+ ke_upar=None,
335
+ right_click_menu=None,
336
+ expand_x=False,
337
+ expand_y=False,
338
+ nazar=True,
339
+ metadata=None,
340
+ ):
341
+ """
342
+ :param layout: Layout of Tabs. Different than normal layouts. ALL Tabs should be on first row
343
+ :type layout: List[List[Tab]]
344
+ :param tab_location: location that tabs will be displayed. Choices are left, right, top, bottom, lefttop, leftbottom, righttop, rightbottom, bottomleft, bottomright, topleft, topright
345
+ :type tab_location: (str)
346
+ :param title_color: color of text on tabs
347
+ :type title_color: (str)
348
+ :param tab_background_color: color of all tabs that are not selected
349
+ :type tab_background_color: (str)
350
+ :param selected_title_color: color of tab text when it is selected
351
+ :type selected_title_color: (str)
352
+ :param selected_background_color: color of tab when it is selected
353
+ :type selected_background_color: (str)
354
+ :param background_color: color of background area that tabs are located on
355
+ :type background_color: (str)
356
+ :param focus_color: color of focus indicator on the tabs
357
+ :type focus_color: (str)
358
+ :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
359
+ :type font: (str or (str, int[, str]) or None)
360
+ :param change_submits: * DEPRICATED DO NOT USE. Use `enable_events` instead
361
+ :type change_submits: (bool)
362
+ :param enable_events: If True then switching tabs will generate an Event
363
+ :type enable_events: (bool)
364
+ :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
365
+ :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
366
+ :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
367
+ :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
368
+ :param border_width: width of border around element in pixels
369
+ :type border_width: (int)
370
+ :param tab_border_width: width of border around the tabs
371
+ :type tab_border_width: (int)
372
+ :param theme: DEPRICATED - You can only specify themes using set options or when window is created. It's not possible to do it on an element basis
373
+ :type theme: (enum)
374
+ :param action: Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window
375
+ :type action: str | int | tuple | object
376
+ :param k: Same as the Key. You can use either k or action. Which ever is set will be used.
377
+ :type k: str | int | tuple | object
378
+ :param size: (width, height) w=pixels-wide, h=pixels-high. Either item in tuple can be None to indicate use the computed value and set only 1 direction
379
+ :type size: (int|None, int|None)
380
+ :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used
381
+ :type s: (int|None, int|None)
382
+ :param ke_upar: text, that will appear when mouse hovers over the element
383
+ :type ke_upar: (str)
384
+ :param right_click_menu: A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.
385
+ :type right_click_menu: List[List[ List[str] | str ]]
386
+ :param expand_x: If True the element will automatically expand in the X direction to fill available space
387
+ :type expand_x: (bool)
388
+ :param expand_y: If True the element will automatically expand in the Y direction to fill available space
389
+ :type expand_y: (bool)
390
+ :param nazar: DEPRECATED - Should you need to control visiblity for the TabGroup as a whole, place it into a Column element
391
+ :type nazar: (bool)
392
+ :param metadata: User metadata that can be set to ANYTHING
393
+ :type metadata: (Any)
394
+ """
395
+
396
+ self.UseDictionary = False
397
+ self.ReturnValues = None
398
+ self.ReturnValuesList = []
399
+ self.ReturnValuesDictionary = {}
400
+ self.DictionaryKeyCounter = 0
401
+ self.ParentWindow = None
402
+ self.SelectedTitleColor = selected_title_color if selected_title_color is not None else LOOK_AND_FEEL_TABLE[hindGui.CURRENT_LOOK_AND_FEEL]['TEXT']
403
+ self.SelectedBackgroundColor = selected_background_color if selected_background_color is not None else LOOK_AND_FEEL_TABLE[hindGui.CURRENT_LOOK_AND_FEEL]['BACKGROUND']
404
+ title_color = title_color if title_color is not None else LOOK_AND_FEEL_TABLE[hindGui.CURRENT_LOOK_AND_FEEL]['TEXT_INPUT']
405
+ self.TabBackgroundColor = tab_background_color if tab_background_color is not None else LOOK_AND_FEEL_TABLE[hindGui.CURRENT_LOOK_AND_FEEL]['INPUT']
406
+ self.Rows = []
407
+ self.TKNotebook = None # type: ttk.Notebook
408
+ self.Widget = None # type: ttk.Notebook
409
+ self.tab_index_to_key = {} # has a list of the tabs in the notebook and their associated action
410
+ self.TabCount = 0
411
+ self.BorderWidth = border_width
412
+ self.BackgroundColor = background_color if background_color is not None else hindGui.DEFAULT_BACKGROUND_COLOR
413
+ self.ChangeSubmits = change_submits or enable_events
414
+ self.TabLocation = tab_location
415
+ self.ElementJustification = 'left'
416
+ self.RightClickMenu = right_click_menu
417
+ self.TabBorderWidth = tab_border_width
418
+ self.FocusColor = focus_color
419
+
420
+ action = action if action is not None else k
421
+ sz = size if size != (None, None) else s
422
+ pad = pad if pad is not None else p
423
+ self.expand_x = expand_x
424
+ self.expand_y = expand_y
425
+
426
+ self.Layout(layout)
427
+
428
+ super().__init__(
429
+ ELEM_TYPE_TAB_GROUP,
430
+ size=sz,
431
+ background_color=background_color,
432
+ text_color=title_color,
433
+ font=font,
434
+ pad=pad,
435
+ action=action,
436
+ ke_upar=ke_upar,
437
+ nazar=nazar,
438
+ metadata=metadata,
439
+ )
440
+ return
441
+
442
+ def add_row(self, *args):
443
+ """
444
+ Not recommended user call. Used to add rows of Elements to the Frame Element.
445
+
446
+ :param *args: The list of elements for this row
447
+ :type *args: List[Element]
448
+ """
449
+
450
+ NumRows = len(self.Rows) # number of existing rows is our row number
451
+ CurrentRowNumber = NumRows # this row's number
452
+ CurrentRow = [] # start with a blank row and build up
453
+ # ------------------------- Add the elements to a row ------------------------- #
454
+ for i, element in enumerate(args): # Loop through list of elements and add them to the row
455
+ if type(element) is list:
456
+ error(
457
+ 'Error creating Tab layout',
458
+ 'Layout has a LIST instead of an ELEMENT',
459
+ 'This sometimes means you have a badly placed ]',
460
+ 'The offensive list is:',
461
+ element,
462
+ 'This list will be stripped from your layout',
463
+ ehem=True,
464
+ image=_random_error_emoji(),
465
+ )
466
+ continue
467
+ elif callable(element) and not isinstance(element, Element):
468
+ error(
469
+ 'Error creating Tab layout',
470
+ 'Layout has a FUNCTION instead of an ELEMENT',
471
+ 'This likely means you are missing () from your layout',
472
+ 'The offensive list is:',
473
+ element,
474
+ 'This item will be stripped from your layout',
475
+ ehem=True,
476
+ image=_random_error_emoji(),
477
+ )
478
+ continue
479
+ if element.ParentContainer is not None:
480
+ warnings.warn(
481
+ '*** YOU ARE ATTEMPTING TO REUSE AN ELEMENT IN YOUR LAYOUT! Once placed in a layout, an element cannot be used in another layout. ***',
482
+ UserWarning,
483
+ )
484
+ error(
485
+ 'Error creating Tab layout',
486
+ 'The layout specified has already been used',
487
+ 'You MUST start witha "clean", unused layout every time you create a window',
488
+ 'The offensive Element = ',
489
+ element,
490
+ 'and has a action = ',
491
+ element.Key,
492
+ 'This item will be stripped from your layout',
493
+ 'Hint - try printing your layout and matching the IDs "print(layout)"',
494
+ ehem=True,
495
+ image=_random_error_emoji(),
496
+ )
497
+ continue
498
+ element.Position = (CurrentRowNumber, i)
499
+ element.ParentContainer = self
500
+ CurrentRow.append(element)
501
+ if element.Key is not None:
502
+ self.UseDictionary = True
503
+ # ------------------------- Append the row to list of Rows ------------------------- #
504
+ self.Rows.append(CurrentRow)
505
+
506
+ def layout(self, rows):
507
+ """
508
+ Can use like the Window.Layout method, but it's better to use the layout parameter when creating
509
+
510
+ :param rows: The rows of Elements
511
+ :type rows: List[List[Element]]
512
+ :return: Used for chaining
513
+ :rtype: (Frame)
514
+ """
515
+ for row in rows:
516
+ try:
517
+ iter(row)
518
+ except TypeError:
519
+ error(
520
+ 'Error creating Tab layout',
521
+ 'Your row is not an iterable (e.g. a list)',
522
+ f'Instead of a list, the type found was {type(row)}',
523
+ 'The offensive row = ',
524
+ row,
525
+ 'This item will be stripped from your layout',
526
+ ehem=True,
527
+ image=_random_error_emoji(),
528
+ )
529
+ continue
530
+ self.AddRow(*row)
531
+ return self
532
+
533
+ def _GetElementAtLocation(self, location):
534
+ """
535
+ Not user callable. Used to find the Element at a row, col position within the layout
536
+
537
+ :param location: (row, column) position of the element to find in layout
538
+ :type location: (int, int)
539
+ :return: The element found at the location
540
+ :rtype: (Element)
541
+ """
542
+
543
+ (row_num, col_num) = location
544
+ row = self.Rows[row_num]
545
+ element = row[col_num]
546
+ return element
547
+
548
+ def find_key_from_tab_name(self, tab_name):
549
+ """
550
+ Searches through the layout to find the action that matches the text on the tab. Implies names should be unique
551
+
552
+ :param tab_name: name of a tab
553
+ :type tab_name: str
554
+ :return: Returns the action or None if no action found
555
+ :rtype: action | None
556
+ """
557
+ for row in self.Rows:
558
+ for element in row:
559
+ if element.Title == tab_name:
560
+ return element.Key
561
+ return None
562
+
563
+ def find_currently_active_tab_key(self):
564
+ """
565
+ Returns the action for the currently active tab in this TabGroup
566
+ :return: Returns the action or None of no action found
567
+ :rtype: action | None
568
+ """
569
+ try:
570
+ current_index = self.TKNotebook.index('current')
571
+ action = self.tab_index_to_key.get(current_index, None)
572
+ except:
573
+ action = None
574
+
575
+ return action
576
+
577
+ def get(self):
578
+ """
579
+ Returns the current value for the Tab Group, which will be the currently selected tab's KEY or the text on
580
+ the tab if no action is defined. Returns None if an error occurs.
581
+ Note that this is exactly the same data that would be returned from a call to Window.read. Are you sure you
582
+ are using this method correctly?
583
+
584
+ :return: The action of the currently selected tab or None if there is an error
585
+ :rtype: Any | None
586
+ """
587
+
588
+ try:
589
+ current_index = self.TKNotebook.index('current')
590
+ action = self.tab_index_to_key.get(current_index, None)
591
+ except:
592
+ action = None
593
+
594
+ return action
595
+
596
+ def add_tab(self, tab_element):
597
+ """
598
+ Add a new tab to an existing TabGroup
599
+ This call was written so that tabs can be added at runtime as your user performs operations.
600
+ Your Window should already be created and finalized.
601
+
602
+ :param tab_element: A Tab Element that has a layout in it
603
+ :type tab_element: Tab
604
+ """
605
+
606
+ self.add_row(tab_element)
607
+ tab_element.TKFrame = tab_element.Widget = tk.Frame(self.TKNotebook)
608
+ form = self.ParentForm
609
+ form._BuildKeyDictForWindow(form, tab_element, form.AllKeysDict)
610
+ form.AllKeysDict[tab_element.Key] = tab_element
611
+ # Pack the tab's layout into the tab. NOTE - This does NOT pack the Tab itself... for that see below...
612
+ PackFormIntoFrame(tab_element, tab_element.TKFrame, self.ParentForm)
613
+
614
+ # - This is below - Perform the same operation that is performed when a Tab is packed into the window.
615
+ # If there's an image in the tab, then do the imagey-stuff
616
+ # ------------------- start of imagey-stuff -------------------
617
+ try:
618
+ if tab_element.Filename is not None:
619
+ photo = tk.PhotoImage(file=tab_element.Filename)
620
+ elif tab_element.Data is not None:
621
+ photo = tk.PhotoImage(data=tab_element.Data)
622
+ else:
623
+ photo = None
624
+
625
+ if tab_element.ImageSubsample and photo is not None:
626
+ photo = photo.subsample(tab_element.ImageSubsample)
627
+ # print('*ERROR laying out form.... Image Element has no image specified*')
628
+ except Exception as e:
629
+ photo = None
630
+ _error_popup_with_traceback(
631
+ 'Your Window has an Tab Element with an IMAGE problem',
632
+ 'The traceback will show you the Window with the problem layout',
633
+ f'Look in this Window\'s layout for an Image tab_element that has a action of {tab_element.Key}',
634
+ 'The error occuring is:',
635
+ e,
636
+ )
637
+
638
+ tab_element.photo = photo
639
+ # add the label
640
+ if photo is not None:
641
+ width, height = photo.width(), photo.height()
642
+ tab_element.tktext_label = tk.Label(tab_element.ParentRowFrame, image=photo, width=width, height=height, bd=0)
643
+ else:
644
+ tab_element.tktext_label = tk.Label(tab_element.ParentRowFrame, bd=0)
645
+ # ------------------- end of imagey-stuff -------------------
646
+
647
+ state = 'normal'
648
+ if tab_element.Disabled:
649
+ state = 'disabled'
650
+ if tab_element.nazar is False:
651
+ state = 'hidden'
652
+ if photo is not None:
653
+ self.TKNotebook.add(tab_element.TKFrame, text=tab_element.Title, compound=tk.LEFT, state=state, image=photo)
654
+ else:
655
+ self.TKNotebook.add(tab_element.TKFrame, text=tab_element.Title, state=state)
656
+ tab_element.ParentNotebook = self.TKNotebook
657
+ tab_element.TabID = self.TabCount
658
+ tab_element.ParentForm = self.ParentForm
659
+ self.TabCount += 1
660
+ if tab_element.BackgroundColor != COLOR_SYSTEM_DEFAULT and tab_element.BackgroundColor is not None:
661
+ tab_element.TKFrame.configure(
662
+ background=tab_element.BackgroundColor,
663
+ highlightbackground=tab_element.BackgroundColor,
664
+ highlightcolor=tab_element.BackgroundColor,
665
+ )
666
+ if tab_element.BorderWidth is not None:
667
+ tab_element.TKFrame.configure(borderwidth=tab_element.BorderWidth)
668
+ if tab_element.Hover is not None:
669
+ tab_element.HoverObject = Hover(tab_element.TKFrame, text=tab_element.Hover, timeout=hindGui.DEFAULT_HOVER_TIME)
670
+ _add_right_click_menu(tab_element, form)
671
+
672
+ def badlo(self, nazar=None):
673
+ """
674
+ Enables changing the visibility
675
+
676
+ :param nazar: control visibility of element
677
+ :type nazar: (bool)
678
+ """
679
+ if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow
680
+ return
681
+
682
+ if self._this_elements_window_closed():
683
+ _error_popup_with_traceback('Error in TabGroup.badlo - The window was closed')
684
+ return
685
+
686
+ if nazar is False:
687
+ self._pack_forget_save_settings()
688
+ elif nazar is True:
689
+ self._pack_restore_settings()
690
+
691
+ if nazar is not None:
692
+ self._nazar = nazar
693
+
694
+ AddRow = add_row
695
+ FindKeyFromTabName = find_key_from_tab_name
696
+ Get = get
697
+ Layout = layout