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,817 @@
1
+ from __future__ import annotations
2
+
3
+ import tkinter as tk
4
+ from math import floor
5
+
6
+ from hindGui import COLOR_SYSTEM_DEFAULT
7
+ from hindGui import ELEM_TYPE_GRAPH
8
+ from hindGui import Element
9
+ from hindGui import TEXT_LOCATION_CENTER
10
+ from hindGui._utils import _error_popup_with_traceback
11
+ from hindGui._utils import _exit_mainloop
12
+
13
+
14
+ class Graph(Element):
15
+ """
16
+ Creates an area for you to draw on. The MAGICAL property this Element has is that you interact
17
+ with the element using your own coordinate system. This is an important point!! YOU define where the location
18
+ is for (0,0). Want (0,0) to be in the middle of the graph like a math 4-quadrant graph? No problem! Set your
19
+ lower left corner to be (-100,-100) and your upper right to be (100,100) and you've got yourself a graph with
20
+ (0,0) at the center.
21
+ One of THE coolest of the Elements.
22
+ You can also use float values. To do so, be sure and set the float_values parameter.
23
+ Mouse click and drag events are possible and return the (x,y) coordinates of the mouse
24
+ Drawing primitives return an "id" that is referenced when you want to operation on that item (e.g. to erase it)
25
+ """
26
+
27
+ def __init__(
28
+ self,
29
+ canvas_size,
30
+ graph_bottom_left,
31
+ graph_top_right,
32
+ background_color=None,
33
+ pad=None,
34
+ p=None,
35
+ change_submits=False,
36
+ drag_submits=False,
37
+ enable_events=False,
38
+ motion_events=False,
39
+ action=None,
40
+ k=None,
41
+ ke_upar=None,
42
+ right_click_menu=None,
43
+ expand_x=False,
44
+ expand_y=False,
45
+ nazar=True,
46
+ float_values=False,
47
+ border_width=0,
48
+ metadata=None,
49
+ ):
50
+ """
51
+ :param canvas_size: size of the canvas area in pixels
52
+ :type canvas_size: (int, int)
53
+ :param graph_bottom_left: (x,y) The bottoms left corner of your coordinate system
54
+ :type graph_bottom_left: (int, int)
55
+ :param graph_top_right: (x,y) The top right corner of your coordinate system
56
+ :type graph_top_right: (int, int)
57
+ :param background_color: background color of the drawing area
58
+ :type background_color: (str)
59
+ :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)
60
+ :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
61
+ :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
62
+ :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
63
+ :param change_submits: * DEPRICATED DO NOT USE. Use `enable_events` instead
64
+ :type change_submits: (bool)
65
+ :param drag_submits: if True and Events are enabled for the Graph, will report Events any time the mouse moves while button down. When the mouse button is released, you'll get an action = graph action + '+UP' (if action is a string.. if not a string, it'll be made into a tuple)
66
+ :type drag_submits: (bool)
67
+ :param enable_events: If True then clicks on the Graph are immediately reported as an action. Use this instead of change_submits
68
+ :type enable_events: (bool)
69
+ :param motion_events: If True then if no button is down and the mouse is moved, an action is generated with action = graph action + '+MOVE' (if action is a string, it not a string then a tuple is returned)
70
+ :type motion_events: (bool)
71
+ :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
72
+ :type action: str | int | tuple | object
73
+ :param k: Same as the Key. You can use either k or action. Which ever is set will be used.
74
+ :type k: str | int | tuple | object
75
+ :param ke_upar: text, that will appear when mouse hovers over the element
76
+ :type ke_upar: (str)
77
+ :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.
78
+ :type right_click_menu: List[List[ List[str] | str ]]
79
+ :param expand_x: If True the element will automatically expand in the X direction to fill available space
80
+ :type expand_x: (bool)
81
+ :param expand_y: If True the element will automatically expand in the Y direction to fill available space
82
+ :type expand_y: (bool)
83
+ :param nazar: set visibility state of the element (Default = True)
84
+ :type nazar: (bool)
85
+ :param float_values: If True x,y coordinates are returned as floats, not ints
86
+ :type float_values: (bool)
87
+ :param border_width: width of border around element in pixels. Not normally used for Graph Elements
88
+ :type border_width: (int)
89
+ :param metadata: User metadata that can be set to ANYTHING
90
+ :type metadata: (Any)
91
+ """
92
+
93
+ self.CanvasSize = canvas_size
94
+ self.BottomLeft = graph_bottom_left
95
+ self.TopRight = graph_top_right
96
+ # self._TKCanvas = None # type: tk.Canvas
97
+ self._TKCanvas2 = self.Widget = None # type: tk.Canvas
98
+ self.ChangeSubmits = change_submits or enable_events
99
+ self.DragSubmits = drag_submits
100
+ self.ClickPosition = (None, None)
101
+ self.MouseButtonDown = False
102
+ self.Images = {}
103
+ self.RightClickMenu = right_click_menu
104
+ self.FloatValues = float_values
105
+ self.BorderWidth = border_width
106
+ action = action if action is not None else k
107
+ pad = pad if pad is not None else p
108
+ self.expand_x = expand_x
109
+ self.expand_y = expand_y
110
+ self.motion_events = motion_events
111
+
112
+ super().__init__(
113
+ ELEM_TYPE_GRAPH,
114
+ background_color=background_color,
115
+ size=canvas_size,
116
+ pad=pad,
117
+ action=action,
118
+ ke_upar=ke_upar,
119
+ nazar=nazar,
120
+ metadata=metadata,
121
+ )
122
+ return
123
+
124
+ def _convert_xy_to_canvas_xy(self, x_in, y_in):
125
+ """
126
+ Not user callable. Used to convert user's coordinates into the ones used by tkinter
127
+ :param x_in: The x coordinate to convert
128
+ :type x_in: int | float
129
+ :param y_in: The y coordinate to convert
130
+ :type y_in: int | float
131
+ :return: (int, int) The converted canvas coordinates
132
+ :rtype: (int, int)
133
+ """
134
+ if None in (x_in, y_in):
135
+ return None, None
136
+ try:
137
+ scale_x = (self.CanvasSize[0] - 0) / (self.TopRight[0] - self.BottomLeft[0])
138
+ scale_y = (0 - self.CanvasSize[1]) / (self.TopRight[1] - self.BottomLeft[1])
139
+ except:
140
+ scale_x = scale_y = 0
141
+
142
+ new_x = 0 + scale_x * (x_in - self.BottomLeft[0])
143
+ new_y = self.CanvasSize[1] + scale_y * (y_in - self.BottomLeft[1])
144
+ return new_x, new_y
145
+
146
+ def _convert_canvas_xy_to_xy(self, x_in, y_in):
147
+ """
148
+ Not user callable. Used to convert tkinter Canvas coords into user's coordinates
149
+
150
+ :param x_in: The x coordinate in canvas coordinates
151
+ :type x_in: (int)
152
+ :param y_in: (int) The y coordinate in canvas coordinates
153
+ :type y_in:
154
+ :return: The converted USER coordinates
155
+ :rtype: (int, int) | Tuple[float, float]
156
+ """
157
+ if None in (x_in, y_in):
158
+ return None, None
159
+ scale_x = (self.CanvasSize[0] - 0) / (self.TopRight[0] - self.BottomLeft[0])
160
+ scale_y = (0 - self.CanvasSize[1]) / (self.TopRight[1] - self.BottomLeft[1])
161
+
162
+ new_x = x_in / scale_x + self.BottomLeft[0]
163
+ new_y = (y_in - self.CanvasSize[1]) / scale_y + self.BottomLeft[1]
164
+ if self.FloatValues:
165
+ return new_x, new_y
166
+ else:
167
+ return floor(new_x), floor(new_y)
168
+
169
+ def draw_line(self, point_from, point_to, color='black', width=1):
170
+ """
171
+ Draws a line from one point to another point using USER'S coordinates. Can set the color and width of line
172
+ :param point_from: Starting point for line
173
+ :type point_from: (int, int) | Tuple[float, float]
174
+ :param point_to: Ending point for line
175
+ :type point_to: (int, int) | Tuple[float, float]
176
+ :param color: Color of the line
177
+ :type color: (str)
178
+ :param width: width of line in pixels
179
+ :type width: (int)
180
+ :return: id returned from tktiner or None if user closed the window. id is used when you
181
+ :rtype: int | None
182
+ """
183
+ if point_from == (None, None):
184
+ return
185
+ converted_point_from = self._convert_xy_to_canvas_xy(point_from[0], point_from[1])
186
+ converted_point_to = self._convert_xy_to_canvas_xy(point_to[0], point_to[1])
187
+ if self._TKCanvas2 is None:
188
+ print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
189
+ print('Call Window.Finalize() prior to this operation')
190
+ return None
191
+ try: # in case window was closed with an X
192
+ id = self._TKCanvas2.create_line(converted_point_from, converted_point_to, width=width, fill=color)
193
+ except:
194
+ id = None
195
+ return id
196
+
197
+ def draw_lines(self, points, color='black', width=1):
198
+ """
199
+ Draw a series of lines given list of points
200
+
201
+ :param points: list of points that define the polygon
202
+ :type points: List[(int, int) | Tuple[float, float]]
203
+ :param color: Color of the line
204
+ :type color: (str)
205
+ :param width: width of line in pixels
206
+ :type width: (int)
207
+ :return: id returned from tktiner or None if user closed the window. id is used when you
208
+ :rtype: int | None
209
+ """
210
+ converted_points = [self._convert_xy_to_canvas_xy(point[0], point[1]) for point in points]
211
+
212
+ try: # in case window was closed with an X
213
+ id = self._TKCanvas2.create_line(*converted_points, width=width, fill=color)
214
+ except:
215
+ if self._TKCanvas2 is None:
216
+ print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
217
+ print('Call Window.Finalize() prior to this operation')
218
+ id = None
219
+ return id
220
+
221
+ def draw_point(self, point, size=2, color='black'):
222
+ """
223
+ Draws a "dot" at the point you specify using the USER'S coordinate system
224
+ :param point: Center location using USER'S coordinate system
225
+ :type point: (int, int) | Tuple[float, float]
226
+ :param size: Radius? (Or is it the diameter?) in user's coordinate values.
227
+ :type size: int | float
228
+ :param color: color of the point to draw
229
+ :type color: (str)
230
+ :return: id returned from tkinter that you'll need if you want to manipulate the point
231
+ :rtype: int | None
232
+ """
233
+ if point == (None, None):
234
+ return
235
+ converted_point = self._convert_xy_to_canvas_xy(point[0], point[1])
236
+ size_converted = self._convert_xy_to_canvas_xy(point[0] + size, point[1])
237
+ size = size_converted[0] - converted_point[0]
238
+ if self._TKCanvas2 is None:
239
+ print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
240
+ print('Call Window.Finalize() prior to this operation')
241
+ return None
242
+ try: # needed in case window was closed with an X
243
+ point1 = converted_point[0] - size // 2, converted_point[1] - size // 2
244
+ point2 = converted_point[0] + size // 2, converted_point[1] + size // 2
245
+ id = self._TKCanvas2.create_oval(point1[0], point1[1], point2[0], point2[1], width=0, fill=color, outline=color)
246
+ except:
247
+ id = None
248
+ return id
249
+
250
+ def draw_circle(self, center_location, radius, fill_color=None, line_color='black', line_width=1):
251
+ """
252
+ Draws a circle, cenetered at the location provided. Can set the fill and outline colors
253
+ :param center_location: Center location using USER'S coordinate system
254
+ :type center_location: (int, int) | Tuple[float, float]
255
+ :param radius: Radius in user's coordinate values.
256
+ :type radius: int | float
257
+ :param fill_color: color of the point to draw
258
+ :type fill_color: (str)
259
+ :param line_color: color of the outer line that goes around the circle (sorry, can't set thickness)
260
+ :type line_color: (str)
261
+ :param line_width: width of the line around the circle, the outline, in pixels
262
+ :type line_width: (int)
263
+ :return: id returned from tkinter that you'll need if you want to manipulate the circle
264
+ :rtype: int | None
265
+ """
266
+ if center_location == (None, None):
267
+ return
268
+ converted_point = self._convert_xy_to_canvas_xy(center_location[0], center_location[1])
269
+ radius_converted = self._convert_xy_to_canvas_xy(center_location[0] + radius, center_location[1])
270
+ radius = radius_converted[0] - converted_point[0]
271
+ # radius = radius_converted[1]-5
272
+ if self._TKCanvas2 is None:
273
+ print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
274
+ print('Call Window.Finalize() prior to this operation')
275
+ return None
276
+ try: # needed in case the window was closed with an X
277
+ id = self._TKCanvas2.create_oval(
278
+ int(converted_point[0]) - int(radius),
279
+ int(converted_point[1]) - int(radius),
280
+ int(converted_point[0]) + int(radius),
281
+ int(converted_point[1]) + int(radius),
282
+ fill=fill_color,
283
+ outline=line_color,
284
+ width=line_width,
285
+ )
286
+ except:
287
+ id = None
288
+ return id
289
+
290
+ def draw_oval(self, top_left, bottom_right, fill_color=None, line_color=None, line_width=1):
291
+ """
292
+ Draws an oval based on coordinates in user coordinate system. Provide the location of a "bounding rectangle"
293
+ :param top_left: the top left point of bounding rectangle
294
+ :type top_left: (int, int) | Tuple[float, float]
295
+ :param bottom_right: the bottom right point of bounding rectangle
296
+ :type bottom_right: (int, int) | Tuple[float, float]
297
+ :param fill_color: color of the interrior
298
+ :type fill_color: (str)
299
+ :param line_color: color of outline of oval
300
+ :type line_color: (str)
301
+ :param line_width: width of the line around the oval, the outline, in pixels
302
+ :type line_width: (int)
303
+ :return: id returned from tkinter that you'll need if you want to manipulate the oval
304
+ :rtype: int | None
305
+ """
306
+ converted_top_left = self._convert_xy_to_canvas_xy(top_left[0], top_left[1])
307
+ converted_bottom_right = self._convert_xy_to_canvas_xy(bottom_right[0], bottom_right[1])
308
+ if self._TKCanvas2 is None:
309
+ print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
310
+ print('Call Window.Finalize() prior to this operation')
311
+ return None
312
+ try: # in case windows close with X
313
+ id = self._TKCanvas2.create_oval(
314
+ converted_top_left[0],
315
+ converted_top_left[1],
316
+ converted_bottom_right[0],
317
+ converted_bottom_right[1],
318
+ fill=fill_color,
319
+ outline=line_color,
320
+ width=line_width,
321
+ )
322
+ except:
323
+ id = None
324
+
325
+ return id
326
+
327
+ def draw_arc(self, top_left, bottom_right, extent, start_angle, style=None, arc_color='black', line_width=1, fill_color=None):
328
+ """
329
+ Draws different types of arcs. Uses a "bounding box" to define location
330
+ :param top_left: the top left point of bounding rectangle
331
+ :type top_left: (int, int) | Tuple[float, float]
332
+ :param bottom_right: the bottom right point of bounding rectangle
333
+ :type bottom_right: (int, int) | Tuple[float, float]
334
+ :param extent: Andle to end drawing. Used in conjunction with start_angle
335
+ :type extent: (float)
336
+ :param start_angle: Angle to begin drawing. Used in conjunction with extent
337
+ :type start_angle: (float)
338
+ :param style: Valid choices are One of these Style strings- 'pieslice', 'chord', 'arc', 'first', 'last', 'butt', 'projecting', 'round', 'bevel', 'miter'
339
+ :type style: (str)
340
+ :param arc_color: color to draw arc with
341
+ :type arc_color: (str)
342
+ :param fill_color: color to fill the area
343
+ :type fill_color: (str)
344
+ :return: id returned from tkinter that you'll need if you want to manipulate the arc
345
+ :rtype: int | None
346
+ """
347
+ converted_top_left = self._convert_xy_to_canvas_xy(top_left[0], top_left[1])
348
+ converted_bottom_right = self._convert_xy_to_canvas_xy(bottom_right[0], bottom_right[1])
349
+ tkstyle = tk.PIESLICE if style is None else style
350
+ if self._TKCanvas2 is None:
351
+ print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
352
+ print('Call Window.Finalize() prior to this operation')
353
+ return None
354
+ try: # in case closed with X
355
+ id = self._TKCanvas2.create_arc(
356
+ converted_top_left[0],
357
+ converted_top_left[1],
358
+ converted_bottom_right[0],
359
+ converted_bottom_right[1],
360
+ extent=extent,
361
+ start=start_angle,
362
+ style=tkstyle,
363
+ outline=arc_color,
364
+ width=line_width,
365
+ fill=fill_color,
366
+ )
367
+ except Exception as e:
368
+ print('Error encountered drawing arc.', e)
369
+ id = None
370
+ return id
371
+
372
+ def draw_rectangle(self, top_left, bottom_right, fill_color=None, line_color=None, line_width=None):
373
+ """
374
+ Draw a rectangle given 2 points. Can control the line and fill colors
375
+
376
+ :param top_left: the top left point of rectangle
377
+ :type top_left: (int, int) | Tuple[float, float]
378
+ :param bottom_right: the bottom right point of rectangle
379
+ :type bottom_right: (int, int) | Tuple[float, float]
380
+ :param fill_color: color of the interior
381
+ :type fill_color: (str)
382
+ :param line_color: color of outline
383
+ :type line_color: (str)
384
+ :param line_width: width of the line in pixels
385
+ :type line_width: (int)
386
+ :return: int | None id returned from tkinter that you'll need if you want to manipulate the rectangle
387
+ :rtype: int | None
388
+ """
389
+
390
+ converted_top_left = self._convert_xy_to_canvas_xy(top_left[0], top_left[1])
391
+ converted_bottom_right = self._convert_xy_to_canvas_xy(bottom_right[0], bottom_right[1])
392
+ if self._TKCanvas2 is None:
393
+ print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
394
+ print('Call Window.Finalize() prior to this operation')
395
+ return None
396
+ if line_width is None:
397
+ line_width = 1
398
+ try: # in case closed with X
399
+ id = self._TKCanvas2.create_rectangle(
400
+ converted_top_left[0],
401
+ converted_top_left[1],
402
+ converted_bottom_right[0],
403
+ converted_bottom_right[1],
404
+ fill=fill_color,
405
+ outline=line_color,
406
+ width=line_width,
407
+ )
408
+ except:
409
+ id = None
410
+ return id
411
+
412
+ def draw_polygon(self, points, fill_color=None, line_color=None, line_width=None):
413
+ """
414
+ Draw a polygon given list of points
415
+
416
+ :param points: list of points that define the polygon
417
+ :type points: List[(int, int) | Tuple[float, float]]
418
+ :param fill_color: color of the interior
419
+ :type fill_color: (str)
420
+ :param line_color: color of outline
421
+ :type line_color: (str)
422
+ :param line_width: width of the line in pixels
423
+ :type line_width: (int)
424
+ :return: id returned from tkinter that you'll need if you want to manipulate the rectangle
425
+ :rtype: int | None
426
+ """
427
+
428
+ converted_points = [self._convert_xy_to_canvas_xy(point[0], point[1]) for point in points]
429
+ if self._TKCanvas2 is None:
430
+ print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
431
+ print('Call Window.Finalize() prior to this operation')
432
+ return None
433
+ try: # in case closed with X
434
+ id = self._TKCanvas2.create_polygon(converted_points, fill=fill_color, outline=line_color, width=line_width)
435
+ except:
436
+ id = None
437
+ return id
438
+
439
+ def draw_text(self, text, location, color='black', font=None, angle=0, text_location=TEXT_LOCATION_CENTER):
440
+ """
441
+ Draw some text on your graph. This is how you label graph number lines for example
442
+
443
+ :param text: text to display
444
+ :type text: (Any)
445
+ :param location: location to place first letter
446
+ :type location: (int, int) | Tuple[float, float]
447
+ :param color: text color
448
+ :type color: (str)
449
+ :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
450
+ :type font: (str or (str, int[, str]) or None)
451
+ :param angle: Angle 0 to 360 to draw the text. Zero represents horizontal text
452
+ :type angle: (float)
453
+ :param text_location: "anchor" location for the text. Values start with TEXT_LOCATION_
454
+ :type text_location: (enum)
455
+ :return: id returned from tkinter that you'll need if you want to manipulate the text
456
+ :rtype: int | None
457
+ """
458
+ text = str(text)
459
+ if location == (None, None):
460
+ return
461
+ converted_point = self._convert_xy_to_canvas_xy(location[0], location[1])
462
+ if self._TKCanvas2 is None:
463
+ print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
464
+ print('Call Window.Finalize() prior to this operation')
465
+ return None
466
+ try: # in case closed with X
467
+ id = self._TKCanvas2.create_text(
468
+ converted_point[0],
469
+ converted_point[1],
470
+ text=text,
471
+ font=font,
472
+ fill=color,
473
+ angle=angle,
474
+ anchor=text_location,
475
+ )
476
+ except:
477
+ id = None
478
+ return id
479
+
480
+ def draw_image(self, filename=None, data=None, location=(None, None)):
481
+ """
482
+ Places an image onto your canvas. It's a really important method for this element as it enables so much
483
+
484
+ :param filename: if image is in a file, path and filename for the image. (GIF and PNG only!)
485
+ :type filename: (str)
486
+ :param data: if image is in Base64 format or raw? format then use instead of filename
487
+ :type data: str | bytes
488
+ :param location: the (x,y) location to place image's top left corner
489
+ :type location: (int, int) | Tuple[float, float]
490
+ :return: id returned from tkinter that you'll need if you want to manipulate the image
491
+ :rtype: int | None
492
+ """
493
+ if location == (None, None):
494
+ return
495
+ if filename is not None:
496
+ image = tk.PhotoImage(file=filename)
497
+ elif data is not None:
498
+ # if type(data) is bytes:
499
+ try:
500
+ image = tk.PhotoImage(data=data)
501
+ except:
502
+ return None # an error likely means the window has closed so exit
503
+ converted_point = self._convert_xy_to_canvas_xy(location[0], location[1])
504
+ if self._TKCanvas2 is None:
505
+ print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
506
+ print('Call Window.Finalize() prior to this operation')
507
+ return None
508
+ try: # in case closed with X
509
+ id = self._TKCanvas2.create_image(converted_point, image=image, anchor=tk.NW)
510
+ self.Images[id] = image
511
+ except:
512
+ id = None
513
+ return id
514
+
515
+ def erase(self):
516
+ """
517
+ Erase the Graph - Removes all figures previously "drawn" using the Graph methods (e.g. DrawText)
518
+ """
519
+ if self._TKCanvas2 is None:
520
+ print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
521
+ print('Call Window.Finalize() prior to this operation')
522
+ return None
523
+ self.Images = {}
524
+ try: # in case window was closed with X
525
+ self._TKCanvas2.delete('all')
526
+ except:
527
+ pass
528
+
529
+ def delete_figure(self, id):
530
+ """
531
+ Remove from the Graph the figure represented by id. The id is given to you anytime you call a drawing primitive
532
+
533
+ :param id: the id returned to you when calling one of the drawing methods
534
+ :type id: (int)
535
+ """
536
+ try:
537
+ self._TKCanvas2.delete(id)
538
+ except:
539
+ print(f'DeleteFigure - bad ID {id}')
540
+ try:
541
+ del self.Images[id] # in case was an image. If wasn't an image, then will get exception
542
+ except:
543
+ pass
544
+
545
+ def badlo(self, background_color=None, nazar=None):
546
+ """
547
+ Changes some of the settings for the Graph Element. Must call `Window.Read` or `Window.Finalize` prior
548
+
549
+ Changes will not be nazar in your window until you call window.read or window.refresh.
550
+
551
+ If you badlo visibility, your element may MOVE. If you want it to remain stationary, use the "layout helper"
552
+ function "pin" to ensure your element is "pinned" to that location in your layout so that it returns there
553
+ when made nazar.
554
+
555
+ :param background_color: color of background
556
+ :type background_color: ???
557
+ :param nazar: control visibility of element
558
+ :type nazar: (bool)
559
+ """
560
+ if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow
561
+ return
562
+
563
+ if self._this_elements_window_closed():
564
+ _error_popup_with_traceback('Error in Graph.badlo - The window was closed')
565
+ return
566
+
567
+ if background_color is not None and background_color != COLOR_SYSTEM_DEFAULT:
568
+ self._TKCanvas2.configure(background=background_color)
569
+
570
+ if nazar is False:
571
+ self._pack_forget_save_settings()
572
+ elif nazar is True:
573
+ self._pack_restore_settings()
574
+
575
+ if nazar is not None:
576
+ self._nazar = nazar
577
+
578
+ def move(self, x_direction, y_direction):
579
+ """
580
+ Moves the entire drawing area (the canvas) by some delta from the current position. Units are indicated in your coordinate system indicated number of ticks in your coordinate system
581
+
582
+ :param x_direction: how far to move in the "X" direction in your coordinates
583
+ :type x_direction: int | float
584
+ :param y_direction: how far to move in the "Y" direction in your coordinates
585
+ :type y_direction: int | float
586
+ """
587
+ zero_converted = self._convert_xy_to_canvas_xy(0, 0)
588
+ shift_converted = self._convert_xy_to_canvas_xy(x_direction, y_direction)
589
+ shift_amount = (shift_converted[0] - zero_converted[0], shift_converted[1] - zero_converted[1])
590
+ if self._TKCanvas2 is None:
591
+ print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
592
+ print('Call Window.Finalize() prior to this operation')
593
+ return None
594
+ self._TKCanvas2.move('all', shift_amount[0], shift_amount[1])
595
+
596
+ def move_figure(self, figure, x_direction, y_direction):
597
+ """
598
+ Moves a previously drawn figure using a "delta" from current position
599
+
600
+ :param figure: Previously obtained figure-id. These are returned from all Draw methods
601
+ :type figure: (id)
602
+ :param x_direction: delta to apply to position in the X direction
603
+ :type x_direction: int | float
604
+ :param y_direction: delta to apply to position in the Y direction
605
+ :type y_direction: int | float
606
+ """
607
+ zero_converted = self._convert_xy_to_canvas_xy(0, 0)
608
+ shift_converted = self._convert_xy_to_canvas_xy(x_direction, y_direction)
609
+ shift_amount = (shift_converted[0] - zero_converted[0], shift_converted[1] - zero_converted[1])
610
+ if figure is None:
611
+ print('* move_figure warning - your figure is None *')
612
+ return None
613
+ self._TKCanvas2.move(figure, shift_amount[0], shift_amount[1])
614
+
615
+ def relocate_figure(self, figure, x, y):
616
+ """
617
+ Move a previously made figure to an arbitrary (x,y) location. This differs from the Move methods because it
618
+ uses absolute coordinates versus relative for Move
619
+
620
+ :param figure: Previously obtained figure-id. These are returned from all Draw methods
621
+ :type figure: (id)
622
+ :param x: location on X axis (in user coords) to move the upper left corner of the figure
623
+ :type x: int | float
624
+ :param y: location on Y axis (in user coords) to move the upper left corner of the figure
625
+ :type y: int | float
626
+ """
627
+
628
+ # zero_converted = self._convert_xy_to_canvas_xy(0, 0)
629
+ shift_converted = self._convert_xy_to_canvas_xy(x, y)
630
+ # shift_amount = (shift_converted[0] - zero_converted[0], shift_converted[1] - zero_converted[1])
631
+ if figure is None:
632
+ print('*** WARNING - Your figure is None. It most likely means your did not Finalize your Window ***')
633
+ print('Call Window.Finalize() prior to all graph operations')
634
+ return None
635
+ xy = self._TKCanvas2.coords(figure)
636
+ self._TKCanvas2.move(figure, shift_converted[0] - xy[0], shift_converted[1] - xy[1])
637
+
638
+ def send_figure_to_back(self, figure):
639
+ """
640
+ Changes Z-order of figures on the Graph. Sends the indicated figure to the back of all other drawn figures
641
+
642
+ :param figure: value returned by tkinter when creating the figure / drawing
643
+ :type figure: (int)
644
+ """
645
+ self.TKCanvas.tag_lower(figure) # move figure to the "bottom" of all other figure
646
+
647
+ def bring_figure_to_front(self, figure):
648
+ """
649
+ Changes Z-order of figures on the Graph. Brings the indicated figure to the front of all other drawn figures
650
+
651
+ :param figure: value returned by tkinter when creating the figure / drawing
652
+ :type figure: (int)
653
+ """
654
+ self.TKCanvas.tag_raise(figure) # move figure to the "top" of all other figures
655
+
656
+ def get_figures_at_location(self, location):
657
+ """
658
+ Returns a list of figures located at a particular x,y location within the Graph
659
+
660
+ :param location: point to check
661
+ :type location: (int, int) | Tuple[float, float]
662
+ :return: a list of previously drawn "Figures" (returned from the drawing primitives)
663
+ :rtype: List[int]
664
+ """
665
+ x, y = self._convert_xy_to_canvas_xy(location[0], location[1])
666
+ ids = self.TKCanvas.find_overlapping(x, y, x, y)
667
+ return ids
668
+
669
+ def get_bounding_box(self, figure):
670
+ """
671
+ Given a figure, returns the upper left and lower right bounding box coordinates
672
+
673
+ :param figure: a previously drawing figure
674
+ :type figure: object
675
+ :return: upper left x, upper left y, lower right x, lower right y
676
+ :rtype: Tuple[int, int, int, int] | Tuple[float, float, float, float]
677
+ """
678
+ box = self.TKCanvas.bbox(figure)
679
+ top_left = self._convert_canvas_xy_to_xy(box[0], box[1])
680
+ bottom_right = self._convert_canvas_xy_to_xy(box[2], box[3])
681
+ return top_left, bottom_right
682
+
683
+ def change_coordinates(self, graph_bottom_left, graph_top_right):
684
+ """
685
+ Changes the corrdinate system to a new one. The same 2 points in space are used to define the coorinate
686
+ system - the bottom left and the top right values of your graph.
687
+
688
+ :param graph_bottom_left: The bottoms left corner of your coordinate system
689
+ :type graph_bottom_left: (int, int) (x,y)
690
+ :param graph_top_right: The top right corner of your coordinate system
691
+ :type graph_top_right: (int, int) (x,y)
692
+ """
693
+ self.BottomLeft = graph_bottom_left
694
+ self.TopRight = graph_top_right
695
+
696
+ @property
697
+ def tk_canvas(self):
698
+ """
699
+ Returns the underlying tkiner Canvas widget
700
+
701
+ :return: The tkinter canvas widget
702
+ :rtype: (tk.Canvas)
703
+ """
704
+ if self._TKCanvas2 is None:
705
+ print('*** Did you forget to call Finalize()? Your code should look something like: ***')
706
+ print('*** form = sg.Window("My Form").Layout(layout).Finalize() ***')
707
+ return self._TKCanvas2
708
+
709
+ # button release callback
710
+ def button_release_call_back(self, action):
711
+ """
712
+ Not a user callable method. Used to get Graph click events. Called by tkinter when button is released
713
+
714
+ :param action: (action) action info from tkinter. Note not used in this method
715
+ :type action:
716
+ """
717
+ if not self.DragSubmits:
718
+ return # only report mouse up for drag operations
719
+ self.ClickPosition = self._convert_canvas_xy_to_xy(action.x, action.y)
720
+ self.ParentForm.LastButtonClickedWasRealtime = False
721
+ if self.Key is not None:
722
+ self.ParentForm.LastButtonClicked = self.Key
723
+ else:
724
+ self.ParentForm.LastButtonClicked = '__GRAPH__' # need to put something rather than None
725
+ _exit_mainloop(self.ParentForm)
726
+ if isinstance(self.ParentForm.LastButtonClicked, str):
727
+ self.ParentForm.LastButtonClicked = self.ParentForm.LastButtonClicked + '+UP'
728
+ else:
729
+ self.ParentForm.LastButtonClicked = (self.ParentForm.LastButtonClicked, '+UP')
730
+ self.MouseButtonDown = False
731
+
732
+ # button callback
733
+ def button_press_call_back(self, action):
734
+ """
735
+ Not a user callable method. Used to get Graph click events. Called by tkinter when button is released
736
+
737
+ :param action: (action) action info from tkinter. Contains the x and y coordinates of a click
738
+ :type action:
739
+ """
740
+
741
+ self.ClickPosition = self._convert_canvas_xy_to_xy(action.x, action.y)
742
+ self.ParentForm.LastButtonClickedWasRealtime = self.DragSubmits
743
+ if self.Key is not None:
744
+ self.ParentForm.LastButtonClicked = self.Key
745
+ else:
746
+ self.ParentForm.LastButtonClicked = '__GRAPH__' # need to put something rather than None
747
+ _exit_mainloop(self.ParentForm)
748
+ self.MouseButtonDown = True
749
+
750
+ def _update_position_for_returned_values(self, action):
751
+ """
752
+ Updates the variable that's used when the values dictionary is returned from a window read.
753
+
754
+ Not called by the user. It's called from another method/function that tkinter calledback
755
+
756
+ :param action: (action) action info from tkinter. Contains the x and y coordinates of a click
757
+ :type action:
758
+ """
759
+ """
760
+ Updates the variable that's used when the values dictionary is returned from a window read.
761
+
762
+ Not called by the user. It's called from another method/function that tkinter calledback
763
+
764
+ :param action: (action) action info from tkinter. Contains the x and y coordinates of a click
765
+ :type action:
766
+ """
767
+
768
+ self.ClickPosition = self._convert_canvas_xy_to_xy(action.x, action.y)
769
+
770
+ # button callback
771
+ def motion_call_back(self, action):
772
+ """
773
+ Not a user callable method. Used to get Graph mouse motion events. Called by tkinter when mouse moved
774
+
775
+ :param action: (action) action info from tkinter. Contains the x and y coordinates of a mouse
776
+ :type action:
777
+ """
778
+
779
+ if not self.MouseButtonDown and not self.motion_events:
780
+ return
781
+ self.ClickPosition = self._convert_canvas_xy_to_xy(action.x, action.y)
782
+ self.ParentForm.LastButtonClickedWasRealtime = self.DragSubmits
783
+ if self.Key is not None:
784
+ self.ParentForm.LastButtonClicked = self.Key
785
+ else:
786
+ self.ParentForm.LastButtonClicked = '__GRAPH__' # need to put something rather than None
787
+ if self.motion_events and not self.MouseButtonDown:
788
+ if isinstance(self.ParentForm.LastButtonClicked, str):
789
+ self.ParentForm.LastButtonClicked = self.ParentForm.LastButtonClicked + '+MOVE'
790
+ else:
791
+ self.ParentForm.LastButtonClicked = (self.ParentForm.LastButtonClicked, '+MOVE')
792
+ _exit_mainloop(self.ParentForm)
793
+
794
+ BringFigureToFront = bring_figure_to_front
795
+ ButtonPressCallBack = button_press_call_back
796
+ ButtonReleaseCallBack = button_release_call_back
797
+ DeleteFigure = delete_figure
798
+ DrawArc = draw_arc
799
+ DrawCircle = draw_circle
800
+ DrawImage = draw_image
801
+ DrawLine = draw_line
802
+ DrawOval = draw_oval
803
+ DrawPoint = draw_point
804
+ DrawPolygon = draw_polygon
805
+ DrawLines = draw_lines
806
+ DrawRectangle = draw_rectangle
807
+ DrawText = draw_text
808
+ GetFiguresAtLocation = get_figures_at_location
809
+ GetBoundingBox = get_bounding_box
810
+ Erase = erase
811
+ MotionCallBack = motion_call_back
812
+ Move = move
813
+ MoveFigure = move_figure
814
+ RelocateFigure = relocate_figure
815
+ SendFigureToBack = send_figure_to_back
816
+ TKCanvas = tk_canvas
817
+ Change = badlo