mg-pso-gui 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.
- mg-pso-gui/BoundsEditorWindow.py +74 -0
- mg-pso-gui/BoundsList.py +263 -0
- mg-pso-gui/CTkToolTip/__init__.py +11 -0
- mg-pso-gui/CTkToolTip/ctk_tooltip.py +187 -0
- mg-pso-gui/CalibrationParametersView.py +61 -0
- mg-pso-gui/FunctionsList.py +83 -0
- mg-pso-gui/GraphGenerator.py +215 -0
- mg-pso-gui/ListParametersView.py +173 -0
- mg-pso-gui/OptionManager.py +259 -0
- mg-pso-gui/PSORunner.py +68 -0
- mg-pso-gui/StaticParameterView.py +61 -0
- mg-pso-gui/StepView.py +118 -0
- mg-pso-gui/__init__.py +1 -0
- mg-pso-gui/main.py +485 -0
- mg_pso_gui-0.0.1.dist-info/LICENSE +21 -0
- mg_pso_gui-0.0.1.dist-info/METADATA +23 -0
- mg_pso_gui-0.0.1.dist-info/RECORD +19 -0
- mg_pso_gui-0.0.1.dist-info/WHEEL +5 -0
- mg_pso_gui-0.0.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,74 @@
|
|
1
|
+
from typing import Union, Tuple, Optional
|
2
|
+
|
3
|
+
from customtkinter import CTkLabel
|
4
|
+
from customtkinter import CTkButton
|
5
|
+
from customtkinter import CTkEntry
|
6
|
+
from customtkinter import CTkInputDialog
|
7
|
+
from ListParametersView import ListParametersView
|
8
|
+
|
9
|
+
class BoundsEditorWindow(CTkInputDialog):
|
10
|
+
"""
|
11
|
+
Dialog with extra window, message, entry widget, cancel and ok button.
|
12
|
+
For detailed information check out the documentation.
|
13
|
+
"""
|
14
|
+
|
15
|
+
def __init__(self, *args,
|
16
|
+
step_index: 0,
|
17
|
+
bound_index: 0,
|
18
|
+
option_manager: None,
|
19
|
+
**kwargs):
|
20
|
+
super().__init__(*args, **kwargs)
|
21
|
+
|
22
|
+
self.geometry("400x800")
|
23
|
+
|
24
|
+
self.step_index = step_index
|
25
|
+
self.bound_index = bound_index
|
26
|
+
self.option_manager = option_manager
|
27
|
+
self.bounds = None
|
28
|
+
|
29
|
+
def _create_widgets(self):
|
30
|
+
|
31
|
+
self.grid_columnconfigure((0, 1), weight=1)
|
32
|
+
self.rowconfigure(0, weight=1)
|
33
|
+
|
34
|
+
self.bounds = ListParametersView(
|
35
|
+
self, step_index=self.step_index, bound_index=self.bound_index, option_manager=self.option_manager)
|
36
|
+
self.bounds.grid(row=0, column=0, columnspan=2, padx=(10, 10),
|
37
|
+
pady=(10, 10), sticky="nsew")
|
38
|
+
self.bounds.grid_columnconfigure(0, weight=1)
|
39
|
+
|
40
|
+
self._ok_button = CTkButton(master=self,
|
41
|
+
width=100,
|
42
|
+
border_width=0,
|
43
|
+
fg_color=self._button_fg_color,
|
44
|
+
hover_color=self._button_hover_color,
|
45
|
+
text_color=self._button_text_color,
|
46
|
+
text='Save',
|
47
|
+
command=self._ok_event)
|
48
|
+
self._ok_button.grid(row=2, column=0, columnspan=1, padx=(20, 10), pady=(0, 20), sticky="ew")
|
49
|
+
|
50
|
+
self._cancel_button = CTkButton(master=self,
|
51
|
+
width=100,
|
52
|
+
border_width=0,
|
53
|
+
fg_color=self._button_fg_color,
|
54
|
+
hover_color=self._button_hover_color,
|
55
|
+
text_color=self._button_text_color,
|
56
|
+
text='Cancel',
|
57
|
+
command=self._ok_event)
|
58
|
+
self._cancel_button.grid(row=2, column=1, columnspan=1, padx=(10, 20), pady=(0, 20), sticky="ew")
|
59
|
+
|
60
|
+
def _ok_event(self, event=None):
|
61
|
+
# Save values in bounds editor...
|
62
|
+
|
63
|
+
self.bounds.push_to_option_manager()
|
64
|
+
|
65
|
+
self.grab_release()
|
66
|
+
self.destroy()
|
67
|
+
|
68
|
+
def _on_closing(self):
|
69
|
+
self.grab_release()
|
70
|
+
self.destroy()
|
71
|
+
|
72
|
+
def _cancel_event(self):
|
73
|
+
self.grab_release()
|
74
|
+
self.destroy()
|
mg-pso-gui/BoundsList.py
ADDED
@@ -0,0 +1,263 @@
|
|
1
|
+
from customtkinter import CTkScrollableFrame
|
2
|
+
from customtkinter import CTkFrame
|
3
|
+
from customtkinter import CTkLabel
|
4
|
+
from customtkinter import CTkButton
|
5
|
+
from customtkinter import CTkEntry
|
6
|
+
from customtkinter import CTkOptionMenu
|
7
|
+
from customtkinter import CTkTextbox
|
8
|
+
from customtkinter import CTkImage
|
9
|
+
from BoundsEditorWindow import BoundsEditorWindow
|
10
|
+
from CTkToolTip import *
|
11
|
+
import tkinter as tk
|
12
|
+
import json
|
13
|
+
import PIL
|
14
|
+
from PIL import Image
|
15
|
+
import os
|
16
|
+
|
17
|
+
|
18
|
+
optParams = []
|
19
|
+
|
20
|
+
details = json.load(open("bounds.json", "r"))
|
21
|
+
paramMap = {}
|
22
|
+
for param in details["parameter"]:
|
23
|
+
paramMap[param["name"]] = param
|
24
|
+
if "min" in param:
|
25
|
+
optParams.append(param["name"])
|
26
|
+
|
27
|
+
optParams.sort()
|
28
|
+
|
29
|
+
class BoundsList(CTkFrame):
|
30
|
+
def __init__(self, *args,
|
31
|
+
option_manager: None,
|
32
|
+
step_index: 0,
|
33
|
+
**kwargs):
|
34
|
+
super().__init__(*args, **kwargs)
|
35
|
+
|
36
|
+
self.edit_mode = False
|
37
|
+
self.tooltip_list = []
|
38
|
+
|
39
|
+
self.option_manager = option_manager
|
40
|
+
self.step_index = step_index
|
41
|
+
self.render()
|
42
|
+
|
43
|
+
def clear(self):
|
44
|
+
for list in self.tooltip_list:
|
45
|
+
for tooltip in list:
|
46
|
+
tooltip.destroy()
|
47
|
+
self.containerFrame.destroy()
|
48
|
+
self.tooltip_list = []
|
49
|
+
|
50
|
+
def toggle_edit_mode(self):
|
51
|
+
self.clear()
|
52
|
+
self.edit_mode = not self.edit_mode
|
53
|
+
self.render()
|
54
|
+
|
55
|
+
def refresh(self, *args):
|
56
|
+
self.clear()
|
57
|
+
self.render()
|
58
|
+
|
59
|
+
def render(self):
|
60
|
+
row = 0
|
61
|
+
index = 0
|
62
|
+
|
63
|
+
self.tooltip_list = []
|
64
|
+
|
65
|
+
self.containerFrame = CTkFrame(self)
|
66
|
+
self.containerFrame.grid(row=0, column=0, padx=(5, 5), pady=(5, 5), sticky="nsew")
|
67
|
+
self.containerFrame.grid_columnconfigure(0, weight=1, minsize=20)
|
68
|
+
self.containerFrame.grid_columnconfigure(5, weight=1, minsize=20)
|
69
|
+
self.containerFrame.grid_columnconfigure((1, 2, 3, 4), weight=5)
|
70
|
+
|
71
|
+
CTkLabel(self.containerFrame, text="Type:").grid(row=row, column=0, padx=(5, 5), pady=(5, 5), sticky="nsew")
|
72
|
+
CTkLabel(self.containerFrame, text="Name:").grid(row=row, column=1, padx=(5, 5), pady=(5, 5), sticky="nsew")
|
73
|
+
CTkLabel(self.containerFrame, text="Bounds:").grid(row=row, column=2, columnspan=2, padx=(5, 5), pady=(5, 5), sticky="nsew")
|
74
|
+
CTkLabel(self.containerFrame, text="Default:").grid(row=row, column=4, padx=(5, 5), pady=(5, 5), sticky="nsew")
|
75
|
+
CTkLabel(self.containerFrame, text="Strategy:").grid(row=row, column=5, padx=(5, 5), pady=(5, 5), sticky="nsew")
|
76
|
+
row += 1
|
77
|
+
|
78
|
+
bounds = self.option_manager.get_steps()[self.step_index]["param"]
|
79
|
+
|
80
|
+
for bound in bounds:
|
81
|
+
tt1 = None
|
82
|
+
tt2 = None
|
83
|
+
tt3 = None
|
84
|
+
|
85
|
+
tt = CTkOptionMenu(self.containerFrame, dynamic_resizing=False, values=['float', 'int', 'list', 'string', 'custom'], variable=bound["type"], command=self.refresh)
|
86
|
+
#command = lambda _, index=index, option=tt: (self.update_type(index, option))
|
87
|
+
#tt.configure(command=command)
|
88
|
+
#tt.set(bound["type"].get())
|
89
|
+
tt.grid(row=row, column=0, padx=(5, 5), pady=(5, 5), sticky="new")
|
90
|
+
|
91
|
+
cc = None
|
92
|
+
|
93
|
+
bound_type = bound["type"].get()
|
94
|
+
|
95
|
+
if bound_type == "float":
|
96
|
+
cc = CTkOptionMenu(self.containerFrame, dynamic_resizing=False, values=optParams, variable=bound["name"])
|
97
|
+
cc.grid(row=row, column=1, padx=(5, 5), pady=(5, 5), sticky="new")
|
98
|
+
|
99
|
+
command = lambda _, index=index: (self.update_values(index), self.update_tooltips(index))
|
100
|
+
cc.configure(command=command)
|
101
|
+
else:
|
102
|
+
|
103
|
+
cc = CTkEntry(self.containerFrame)
|
104
|
+
cc.configure(textvariable=bound["name"])
|
105
|
+
cc.grid(row=row, column=1, padx=(5, 5), pady=(5, 5), sticky="new")
|
106
|
+
|
107
|
+
|
108
|
+
if self.edit_mode:
|
109
|
+
remove_func = lambda index=index: (self.clear(), self.option_manager.remove_bound(self.step_index, index), self.render())
|
110
|
+
bb = CTkButton(self.containerFrame, text="Remove", command=remove_func)
|
111
|
+
bb.grid(row=row, column=2, padx=(5, 5), pady=(5, 5), sticky="new")
|
112
|
+
CTkToolTip(bb, delay=0.1, alpha=0.95, message="Delete this bound...")
|
113
|
+
else:
|
114
|
+
bounds_min = CTkEntry(self.containerFrame)
|
115
|
+
vcmd = (self.register(self.validate_number), '%P', cc, bounds_min)
|
116
|
+
bounds_min.grid(row=row, column=2, padx=(5, 5), pady=(5, 5), sticky="new")
|
117
|
+
bounds_min.configure(textvariable=bound["bounds"][0], validate='all', validatecommand=vcmd)
|
118
|
+
self.validate_number(bounds_min.get(), cc, bounds_min)
|
119
|
+
|
120
|
+
bounds_max = CTkEntry(self.containerFrame)
|
121
|
+
vcmd = (self.register(self.validate_number), '%P', cc, bounds_max)
|
122
|
+
bounds_max.grid(row=row, column=3, padx=(5, 5), pady=(5, 5), sticky="new")
|
123
|
+
bounds_max.configure(textvariable=bound["bounds"][1], validate='all', validatecommand=vcmd)
|
124
|
+
self.validate_number(bounds_max.get(), cc, bounds_max)
|
125
|
+
tt2 = CTkToolTip(bounds_max, delay=0.1, alpha=0.95, message="...")
|
126
|
+
|
127
|
+
default_value = CTkEntry(self.containerFrame)
|
128
|
+
default_value.grid(row=row, column=4, padx=(5, 5), pady=(5, 5), sticky="new")
|
129
|
+
default_value.configure(textvariable=bound["default_value"])
|
130
|
+
|
131
|
+
|
132
|
+
if (bound_type == "list"):
|
133
|
+
def button_click_event(bound_index):
|
134
|
+
dialog = BoundsEditorWindow(title="Edit List Bound", step_index=self.step_index, bound_index=bound_index, option_manager=self.option_manager)
|
135
|
+
print("Number:", dialog.get_input())
|
136
|
+
|
137
|
+
open_window = lambda event=None, bound_index=index: (button_click_event(bound_index))
|
138
|
+
expand_image = CTkImage(Image.open(os.path.join("./images", "expand.png")), size=(20, 20))
|
139
|
+
button = CTkButton(self.containerFrame, width=30, text=None, image=expand_image, command=open_window)
|
140
|
+
button.grid(row=row, column=6, padx=(5, 5), pady=(5, 5), sticky="new")
|
141
|
+
|
142
|
+
calibration_strat = CTkOptionMenu(self.containerFrame, dynamic_resizing=False, values=['none', 'mean', 'single'], variable=bound["calibration_strategy"])
|
143
|
+
calibration_strat.grid(row=row, column=5, padx=(5, 5), pady=(5, 5), sticky="new")
|
144
|
+
|
145
|
+
tt1 = CTkToolTip(bounds_min, delay=0.1, alpha=0.95, message="...")
|
146
|
+
tt2 = CTkToolTip(bounds_max, delay=0.1, alpha=0.95, message="...")
|
147
|
+
if cc is not None:
|
148
|
+
tt3 = CTkToolTip(cc, delay=0.1, alpha=0.95, message="...")
|
149
|
+
|
150
|
+
self.tooltip_list.append([tt3, tt1, tt2])
|
151
|
+
|
152
|
+
self.update_tooltips(index)
|
153
|
+
|
154
|
+
row += 1
|
155
|
+
index += 1
|
156
|
+
|
157
|
+
add_func = lambda: (self.clear(), self.option_manager.add_bound(self.step_index), self.render())
|
158
|
+
if len(bounds) > 0:
|
159
|
+
if self.edit_mode:
|
160
|
+
CTkButton(self.containerFrame, text="Exit", command=self.toggle_edit_mode).grid(row=row, column=0, padx=(5, 5), pady=(5, 5), sticky="new")
|
161
|
+
else:
|
162
|
+
CTkButton(self.containerFrame, text="Edit", command=self.toggle_edit_mode).grid(row=row, column=0, padx=(5, 5), pady=(5, 5), sticky="new")
|
163
|
+
CTkButton(self.containerFrame, text="Add Parameter", command=add_func).grid(row=row, column=1, padx=(5, 5), pady=(5, 5), sticky="new")
|
164
|
+
else:
|
165
|
+
CTkButton(self.containerFrame, text="Add Parameter", command=add_func).grid(row=row, column=0, columnspan=2, padx=(5, 5), pady=(5, 5), sticky="new")
|
166
|
+
|
167
|
+
def update_type(self, index, option):
|
168
|
+
value = option.get()
|
169
|
+
self.option_manager.get_steps()[self.step_index]["param"][index]["type"].set(value)
|
170
|
+
self.refresh()
|
171
|
+
|
172
|
+
def update_values(self, index):
|
173
|
+
name = self.option_manager.get_steps()[self.step_index]["param"][index]["name"].get()
|
174
|
+
if name in paramMap:
|
175
|
+
obj = paramMap[name]
|
176
|
+
self.option_manager.get_steps()[self.step_index]["param"][index]["bounds"][0].set(obj["softmin"])
|
177
|
+
self.option_manager.get_steps()[self.step_index]["param"][index]["bounds"][1].set(obj["softmax"])
|
178
|
+
|
179
|
+
def update_tooltips(self, index):
|
180
|
+
try:
|
181
|
+
name = self.option_manager.get_steps()[self.step_index]["param"][index]["name"].get()
|
182
|
+
bound_type = self.option_manager.get_steps()[self.step_index]["param"][index]["type"].get()
|
183
|
+
|
184
|
+
tooltips = self.tooltip_list[index]
|
185
|
+
t3 = tooltips[0]
|
186
|
+
t1 = tooltips[1]
|
187
|
+
t2 = tooltips[2]
|
188
|
+
|
189
|
+
if (t1 == None or t2 == None or t3 == None):
|
190
|
+
if (t1 is not None):
|
191
|
+
t1.configure(message="")
|
192
|
+
if (t2 is not None):
|
193
|
+
t2.configure(message="")
|
194
|
+
if (t3 is not None):
|
195
|
+
t3.configure(message="")
|
196
|
+
print("update skipped")
|
197
|
+
return
|
198
|
+
|
199
|
+
if bound_type == "list":
|
200
|
+
t1.configure(message="")
|
201
|
+
t2.configure(message="")
|
202
|
+
t3.configure(message="")
|
203
|
+
|
204
|
+
if name in paramMap:
|
205
|
+
obj = paramMap[name]
|
206
|
+
description = obj["description"]
|
207
|
+
default = str(obj["value"])
|
208
|
+
min = str(obj["min"])
|
209
|
+
max = str(obj["max"])
|
210
|
+
softmin = str(obj["softmin"])
|
211
|
+
softmax = str(obj["softmax"])
|
212
|
+
unit = str(obj["unit"])
|
213
|
+
t1.configure(message=description + "\nMin: " + min + "\nSoft Min: " + softmin + "\nUnit: " + unit)
|
214
|
+
t2.configure(message=description + "\nMax: " + max + "\nSoft Max: " + softmax + "\nUnit: " + unit)
|
215
|
+
t3.configure(message=description + "\nDefault: " + default + "\nUnit: " + unit)
|
216
|
+
except:
|
217
|
+
pass
|
218
|
+
|
219
|
+
def validate_number(self, P, name, entry):
|
220
|
+
|
221
|
+
# Get the root window
|
222
|
+
root = self.winfo_toplevel()
|
223
|
+
|
224
|
+
# Get the entry widget using its internal Tkinter name
|
225
|
+
entry_widget = root.nametowidget(entry)
|
226
|
+
name_widget = root.nametowidget(name)
|
227
|
+
|
228
|
+
if isinstance(name_widget, CTkTextbox):
|
229
|
+
return True
|
230
|
+
|
231
|
+
# Call the get method on the entry widget
|
232
|
+
bound_name = name_widget.get()
|
233
|
+
value = entry_widget.get()
|
234
|
+
|
235
|
+
# Print the value of the entry widget
|
236
|
+
#print(bound_name)
|
237
|
+
|
238
|
+
if P == "" or P == "." or P == "-":
|
239
|
+
entry_widget.configure(border_color="red")
|
240
|
+
return True
|
241
|
+
|
242
|
+
try:
|
243
|
+
float(P)
|
244
|
+
entry_widget.configure(border_color=["#979DA2", "#565B5E"])
|
245
|
+
|
246
|
+
if bound_name in paramMap:
|
247
|
+
obj = paramMap[bound_name]
|
248
|
+
if "min" in obj and float(P) < float(obj["min"]):
|
249
|
+
entry_widget.configure(border_color="red")
|
250
|
+
elif "max" in obj and float(P) > float(obj["max"]):
|
251
|
+
entry_widget.configure(border_color="red")
|
252
|
+
elif "softmin" in obj and float(P) < float(obj["softmin"]):
|
253
|
+
entry_widget.configure(border_color="yellow")
|
254
|
+
elif "softmax" in obj and float(P) > float(obj["softmax"]):
|
255
|
+
entry_widget.configure(border_color="yellow")
|
256
|
+
|
257
|
+
return True
|
258
|
+
except ValueError as e:
|
259
|
+
print(e)
|
260
|
+
return False
|
261
|
+
except Exception as e:
|
262
|
+
print(e)
|
263
|
+
return False
|
@@ -0,0 +1,187 @@
|
|
1
|
+
"""
|
2
|
+
CTkToolTip Widget
|
3
|
+
version: 0.4
|
4
|
+
"""
|
5
|
+
|
6
|
+
import time
|
7
|
+
import sys
|
8
|
+
import customtkinter
|
9
|
+
from tkinter import Toplevel, Frame
|
10
|
+
|
11
|
+
class CTkToolTip(Toplevel):
|
12
|
+
"""
|
13
|
+
Creates a ToolTip (pop-up) widget for customtkinter.
|
14
|
+
"""
|
15
|
+
|
16
|
+
def __init__(
|
17
|
+
self,
|
18
|
+
widget: any = None,
|
19
|
+
message: str = None,
|
20
|
+
delay: float = 0.2,
|
21
|
+
follow: bool = True,
|
22
|
+
x_offset: int = +20,
|
23
|
+
y_offset: int = +10,
|
24
|
+
bg_color: str = None,
|
25
|
+
corner_radius: int = 10,
|
26
|
+
border_width: int = 0,
|
27
|
+
border_color: str = None,
|
28
|
+
alpha: float = 0.8,
|
29
|
+
padding: tuple = (10,2),
|
30
|
+
**message_kwargs):
|
31
|
+
|
32
|
+
super().__init__()
|
33
|
+
|
34
|
+
self.widget = widget
|
35
|
+
|
36
|
+
self.withdraw()
|
37
|
+
# Disable ToolTip's title bar
|
38
|
+
self.overrideredirect(True)
|
39
|
+
|
40
|
+
if sys.platform.startswith("win"):
|
41
|
+
self.transparent_color = self.widget._apply_appearance_mode(customtkinter.ThemeManager.theme["CTkToplevel"]["fg_color"])
|
42
|
+
self.attributes("-transparentcolor", self.transparent_color)
|
43
|
+
self.transient()
|
44
|
+
elif sys.platform.startswith("darwin"):
|
45
|
+
self.transparent_color = 'systemTransparent'
|
46
|
+
self.attributes("-transparent", True)
|
47
|
+
self.transient(self.master)
|
48
|
+
else:
|
49
|
+
self.transparent_color = '#000001'
|
50
|
+
corner_radius = 0
|
51
|
+
self.transient()
|
52
|
+
|
53
|
+
self.resizable(width=True, height=True)
|
54
|
+
self.transient()
|
55
|
+
|
56
|
+
# Make the background transparent
|
57
|
+
self.config(background=self.transparent_color)
|
58
|
+
|
59
|
+
# StringVar instance for msg string
|
60
|
+
self.messageVar = customtkinter.StringVar()
|
61
|
+
self.message = message
|
62
|
+
self.messageVar.set(self.message)
|
63
|
+
|
64
|
+
self.delay = delay
|
65
|
+
self.follow = follow
|
66
|
+
self.x_offset = x_offset
|
67
|
+
self.y_offset = y_offset
|
68
|
+
self.corner_radius = corner_radius
|
69
|
+
self.alpha = alpha
|
70
|
+
self.border_width = border_width
|
71
|
+
self.padding = padding
|
72
|
+
self.bg_color = bg_color
|
73
|
+
self.border_color = border_color
|
74
|
+
self.disable = False
|
75
|
+
|
76
|
+
# visibility status of the ToolTip inside|outside|visible
|
77
|
+
self.status = "outside"
|
78
|
+
self.last_moved = 0
|
79
|
+
self.attributes('-alpha', self.alpha)
|
80
|
+
|
81
|
+
# Add the message widget inside the tooltip
|
82
|
+
self.transparent_frame = Frame(self, bg=self.transparent_color)
|
83
|
+
self.transparent_frame.pack(padx=0, pady=0, fill="both", expand=True)
|
84
|
+
|
85
|
+
self.frame = customtkinter.CTkFrame(self.transparent_frame, bg_color=self.transparent_color, corner_radius=self.corner_radius,
|
86
|
+
border_width=self.border_width, fg_color=self.bg_color, border_color=self.border_color)
|
87
|
+
self.frame.pack(padx=0, pady=0, fill="both", expand=True)
|
88
|
+
|
89
|
+
self.message_label = customtkinter.CTkLabel(self.frame, textvariable=self.messageVar, **message_kwargs)
|
90
|
+
self.message_label.pack(fill="both", padx=self.padding[0]+self.border_width,
|
91
|
+
pady=self.padding[1]+self.border_width, expand=True)
|
92
|
+
|
93
|
+
if self.widget != None:
|
94
|
+
if self.widget.winfo_name()!="tk":
|
95
|
+
if self.frame.cget("fg_color")==self.widget.cget("bg_color"):
|
96
|
+
if not bg_color:
|
97
|
+
self._top_fg_color = self.frame._apply_appearance_mode(customtkinter.ThemeManager.theme["CTkFrame"]["top_fg_color"])
|
98
|
+
self.frame.configure(fg_color=self._top_fg_color)
|
99
|
+
|
100
|
+
# Add bindings to the widget without overriding the existing ones
|
101
|
+
self.widget.bind("<Enter>", self.on_enter, add="+")
|
102
|
+
self.widget.bind("<Leave>", self.on_leave, add="+")
|
103
|
+
self.widget.bind("<Motion>", self.on_enter, add="+")
|
104
|
+
self.widget.bind("<B1-Motion>", self.on_enter, add="+")
|
105
|
+
self.widget.bind("<Destroy>", lambda _: self.hide(), add="+")
|
106
|
+
|
107
|
+
def show(self) -> None:
|
108
|
+
"""
|
109
|
+
Enable the widget.
|
110
|
+
"""
|
111
|
+
self.disable = False
|
112
|
+
|
113
|
+
def on_enter(self, event) -> None:
|
114
|
+
"""
|
115
|
+
Processes motion within the widget including entering and moving.
|
116
|
+
"""
|
117
|
+
|
118
|
+
if self.disable: return
|
119
|
+
self.last_moved = time.time()
|
120
|
+
|
121
|
+
# Set the status as inside for the very first time
|
122
|
+
if self.status == "outside":
|
123
|
+
self.status = "inside"
|
124
|
+
|
125
|
+
# If the follow flag is not set, motion within the widget will make the ToolTip dissapear
|
126
|
+
if not self.follow:
|
127
|
+
self.status = "inside"
|
128
|
+
self.withdraw()
|
129
|
+
|
130
|
+
# Offsets the ToolTip using the coordinates od an event as an origin
|
131
|
+
self.geometry(f"+{event.x_root + self.x_offset}+{event.y_root + self.y_offset}")
|
132
|
+
|
133
|
+
# Time is in integer: milliseconds
|
134
|
+
self.after(int(self.delay * 1000), self._show)
|
135
|
+
|
136
|
+
def on_leave(self, event=None) -> None:
|
137
|
+
"""
|
138
|
+
Hides the ToolTip temporarily.
|
139
|
+
"""
|
140
|
+
|
141
|
+
if self.disable: return
|
142
|
+
self.status = "outside"
|
143
|
+
self.withdraw()
|
144
|
+
|
145
|
+
def _show(self) -> None:
|
146
|
+
"""
|
147
|
+
Displays the ToolTip.
|
148
|
+
"""
|
149
|
+
|
150
|
+
if not self.widget.winfo_exists():
|
151
|
+
self.hide()
|
152
|
+
self.destroy()
|
153
|
+
|
154
|
+
if self.status == "inside" and time.time() - self.last_moved >= self.delay:
|
155
|
+
self.status = "visible"
|
156
|
+
self.deiconify()
|
157
|
+
|
158
|
+
def hide(self) -> None:
|
159
|
+
"""
|
160
|
+
Disable the widget from appearing.
|
161
|
+
"""
|
162
|
+
if not self.winfo_exists():
|
163
|
+
return
|
164
|
+
self.withdraw()
|
165
|
+
self.disable = True
|
166
|
+
|
167
|
+
def is_disabled(self) -> None:
|
168
|
+
"""
|
169
|
+
Return the window state
|
170
|
+
"""
|
171
|
+
return self.disable
|
172
|
+
|
173
|
+
def get(self) -> None:
|
174
|
+
"""
|
175
|
+
Returns the text on the tooltip.
|
176
|
+
"""
|
177
|
+
return self.messageVar.get()
|
178
|
+
|
179
|
+
def configure(self, message: str = None, delay: float = None, bg_color: str = None, **kwargs):
|
180
|
+
"""
|
181
|
+
Set new message or configure the label parameters.
|
182
|
+
"""
|
183
|
+
if delay: self.delay = delay
|
184
|
+
if bg_color: self.frame.configure(fg_color=bg_color)
|
185
|
+
|
186
|
+
self.messageVar.set(message)
|
187
|
+
self.message_label.configure(**kwargs)
|
@@ -0,0 +1,61 @@
|
|
1
|
+
from customtkinter import CTkScrollableFrame
|
2
|
+
from customtkinter import CTkFrame
|
3
|
+
from customtkinter import CTkLabel
|
4
|
+
from customtkinter import CTkButton
|
5
|
+
from customtkinter import CTkEntry
|
6
|
+
import tkinter as tk
|
7
|
+
|
8
|
+
global option_manager
|
9
|
+
|
10
|
+
class CalibrationParametersView(CTkScrollableFrame):
|
11
|
+
def __init__(self, *args,
|
12
|
+
option_manager: None,
|
13
|
+
**kwargs):
|
14
|
+
super().__init__(*args, **kwargs)
|
15
|
+
|
16
|
+
self.option_manager = option_manager
|
17
|
+
self.key_values = option_manager.get_arguments()['calibration_parameters']
|
18
|
+
self.edit_mode = False
|
19
|
+
|
20
|
+
self.render()
|
21
|
+
|
22
|
+
def clear(self):
|
23
|
+
self.containerFrame.destroy()
|
24
|
+
|
25
|
+
def toggle_edit_mode(self):
|
26
|
+
self.clear()
|
27
|
+
self.edit_mode = not self.edit_mode
|
28
|
+
self.render()
|
29
|
+
|
30
|
+
def render(self):
|
31
|
+
row = 0
|
32
|
+
index = 0
|
33
|
+
|
34
|
+
self.containerFrame = CTkFrame(self)
|
35
|
+
self.containerFrame.grid(row=0, column=0, padx=(5, 5), pady=(5, 5), sticky="nsew")
|
36
|
+
self.containerFrame.grid_columnconfigure((0, 1), weight=1)
|
37
|
+
|
38
|
+
CTkLabel(self.containerFrame, text="Name:").grid(row=row, column=0, columnspan=1, padx=5, pady=5, sticky="")
|
39
|
+
CTkLabel(self.containerFrame, text="Value:").grid(row=row, column=1, columnspan=1, padx=5, pady=5, sticky="")
|
40
|
+
row += 1
|
41
|
+
|
42
|
+
for key_value_pair in self.key_values:
|
43
|
+
CTkEntry(self.containerFrame, textvariable=self.key_values[index]["name"]).grid(row=row, column=0, padx=(5, 5), pady=(5, 5), sticky="ew")
|
44
|
+
|
45
|
+
if self.edit_mode:
|
46
|
+
return_func = lambda index=index: (self.clear(), self.option_manager.remove_calibration_parameter(index), self.render())
|
47
|
+
CTkButton(self.containerFrame, text="Remove", command=return_func).grid(row=row, column=1, padx=(5, 5), pady=(5, 5), sticky="ew")
|
48
|
+
else:
|
49
|
+
bb = CTkEntry(self.containerFrame)
|
50
|
+
bb.grid(row=row, column=1, padx=(5, 5), pady=(5, 5), sticky="ew")
|
51
|
+
bb.configure(textvariable=self.key_values[index]["value"])
|
52
|
+
row += 1
|
53
|
+
index += 1
|
54
|
+
|
55
|
+
if self.edit_mode:
|
56
|
+
CTkButton(self.containerFrame, text="Exit", command=self.toggle_edit_mode).grid(row=row, column=0, padx=(5, 5), pady=(5, 5), sticky="ew")
|
57
|
+
else:
|
58
|
+
CTkButton(self.containerFrame, text="Edit", command=self.toggle_edit_mode).grid(row=row, column=0, padx=(5, 5), pady=(5, 5), sticky="ew")
|
59
|
+
|
60
|
+
add_key_func = lambda: (self.clear(), self.option_manager.add_calibration_param("name", "value"), self.render())
|
61
|
+
CTkButton(self.containerFrame, text="Add Parameter", command=add_key_func).grid(row=row, column=1, padx=(5, 5), pady=(5, 5), sticky="ew")
|
@@ -0,0 +1,83 @@
|
|
1
|
+
from customtkinter import CTkScrollableFrame
|
2
|
+
from customtkinter import CTkFrame
|
3
|
+
from customtkinter import CTkLabel
|
4
|
+
from customtkinter import CTkButton
|
5
|
+
from customtkinter import CTkEntry
|
6
|
+
from customtkinter import CTkOptionMenu
|
7
|
+
import tkinter as tk
|
8
|
+
|
9
|
+
# TODO: Add weights to interface for each function
|
10
|
+
|
11
|
+
class FunctionsList(CTkFrame):
|
12
|
+
def __init__(self, *args,
|
13
|
+
option_manager: None,
|
14
|
+
step_index: 0,
|
15
|
+
**kwargs):
|
16
|
+
super().__init__(*args, **kwargs)
|
17
|
+
|
18
|
+
|
19
|
+
self.option_manager = option_manager
|
20
|
+
self.step_index = step_index
|
21
|
+
|
22
|
+
self.edit_mode = False
|
23
|
+
self.render()
|
24
|
+
|
25
|
+
def clear(self):
|
26
|
+
self.containerFrame.destroy()
|
27
|
+
|
28
|
+
def toggle_edit_mode(self):
|
29
|
+
self.clear()
|
30
|
+
self.edit_mode = not self.edit_mode
|
31
|
+
self.render()
|
32
|
+
|
33
|
+
def render(self):
|
34
|
+
|
35
|
+
self.containerFrame = CTkFrame(self)
|
36
|
+
self.containerFrame.grid(row=0, column=0, padx=(5, 5), pady=(5, 5), sticky="nsew")
|
37
|
+
self.containerFrame.grid_columnconfigure((0, 1), weight=1)
|
38
|
+
|
39
|
+
row = 1
|
40
|
+
|
41
|
+
funcs = self.option_manager.get_steps()[self.step_index]["objfunc"]
|
42
|
+
|
43
|
+
index = 0
|
44
|
+
for func in funcs:
|
45
|
+
|
46
|
+
CTkLabel(self.containerFrame, text="Name:").grid(row=row, column=0, padx=(5, 5), pady=(5, 5), sticky="nsew")
|
47
|
+
CTkLabel(self.containerFrame, text="Objective:").grid(row=row, column=1, padx=(5, 5), pady=(5, 5), sticky="nsew")
|
48
|
+
CTkLabel(self.containerFrame, text="Weight:").grid(row=row, column=2, padx=(5, 5), pady=(5, 5), sticky="nsew")
|
49
|
+
|
50
|
+
row += 1
|
51
|
+
|
52
|
+
CTkEntry(self.containerFrame, textvariable=func["name"]).grid(row=row, column=0, padx=(5, 5), pady=(5, 5), sticky="ew")
|
53
|
+
CTkEntry(self.containerFrame, textvariable=func["of"]).grid(row=row, column=1, padx=(5, 5), pady=(5, 5), sticky="ew")
|
54
|
+
CTkEntry(self.containerFrame, textvariable=func["weight"]).grid(row=row, column=2, padx=(5, 5), pady=(5, 5), sticky="ew")
|
55
|
+
|
56
|
+
row += 1
|
57
|
+
|
58
|
+
CTkLabel(self.containerFrame, text="Data:").grid(row=row, column=0, padx=(5, 5), pady=(5, 5), sticky="nsew")
|
59
|
+
|
60
|
+
row += 1
|
61
|
+
for obj in func["data"]:
|
62
|
+
CTkEntry(self.containerFrame, textvariable=obj).grid(row=row, column=0, columnspan=3, padx=(5, 5), pady=(5, 5), sticky="nsew")
|
63
|
+
row += 1
|
64
|
+
|
65
|
+
if self.edit_mode:
|
66
|
+
remove_func = lambda index=index: (self.clear(), self.option_manager.remove_function(self.step_index, index), self.render())
|
67
|
+
CTkButton(self.containerFrame, text="Remove", command=remove_func).grid(row=row, column=0, columnspan=3, padx=(5, 5), pady=(5, 5), sticky="ew")
|
68
|
+
row += 1
|
69
|
+
pass
|
70
|
+
else:
|
71
|
+
pass
|
72
|
+
index += 1
|
73
|
+
row += 1
|
74
|
+
|
75
|
+
add_function = lambda: (self.clear(), self.option_manager.add_function(self.step_index), self.render())
|
76
|
+
if len(funcs) > 0:
|
77
|
+
if self.edit_mode:
|
78
|
+
CTkButton(self.containerFrame, text="Exit", command=self.toggle_edit_mode).grid(row=row, column=0, padx=(5, 5), pady=(5, 5), sticky="ew")
|
79
|
+
else:
|
80
|
+
CTkButton(self.containerFrame, text="Edit", command=self.toggle_edit_mode).grid(row=row, column=0, padx=(5, 5), pady=(5, 5), sticky="ew")
|
81
|
+
CTkButton(self.containerFrame, text="Add Objective Function", command=add_function).grid(row=row, column=1, columnspan=2, padx=(5, 5), pady=(5, 5), sticky="ew")
|
82
|
+
else:
|
83
|
+
CTkButton(self.containerFrame, text="Add Objective Function", command=add_function).grid(row=row, column=0, columnspan=2, padx=(5, 5), pady=(5, 5), sticky="ew")
|