spacr 0.2.46__py3-none-any.whl → 0.2.53__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.
- spacr/core.py +24 -11
- spacr/gui.py +0 -2
- spacr/gui_core.py +70 -55
- spacr/gui_elements.py +367 -152
- spacr/gui_utils.py +59 -68
- spacr/io.py +2 -3
- spacr/measure.py +196 -145
- spacr/plot.py +2 -42
- spacr/resources/font/open_sans/OFL.txt +93 -0
- spacr/resources/font/open_sans/OpenSans-Italic-VariableFont_wdth,wght.ttf +0 -0
- spacr/resources/font/open_sans/OpenSans-VariableFont_wdth,wght.ttf +0 -0
- spacr/resources/font/open_sans/README.txt +100 -0
- spacr/resources/font/open_sans/static/OpenSans-Bold.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans-BoldItalic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans-ExtraBold.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans-ExtraBoldItalic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans-Italic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans-Light.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans-LightItalic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans-Medium.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans-MediumItalic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans-Regular.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans-SemiBold.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans-SemiBoldItalic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_Condensed-Bold.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_Condensed-BoldItalic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_Condensed-ExtraBold.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_Condensed-ExtraBoldItalic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_Condensed-Italic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_Condensed-Light.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_Condensed-LightItalic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_Condensed-Medium.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_Condensed-MediumItalic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_Condensed-Regular.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_Condensed-SemiBold.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_Condensed-SemiBoldItalic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-Bold.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-BoldItalic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-ExtraBold.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-ExtraBoldItalic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-Italic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-Light.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-LightItalic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-Medium.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-MediumItalic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-Regular.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-SemiBold.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-SemiBoldItalic.ttf +0 -0
- spacr/sequencing.py +107 -13
- spacr/settings.py +27 -84
- spacr/utils.py +9 -9
- {spacr-0.2.46.dist-info → spacr-0.2.53.dist-info}/METADATA +6 -4
- spacr-0.2.53.dist-info/RECORD +100 -0
- spacr-0.2.46.dist-info/RECORD +0 -60
- {spacr-0.2.46.dist-info → spacr-0.2.53.dist-info}/LICENSE +0 -0
- {spacr-0.2.46.dist-info → spacr-0.2.53.dist-info}/WHEEL +0 -0
- {spacr-0.2.46.dist-info → spacr-0.2.53.dist-info}/entry_points.txt +0 -0
- {spacr-0.2.46.dist-info → spacr-0.2.53.dist-info}/top_level.txt +0 -0
spacr/gui_elements.py
CHANGED
@@ -1,7 +1,8 @@
|
|
1
|
-
import os, threading, time, sqlite3, webbrowser
|
1
|
+
import os, threading, time, sqlite3, webbrowser, pyautogui
|
2
2
|
import tkinter as tk
|
3
3
|
from tkinter import ttk
|
4
4
|
import tkinter.font as tkFont
|
5
|
+
from tkinter import font
|
5
6
|
from queue import Queue
|
6
7
|
from tkinter import Label, Frame, Button
|
7
8
|
import numpy as np
|
@@ -16,14 +17,28 @@ from skimage.transform import resize
|
|
16
17
|
from scipy.ndimage import binary_fill_holes, label
|
17
18
|
from tkinter import ttk, scrolledtext
|
18
19
|
|
19
|
-
def
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
20
|
+
def set_element_size():
|
21
|
+
|
22
|
+
screen_width, screen_height = pyautogui.size()
|
23
|
+
screen_area = screen_width * screen_height
|
24
|
+
|
25
|
+
# Calculate sizes based on screen dimensions
|
26
|
+
btn_size = int((screen_area * 0.002) ** 0.5) # Button size as a fraction of screen area
|
27
|
+
bar_size = screen_height // 20 # Bar size based on screen height
|
28
|
+
settings_width = screen_width // 4 # Settings panel width as a fraction of screen width
|
29
|
+
panel_width = screen_width - settings_width # Panel width as a fraction of screen width
|
30
|
+
panel_height = screen_height // 6 # Panel height as a fraction of screen height
|
25
31
|
|
26
|
-
|
32
|
+
size_dict = {
|
33
|
+
'btn_size': btn_size,
|
34
|
+
'bar_size': bar_size,
|
35
|
+
'settings_width': settings_width,
|
36
|
+
'panel_width': panel_width,
|
37
|
+
'panel_height': panel_height
|
38
|
+
}
|
39
|
+
return size_dict
|
40
|
+
|
41
|
+
def set_dark_style(style, parent_frame=None, containers=None, widgets=None, font_family="OpenSans", font_size=12, bg_color='black', fg_color='white', active_color='blue', inactive_color='dark_gray'):
|
27
42
|
|
28
43
|
if active_color == 'teal':
|
29
44
|
active_color = '#008080'
|
@@ -39,6 +54,11 @@ def set_dark_style(style, parent_frame=None, containers=None, widgets=None, font
|
|
39
54
|
padding = '5 5 5 5'
|
40
55
|
font_style = tkFont.Font(family=font_family, size=font_size)
|
41
56
|
|
57
|
+
if font_family == 'OpenSans':
|
58
|
+
font_loader = spacrFont(font_name='OpenSans', font_style='Regular', font_size=12)
|
59
|
+
else:
|
60
|
+
font_loader = None
|
61
|
+
|
42
62
|
style.theme_use('clam')
|
43
63
|
|
44
64
|
style.configure('TEntry', padding=padding)
|
@@ -50,7 +70,10 @@ def set_dark_style(style, parent_frame=None, containers=None, widgets=None, font
|
|
50
70
|
style.configure('TButton', padding=padding)
|
51
71
|
style.configure('TFrame', background=bg_color)
|
52
72
|
style.configure('TPanedwindow', background=bg_color)
|
53
|
-
|
73
|
+
if font_loader:
|
74
|
+
style.configure('TLabel', background=bg_color, foreground=fg_color, font=font_loader.get_font(size=font_size))
|
75
|
+
else:
|
76
|
+
style.configure('TLabel', background=bg_color, foreground=fg_color, font=(font_family, font_size))
|
54
77
|
|
55
78
|
if parent_frame:
|
56
79
|
parent_frame.configure(bg=bg_color)
|
@@ -71,18 +94,193 @@ def set_dark_style(style, parent_frame=None, containers=None, widgets=None, font
|
|
71
94
|
if isinstance(widget, (tk.Label, tk.Button, tk.Frame, ttk.LabelFrame, tk.Canvas)):
|
72
95
|
widget.configure(bg=bg_color)
|
73
96
|
if isinstance(widget, (tk.Label, tk.Button)):
|
74
|
-
|
97
|
+
if font_loader:
|
98
|
+
widget.configure(fg=fg_color, font=font_loader.get_font(size=font_size))
|
99
|
+
else:
|
100
|
+
widget.configure(fg=fg_color, font=(font_family, font_size))
|
75
101
|
if isinstance(widget, scrolledtext.ScrolledText):
|
76
102
|
widget.configure(bg=bg_color, fg=fg_color, insertbackground=fg_color)
|
77
103
|
if isinstance(widget, tk.OptionMenu):
|
78
|
-
|
104
|
+
if font_loader:
|
105
|
+
widget.configure(bg=bg_color, fg=fg_color, font=font_loader.get_font(size=font_size))
|
106
|
+
else:
|
107
|
+
widget.configure(bg=bg_color, fg=fg_color, font=(font_family, font_size))
|
79
108
|
menu = widget['menu']
|
80
|
-
|
109
|
+
if font_loader:
|
110
|
+
menu.configure(bg=bg_color, fg=fg_color, font=font_loader.get_font(size=font_size))
|
111
|
+
else:
|
112
|
+
menu.configure(bg=bg_color, fg=fg_color, font=(font_family, font_size))
|
113
|
+
|
114
|
+
return {'font_loader':font_loader, 'font_family': font_family, 'font_size': font_size, 'bg_color': bg_color, 'fg_color': fg_color, 'active_color': active_color, 'inactive_color': inactive_color}
|
115
|
+
|
116
|
+
class spacrFont:
|
117
|
+
def __init__(self, font_name, font_style, font_size=12):
|
118
|
+
"""
|
119
|
+
Initializes the FontLoader class.
|
120
|
+
|
121
|
+
Parameters:
|
122
|
+
- font_name: str, the name of the font (e.g., 'OpenSans').
|
123
|
+
- font_style: str, the style of the font (e.g., 'Regular', 'Bold').
|
124
|
+
- font_size: int, the size of the font (default: 12).
|
125
|
+
"""
|
126
|
+
self.font_name = font_name
|
127
|
+
self.font_style = font_style
|
128
|
+
self.font_size = font_size
|
129
|
+
|
130
|
+
# Determine the path based on the font name and style
|
131
|
+
self.font_path = self.get_font_path(font_name, font_style)
|
132
|
+
|
133
|
+
# Register the font with Tkinter
|
134
|
+
self.load_font()
|
135
|
+
|
136
|
+
def get_font_path(self, font_name, font_style):
|
137
|
+
"""
|
138
|
+
Returns the font path based on the font name and style.
|
139
|
+
|
140
|
+
Parameters:
|
141
|
+
- font_name: str, the name of the font.
|
142
|
+
- font_style: str, the style of the font.
|
143
|
+
|
144
|
+
Returns:
|
145
|
+
- str, the path to the font file.
|
146
|
+
"""
|
147
|
+
base_dir = os.path.dirname(__file__)
|
148
|
+
|
149
|
+
if font_name == 'OpenSans':
|
150
|
+
if font_style == 'Regular':
|
151
|
+
return os.path.join(base_dir, 'resources/font/open_sans/static/OpenSans-Regular.ttf')
|
152
|
+
elif font_style == 'Bold':
|
153
|
+
return os.path.join(base_dir, 'resources/font/open_sans/static/OpenSans-Bold.ttf')
|
154
|
+
elif font_style == 'Italic':
|
155
|
+
return os.path.join(base_dir, 'resources/font/open_sans/static/OpenSans-Italic.ttf')
|
156
|
+
# Add more styles as needed
|
157
|
+
# Add more fonts as needed
|
158
|
+
|
159
|
+
raise ValueError(f"Font '{font_name}' with style '{font_style}' not found.")
|
160
|
+
|
161
|
+
def load_font(self):
|
162
|
+
"""
|
163
|
+
Loads the font into Tkinter.
|
164
|
+
"""
|
165
|
+
try:
|
166
|
+
font.Font(family=self.font_name, size=self.font_size)
|
167
|
+
except tk.TclError:
|
168
|
+
# Load the font manually if it's not already loaded
|
169
|
+
self.tk_font = font.Font(
|
170
|
+
name=self.font_name,
|
171
|
+
file=self.font_path,
|
172
|
+
size=self.font_size
|
173
|
+
)
|
174
|
+
|
175
|
+
def get_font(self, size=None):
|
176
|
+
"""
|
177
|
+
Returns the font in the specified size.
|
178
|
+
|
179
|
+
Parameters:
|
180
|
+
- size: int, the size of the font (optional).
|
181
|
+
|
182
|
+
Returns:
|
183
|
+
- tkFont.Font object.
|
184
|
+
"""
|
185
|
+
if size is None:
|
186
|
+
size = self.font_size
|
187
|
+
return font.Font(family=self.font_name, size=size)
|
188
|
+
|
189
|
+
class spacrContainer(tk.Frame):
|
190
|
+
def __init__(self, parent, orient=tk.VERTICAL, bg=None, *args, **kwargs):
|
191
|
+
super().__init__(parent, *args, **kwargs)
|
192
|
+
self.orient = orient
|
193
|
+
self.bg = bg if bg else 'lightgrey'
|
194
|
+
self.sash_thickness = 10
|
195
|
+
|
196
|
+
self.panes = []
|
197
|
+
self.sashes = []
|
198
|
+
self.bind("<Configure>", self.on_configure)
|
199
|
+
|
200
|
+
self.grid_rowconfigure(0, weight=1)
|
201
|
+
self.grid_columnconfigure(0, weight=1)
|
202
|
+
|
203
|
+
def add(self, widget, stretch='always'):
|
204
|
+
print(f"Adding widget: {widget} with stretch: {stretch}")
|
205
|
+
pane = tk.Frame(self, bg=self.bg)
|
206
|
+
pane.grid_propagate(False)
|
207
|
+
widget.grid(in_=pane, sticky="nsew") # Use grid for the widget within the pane
|
208
|
+
self.panes.append((pane, widget))
|
81
209
|
|
82
|
-
|
210
|
+
if len(self.panes) > 1:
|
211
|
+
self.create_sash()
|
212
|
+
|
213
|
+
self.reposition_panes()
|
214
|
+
|
215
|
+
def create_sash(self):
|
216
|
+
sash = tk.Frame(self, bg=self.bg, cursor='sb_v_double_arrow' if self.orient == tk.VERTICAL else 'sb_h_double_arrow', height=self.sash_thickness, width=self.sash_thickness)
|
217
|
+
sash.bind("<Enter>", self.on_enter_sash)
|
218
|
+
sash.bind("<Leave>", self.on_leave_sash)
|
219
|
+
sash.bind("<ButtonPress-1>", self.start_resize)
|
220
|
+
self.sashes.append(sash)
|
221
|
+
|
222
|
+
def reposition_panes(self):
|
223
|
+
if not self.panes:
|
224
|
+
return
|
225
|
+
|
226
|
+
total_size = self.winfo_height() if self.orient == tk.VERTICAL else self.winfo_width()
|
227
|
+
pane_size = total_size // len(self.panes)
|
228
|
+
|
229
|
+
print(f"Total size: {total_size}, Pane size: {pane_size}, Number of panes: {len(self.panes)}")
|
230
|
+
|
231
|
+
for i, (pane, widget) in enumerate(self.panes):
|
232
|
+
if self.orient == tk.VERTICAL:
|
233
|
+
pane.grid(row=i * 2, column=0, sticky="nsew", pady=(0, self.sash_thickness if i < len(self.panes) - 1 else 0))
|
234
|
+
else:
|
235
|
+
pane.grid(row=0, column=i * 2, sticky="nsew", padx=(0, self.sash_thickness if i < len(self.panes) - 1 else 0))
|
236
|
+
|
237
|
+
for i, sash in enumerate(self.sashes):
|
238
|
+
if self.orient == tk.VERTICAL:
|
239
|
+
sash.grid(row=(i * 2) + 1, column=0, sticky="ew")
|
240
|
+
else:
|
241
|
+
sash.grid(row=0, column=(i * 2) + 1, sticky="ns")
|
242
|
+
|
243
|
+
def on_configure(self, event):
|
244
|
+
print(f"Configuring container: {self}")
|
245
|
+
self.reposition_panes()
|
246
|
+
|
247
|
+
def on_enter_sash(self, event):
|
248
|
+
event.widget.config(bg='blue')
|
249
|
+
|
250
|
+
def on_leave_sash(self, event):
|
251
|
+
event.widget.config(bg=self.bg)
|
252
|
+
|
253
|
+
def start_resize(self, event):
|
254
|
+
sash = event.widget
|
255
|
+
self.start_pos = event.y_root if self.orient == tk.VERTICAL else event.x_root
|
256
|
+
self.start_size = sash.winfo_y() if self.orient == tk.VERTICAL else sash.winfo_x()
|
257
|
+
sash.bind("<B1-Motion>", self.perform_resize)
|
258
|
+
|
259
|
+
def perform_resize(self, event):
|
260
|
+
sash = event.widget
|
261
|
+
delta = (event.y_root - self.start_pos) if self.orient == tk.VERTICAL else (event.x_root - self.start_pos)
|
262
|
+
new_size = self.start_size + delta
|
263
|
+
|
264
|
+
for i, (pane, widget) in enumerate(self.panes):
|
265
|
+
if self.orient == tk.VERTICAL:
|
266
|
+
new_row = max(0, new_size // self.sash_thickness)
|
267
|
+
if pane.winfo_y() >= new_size:
|
268
|
+
pane.grid_configure(row=new_row)
|
269
|
+
elif pane.winfo_y() < new_size and i > 0:
|
270
|
+
previous_row = max(0, (new_size - pane.winfo_height()) // self.sash_thickness)
|
271
|
+
self.panes[i - 1][0].grid_configure(row=previous_row)
|
272
|
+
else:
|
273
|
+
new_col = max(0, new_size // self.sash_thickness)
|
274
|
+
if pane.winfo_x() >= new_size:
|
275
|
+
pane.grid_configure(column=new_col)
|
276
|
+
elif pane.winfo_x() < new_size and i > 0:
|
277
|
+
previous_col = max(0, (new_size - pane.winfo_width()) // self.sash_thickness)
|
278
|
+
self.panes[i - 1][0].grid_configure(column=previous_col)
|
279
|
+
|
280
|
+
self.reposition_panes()
|
83
281
|
|
84
282
|
class spacrEntry(tk.Frame):
|
85
|
-
def __init__(self, parent, textvariable=None, outline=False, *args, **kwargs):
|
283
|
+
def __init__(self, parent, textvariable=None, outline=False, width=None, *args, **kwargs):
|
86
284
|
super().__init__(parent, *args, **kwargs)
|
87
285
|
|
88
286
|
# Set dark style
|
@@ -93,18 +291,26 @@ class spacrEntry(tk.Frame):
|
|
93
291
|
self.outline = outline
|
94
292
|
self.font_family = style_out['font_family']
|
95
293
|
self.font_size = style_out['font_size']
|
294
|
+
self.font_loader = style_out['font_loader']
|
96
295
|
|
97
296
|
# Set the background color of the frame
|
98
297
|
self.configure(bg=style_out['bg_color'])
|
99
298
|
|
100
299
|
# Create a canvas for the rounded rectangle background
|
101
|
-
|
300
|
+
if width is None:
|
301
|
+
self.canvas_width = 220 # Adjusted for padding
|
302
|
+
else:
|
303
|
+
self.canvas_width = width
|
102
304
|
self.canvas_height = 40 # Adjusted for padding
|
103
305
|
self.canvas = tk.Canvas(self, width=self.canvas_width, height=self.canvas_height, bd=0, highlightthickness=0, relief='ridge', bg=style_out['bg_color'])
|
104
306
|
self.canvas.pack()
|
105
307
|
|
106
|
-
|
107
|
-
self.
|
308
|
+
# Create the entry widget
|
309
|
+
if self.font_loader:
|
310
|
+
self.entry = tk.Entry(self, textvariable=textvariable, bd=0, highlightthickness=0, fg=self.fg_color, font=self.font_loader.get_font(size=self.font_size), bg=self.bg_color)
|
311
|
+
else:
|
312
|
+
self.entry = tk.Entry(self, textvariable=textvariable, bd=0, highlightthickness=0, fg=self.fg_color, font=(self.font_family, self.font_size), bg=self.bg_color)
|
313
|
+
self.entry.place(relx=0.5, rely=0.5, anchor=tk.CENTER, width=self.canvas_width - 30, height=20) # Centered positioning
|
108
314
|
|
109
315
|
# Bind events to change the background color on focus
|
110
316
|
self.entry.bind("<FocusIn>", self.on_focus_in)
|
@@ -115,7 +321,7 @@ class spacrEntry(tk.Frame):
|
|
115
321
|
def draw_rounded_rectangle(self, color):
|
116
322
|
radius = 15 # Increased radius for more rounded corners
|
117
323
|
x0, y0 = 10, 5
|
118
|
-
x1, y1 =
|
324
|
+
x1, y1 = self.canvas_width - 10, self.canvas_height - 5
|
119
325
|
self.canvas.delete("all")
|
120
326
|
self.canvas.create_arc((x0, y0, x0 + radius, y0 + radius), start=90, extent=90, fill=color, outline=color)
|
121
327
|
self.canvas.create_arc((x1 - radius, y0, x1, y0 + radius), start=0, extent=90, fill=color, outline=color)
|
@@ -183,7 +389,7 @@ class spacrCheck(tk.Frame):
|
|
183
389
|
self.variable.set(not self.variable.get())
|
184
390
|
|
185
391
|
class spacrCombo(tk.Frame):
|
186
|
-
def __init__(self, parent, textvariable=None, values=None, *args, **kwargs):
|
392
|
+
def __init__(self, parent, textvariable=None, values=None, width=None, *args, **kwargs):
|
187
393
|
super().__init__(parent, *args, **kwargs)
|
188
394
|
|
189
395
|
# Set dark style
|
@@ -194,11 +400,12 @@ class spacrCombo(tk.Frame):
|
|
194
400
|
self.inactive_color = style_out['inactive_color']
|
195
401
|
self.font_family = style_out['font_family']
|
196
402
|
self.font_size = style_out['font_size']
|
403
|
+
self.font_loader = style_out['font_loader']
|
197
404
|
|
198
405
|
self.values = values or []
|
199
406
|
|
200
407
|
# Create a canvas for the rounded rectangle background
|
201
|
-
self.canvas_width = 220 # Adjusted for padding
|
408
|
+
self.canvas_width = width if width is not None else 220 # Adjusted for padding
|
202
409
|
self.canvas_height = 40 # Adjusted for padding
|
203
410
|
self.canvas = tk.Canvas(self, width=self.canvas_width, height=self.canvas_height, bd=0, highlightthickness=0, relief='ridge', bg=self.bg_color)
|
204
411
|
self.canvas.pack()
|
@@ -207,7 +414,10 @@ class spacrCombo(tk.Frame):
|
|
207
414
|
self.selected_value = self.var.get()
|
208
415
|
|
209
416
|
# Create the label to display the selected value
|
210
|
-
|
417
|
+
if self.font_loader:
|
418
|
+
self.label = tk.Label(self, text=self.selected_value, bg=self.inactive_color, fg=self.fg_color, font=self.font_loader.get_font(size=self.font_size))
|
419
|
+
else:
|
420
|
+
self.label = tk.Label(self, text=self.selected_value, bg=self.inactive_color, fg=self.fg_color, font=(self.font_family, self.font_size))
|
211
421
|
self.label.place(relx=0.5, rely=0.5, anchor=tk.CENTER)
|
212
422
|
|
213
423
|
# Bind events to open the dropdown menu
|
@@ -221,7 +431,7 @@ class spacrCombo(tk.Frame):
|
|
221
431
|
def draw_rounded_rectangle(self, color):
|
222
432
|
radius = 15 # Increased radius for more rounded corners
|
223
433
|
x0, y0 = 10, 5
|
224
|
-
x1, y1 =
|
434
|
+
x1, y1 = self.canvas_width - 10, self.canvas_height - 5
|
225
435
|
self.canvas.delete("all")
|
226
436
|
self.canvas.create_arc((x0, y0, x0 + radius, y0 + radius), start=90, extent=90, fill=color, outline=color)
|
227
437
|
self.canvas.create_arc((x1 - radius, y0, x1, y0 + radius), start=0, extent=90, fill=color, outline=color)
|
@@ -248,7 +458,10 @@ class spacrCombo(tk.Frame):
|
|
248
458
|
|
249
459
|
for index, value in enumerate(self.values):
|
250
460
|
display_text = value if value is not None else 'None'
|
251
|
-
|
461
|
+
if self.font_loader:
|
462
|
+
item = tk.Label(self.dropdown_menu, text=display_text, bg=self.inactive_color, fg=self.fg_color, font=self.font_loader.get_font(size=self.font_size), anchor='w')
|
463
|
+
else:
|
464
|
+
item = tk.Label(self.dropdown_menu, text=display_text, bg=self.inactive_color, fg=self.fg_color, font=(self.font_family, self.font_size), anchor='w')
|
252
465
|
item.pack(fill='both')
|
253
466
|
item.bind("<Button-1>", lambda e, v=value: self.on_select(v))
|
254
467
|
item.bind("<Enter>", lambda e, w=item: w.config(bg=self.active_color))
|
@@ -274,124 +487,101 @@ class spacrCombo(tk.Frame):
|
|
274
487
|
self.label.config(text=display_text)
|
275
488
|
self.selected_value = value
|
276
489
|
|
277
|
-
class spacrDropdownMenu(tk.
|
278
|
-
def __init__(self, parent, variable, options, command=None, **kwargs):
|
279
|
-
self.variable = variable
|
280
|
-
self.variable.set("Settings Category")
|
281
|
-
super().__init__(parent, self.variable, *options, command=command, **kwargs)
|
282
|
-
self.update_styles()
|
283
|
-
|
284
|
-
# Hide the original button
|
285
|
-
self.configure(highlightthickness=0, relief='flat', bg='#2B2B2B', fg='#2B2B2B')
|
286
|
-
|
287
|
-
# Create custom button
|
288
|
-
self.create_custom_button()
|
289
|
-
|
290
|
-
def create_custom_button(self):
|
291
|
-
self.canvas_width = self.winfo_reqwidth() + 20 # Adjust width based on required size
|
292
|
-
self.canvas_height = 40 # Adjust the height as needed
|
293
|
-
self.canvas = tk.Canvas(self, width=self.canvas_width, height=self.canvas_height, bd=0, highlightthickness=0, relief='ridge', bg='#2B2B2B')
|
294
|
-
self.canvas.pack()
|
295
|
-
self.label = tk.Label(self.canvas, text="Settings Category", bg='#2B2B2B', fg='#ffffff', font=('Arial', 12))
|
296
|
-
self.label.place(relx=0.5, rely=0.5, anchor=tk.CENTER)
|
297
|
-
self.draw_rounded_rectangle('#2B2B2B')
|
298
|
-
|
299
|
-
# Bind the click event to open the dropdown menu
|
300
|
-
self.canvas.bind("<Button-1>", self.on_click)
|
301
|
-
self.label.bind("<Button-1>", self.on_click)
|
302
|
-
|
303
|
-
def draw_rounded_rectangle(self, color):
|
304
|
-
radius = 15
|
305
|
-
x0, y0 = 10, 5
|
306
|
-
x1, y1 = self.canvas_width - 10, self.canvas_height - 5 # Adjust based on canvas size
|
307
|
-
|
308
|
-
self.canvas.delete("all")
|
309
|
-
|
310
|
-
# Create the rounded rectangle
|
311
|
-
self.canvas.create_arc(x0, y0, x0 + 2 * radius, y0 + 2 * radius, start=90, extent=90, fill=color, outline=color)
|
312
|
-
self.canvas.create_arc(x1 - 2 * radius, y0, x1, y0 + 2 * radius, start=0, extent=90, fill=color, outline=color)
|
313
|
-
self.canvas.create_arc(x0, y1 - 2 * radius, x0 + 2 * radius, y1, start=180, extent=90, fill=color, outline=color)
|
314
|
-
self.canvas.create_arc(x1 - 2 * radius, y1 - 2 * radius, x1, y1, start=270, extent=90, fill=color, outline=color)
|
490
|
+
class spacrDropdownMenu(tk.Frame):
|
315
491
|
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
self.
|
492
|
+
def __init__(self, parent, variable, options, command=None, font=None, size=50, **kwargs):
|
493
|
+
super().__init__(parent, **kwargs)
|
494
|
+
self.variable = variable
|
495
|
+
self.options = options
|
496
|
+
self.command = command
|
497
|
+
self.text = "Settings"
|
498
|
+
self.size = size
|
320
499
|
|
321
|
-
|
322
|
-
|
500
|
+
# Apply dark style and get color settings
|
501
|
+
style_out = set_dark_style(ttk.Style())
|
502
|
+
self.font_size = style_out['font_size']
|
503
|
+
self.font_loader = style_out['font_loader']
|
323
504
|
|
324
|
-
|
325
|
-
|
326
|
-
self.
|
505
|
+
# Button size configuration
|
506
|
+
self.button_width = int(size * 3)
|
507
|
+
self.canvas_width = self.button_width + 4
|
508
|
+
self.canvas_height = self.size + 4
|
327
509
|
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
self.menu = self['menu']
|
332
|
-
style_out = set_dark_style(style, widgets=[self.menu])
|
510
|
+
# Create the canvas and rounded button
|
511
|
+
self.canvas = tk.Canvas(self, width=self.canvas_width, height=self.canvas_height, highlightthickness=0, bg=style_out['bg_color'])
|
512
|
+
self.canvas.grid(row=0, column=0)
|
333
513
|
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
else:
|
340
|
-
self.menu.entryconfig(idx, background=style_out['bg_color'], foreground=style_out['fg_color'])
|
514
|
+
# Apply dark style and get color settings
|
515
|
+
color_settings = set_dark_style(ttk.Style(), containers=[self], widgets=[self.canvas])
|
516
|
+
self.inactive_color = color_settings['inactive_color']
|
517
|
+
self.active_color = color_settings['active_color']
|
518
|
+
self.fg_color = color_settings['fg_color']
|
341
519
|
|
520
|
+
# Create the button with rounded edges
|
521
|
+
self.button_bg = self.create_rounded_rectangle(2, 2, self.button_width + 2, self.size + 2, radius=20, fill=self.inactive_color, outline=self.inactive_color)
|
342
522
|
|
523
|
+
# Create and place the label on the button
|
524
|
+
if self.font_loader:
|
525
|
+
self.font_style = self.font_loader.get_font(size=self.font_size)
|
526
|
+
else:
|
527
|
+
self.font_style = font if font else ("Arial", 12)
|
343
528
|
|
344
|
-
|
345
|
-
def __init__(self, parent, variable, options, command=None, **kwargs):
|
346
|
-
self.variable = variable
|
347
|
-
self.variable.set("Settings Category")
|
348
|
-
super().__init__(parent, self.variable, *options, command=command, **kwargs)
|
349
|
-
self.update_styles()
|
529
|
+
self.button_text = self.canvas.create_text(self.button_width // 2, self.size // 2 + 2, text=self.text, fill=self.fg_color, font=self.font_style, anchor="center")
|
350
530
|
|
351
|
-
#
|
352
|
-
self.
|
531
|
+
# Bind events for button behavior
|
532
|
+
self.bind("<Enter>", self.on_enter)
|
533
|
+
self.bind("<Leave>", self.on_leave)
|
534
|
+
self.bind("<Button-1>", self.on_click)
|
535
|
+
self.canvas.bind("<Enter>", self.on_enter)
|
536
|
+
self.canvas.bind("<Leave>", self.on_leave)
|
537
|
+
self.canvas.bind("<Button-1>", self.on_click)
|
353
538
|
|
354
|
-
# Create
|
355
|
-
self.
|
539
|
+
# Create a popup menu
|
540
|
+
self.menu = tk.Menu(self, tearoff=0)
|
541
|
+
for option in self.options:
|
542
|
+
self.menu.add_command(label=option, command=lambda opt=option: self.on_select(opt))
|
356
543
|
|
357
|
-
def
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
544
|
+
def create_rounded_rectangle(self, x1, y1, x2, y2, radius=20, **kwargs):
|
545
|
+
points = [
|
546
|
+
x1 + radius, y1,
|
547
|
+
x2 - radius, y1,
|
548
|
+
x2 - radius, y1,
|
549
|
+
x2, y1,
|
550
|
+
x2, y1 + radius,
|
551
|
+
x2, y2 - radius,
|
552
|
+
x2, y2 - radius,
|
553
|
+
x2, y2,
|
554
|
+
x2 - radius, y2,
|
555
|
+
x1 + radius, y2,
|
556
|
+
x1 + radius, y2,
|
557
|
+
x1, y2,
|
558
|
+
x1, y2 - radius,
|
559
|
+
x1, y2 - radius,
|
560
|
+
x1, y1 + radius,
|
561
|
+
x1, y1 + radius,
|
562
|
+
x1, y1
|
563
|
+
]
|
564
|
+
return self.canvas.create_polygon(points, **kwargs, smooth=True)
|
365
565
|
|
366
|
-
|
367
|
-
self.canvas.
|
368
|
-
self.label.bind("<Button-1>", self.on_click)
|
566
|
+
def on_enter(self, event=None):
|
567
|
+
self.canvas.itemconfig(self.button_bg, fill=self.active_color)
|
369
568
|
|
370
|
-
def
|
371
|
-
|
372
|
-
x0, y0 = 10, 5
|
373
|
-
x1, y1 = self.canvas_width - 10, self.canvas_height - 5 # Adjust based on canvas size
|
374
|
-
self.canvas.delete("all")
|
375
|
-
self.canvas.create_arc((x0, y0, x0 + radius, y0 + radius), start=90, extent=90, fill=color, outline=color)
|
376
|
-
self.canvas.create_arc((x1 - radius, y0, x1, y0 + radius), start=0, extent=90, fill=color, outline=color)
|
377
|
-
self.canvas.create_arc((x0, y1 - radius, x0 + radius, y1), start=180, extent=90, fill=color, outline=color)
|
378
|
-
self.canvas.create_arc((x1 - radius, y1 - radius, x1, y1), start=270, extent=90, fill=color, outline=color)
|
379
|
-
self.canvas.create_rectangle((x0 + radius / 2, y0, x1 - radius / 2, y1), fill=color, outline=color)
|
380
|
-
self.canvas.create_rectangle((x0, y0 + radius / 2, x1, y1 - radius / 2), fill=color, outline=color)
|
381
|
-
self.label.config(bg=color) # Update label background to match rectangle color
|
569
|
+
def on_leave(self, event=None):
|
570
|
+
self.canvas.itemconfig(self.button_bg, fill=self.inactive_color)
|
382
571
|
|
383
|
-
def on_click(self, event):
|
572
|
+
def on_click(self, event=None):
|
384
573
|
self.post_menu()
|
385
574
|
|
386
575
|
def post_menu(self):
|
387
576
|
x, y, width, height = self.winfo_rootx(), self.winfo_rooty(), self.winfo_width(), self.winfo_height()
|
388
577
|
self.menu.post(x, y + height)
|
389
578
|
|
579
|
+
def on_select(self, option):
|
580
|
+
if self.command:
|
581
|
+
self.command(option)
|
582
|
+
|
390
583
|
def update_styles(self, active_categories=None):
|
391
|
-
|
392
|
-
style_out = set_dark_style(style, widgets=[self])
|
393
|
-
self.menu = self['menu']
|
394
|
-
style_out = set_dark_style(style, widgets=[self.menu])
|
584
|
+
style_out = set_dark_style(ttk.Style(), widgets=[self.menu])
|
395
585
|
|
396
586
|
if active_categories is not None:
|
397
587
|
for idx in range(self.menu.index("end") + 1):
|
@@ -401,6 +591,7 @@ class spacrDropdownMenu_v1(tk.OptionMenu):
|
|
401
591
|
else:
|
402
592
|
self.menu.entryconfig(idx, background=style_out['bg_color'], foreground=style_out['fg_color'])
|
403
593
|
|
594
|
+
|
404
595
|
class spacrCheckbutton(ttk.Checkbutton):
|
405
596
|
def __init__(self, parent, text="", variable=None, command=None, *args, **kwargs):
|
406
597
|
super().__init__(parent, *args, **kwargs)
|
@@ -587,12 +778,16 @@ class spacrLabel(tk.Frame):
|
|
587
778
|
label_height = height
|
588
779
|
label_width = label_height * 10
|
589
780
|
|
590
|
-
style_out = set_dark_style(ttk.Style())
|
781
|
+
self.style_out = set_dark_style(ttk.Style())
|
782
|
+
self.font_style = self.style_out['font_family']
|
783
|
+
self.font_size = self.style_out['font_size']
|
784
|
+
self.font_family = self.style_out['font_family']
|
785
|
+
self.font_loader = self.style_out['font_loader']
|
591
786
|
|
592
|
-
self.canvas = tk.Canvas(self, width=label_width, height=label_height, highlightthickness=0, bg=style_out['bg_color'])
|
787
|
+
self.canvas = tk.Canvas(self, width=label_width, height=label_height, highlightthickness=0, bg=self.style_out['bg_color'])
|
593
788
|
self.canvas.grid(row=0, column=0, sticky="ew")
|
594
|
-
|
595
|
-
|
789
|
+
if self.style_out['font_family'] != 'OpenSans':
|
790
|
+
self.font_style = font if font else tkFont.Font(family=self.style_out['font_family'], size=self.style_out['font_size'], weight=tkFont.NORMAL)
|
596
791
|
self.style = style
|
597
792
|
|
598
793
|
if self.align == "center":
|
@@ -604,13 +799,21 @@ class spacrLabel(tk.Frame):
|
|
604
799
|
|
605
800
|
if self.style:
|
606
801
|
ttk_style = ttk.Style()
|
607
|
-
|
802
|
+
if self.font_loader:
|
803
|
+
ttk_style.configure(self.style, font=self.font_loader.get_font(size=self.font_size), background=self.style_out['bg_color'], foreground=self.style_out['fg_color'])
|
804
|
+
else:
|
805
|
+
ttk_style.configure(self.style, font=self.font_style, background=self.style_out['bg_color'], foreground=self.style_out['fg_color'])
|
608
806
|
self.label_text = ttk.Label(self.canvas, text=self.text, style=self.style, anchor=text_anchor)
|
609
807
|
self.label_text.pack(fill=tk.BOTH, expand=True)
|
610
808
|
else:
|
611
|
-
|
612
|
-
|
613
|
-
|
809
|
+
if self.font_loader:
|
810
|
+
self.label_text = self.canvas.create_text(label_width // 2 if self.align == "center" else label_width - 5,
|
811
|
+
label_height // 2, text=self.text, fill=self.style_out['fg_color'],
|
812
|
+
font=self.font_loader.get_font(size=self.font_size), anchor=anchor_value, justify=tk.RIGHT)
|
813
|
+
else:
|
814
|
+
self.label_text = self.canvas.create_text(label_width // 2 if self.align == "center" else label_width - 5,
|
815
|
+
label_height // 2, text=self.text, fill=self.style_out['fg_color'],
|
816
|
+
font=self.font_style, anchor=anchor_value, justify=tk.RIGHT)
|
614
817
|
|
615
818
|
_ = set_dark_style(ttk.Style(), containers=[self], widgets=[self.canvas])
|
616
819
|
|
@@ -633,6 +836,8 @@ class spacrButton(tk.Frame):
|
|
633
836
|
self.animation = animation # Add animation attribute
|
634
837
|
|
635
838
|
style_out = set_dark_style(ttk.Style())
|
839
|
+
self.font_size = style_out['font_size']
|
840
|
+
self.font_loader = style_out['font_loader']
|
636
841
|
|
637
842
|
if self.show_text:
|
638
843
|
self.button_width = int(size * 3)
|
@@ -654,7 +859,10 @@ class spacrButton(tk.Frame):
|
|
654
859
|
self.button_bg = self.create_rounded_rectangle(2, 2, self.button_width + 2, self.size + 2, radius=20, fill=self.inactive_color, outline=self.inactive_color)
|
655
860
|
|
656
861
|
self.load_icon()
|
657
|
-
self.
|
862
|
+
if self.font_loader:
|
863
|
+
self.font_style = self.font_loader.get_font(size=self.font_size)
|
864
|
+
else:
|
865
|
+
self.font_style = font if font else ("Arial", 12)
|
658
866
|
|
659
867
|
if self.show_text:
|
660
868
|
self.button_text = self.canvas.create_text(self.size + 10, self.size // 2 + 2, text=self.text, fill=color_settings['fg_color'], font=self.font_style, anchor="w") # Align text to the left of the specified point
|
@@ -1752,6 +1960,14 @@ class AnnotateApp:
|
|
1752
1960
|
self.threshold = threshold
|
1753
1961
|
|
1754
1962
|
style_out = set_dark_style(ttk.Style())
|
1963
|
+
self.font_loader = style_out['font_loader']
|
1964
|
+
self.font_size = style_out['font_size']
|
1965
|
+
|
1966
|
+
if self.font_loader:
|
1967
|
+
self.font_style = self.font_loader.get_font(size=self.font_size)
|
1968
|
+
else:
|
1969
|
+
self.font_style = ("Arial", 12)
|
1970
|
+
|
1755
1971
|
self.root.configure(bg=style_out['inactive_color'])
|
1756
1972
|
|
1757
1973
|
self.filtered_paths_annotations = []
|
@@ -1765,7 +1981,7 @@ class AnnotateApp:
|
|
1765
1981
|
self.root.update_idletasks()
|
1766
1982
|
|
1767
1983
|
# Create the status label
|
1768
|
-
self.status_label = Label(root, text="", font=
|
1984
|
+
self.status_label = Label(root, text="", font=self.font_style, bg=self.root.cget('bg'))
|
1769
1985
|
self.status_label.grid(row=2, column=0, padx=10, pady=10, sticky="w")
|
1770
1986
|
|
1771
1987
|
# Place the buttons at the bottom right
|
@@ -2095,25 +2311,22 @@ class AnnotateApp:
|
|
2095
2311
|
def create_menu_bar(root):
|
2096
2312
|
from .gui import initiate_root
|
2097
2313
|
gui_apps = {
|
2098
|
-
"Mask":
|
2099
|
-
"Measure":
|
2100
|
-
"Annotate":
|
2101
|
-
"Make Masks":
|
2102
|
-
"Classify":
|
2103
|
-
"Sequencing":
|
2104
|
-
"Umap":
|
2105
|
-
"Train Cellpose":
|
2106
|
-
"ML Analyze":
|
2107
|
-
"Cellpose Masks":
|
2108
|
-
"Cellpose All":
|
2109
|
-
"Map Barcodes":
|
2110
|
-
"Regression":
|
2111
|
-
"Recruitment":
|
2314
|
+
"Mask": lambda: initiate_root(root, settings_type='mask'),
|
2315
|
+
"Measure": lambda: initiate_root(root, settings_type='measure'),
|
2316
|
+
"Annotate": lambda: initiate_root(root, settings_type='annotate'),
|
2317
|
+
"Make Masks": lambda: initiate_root(root, settings_type='make_masks'),
|
2318
|
+
"Classify": lambda: initiate_root(root, settings_type='classify'),
|
2319
|
+
"Sequencing": lambda: initiate_root(root, settings_type='sequencing'),
|
2320
|
+
"Umap": lambda: initiate_root(root, settings_type='umap'),
|
2321
|
+
"Train Cellpose": lambda: initiate_root(root, settings_type='train_cellpose'),
|
2322
|
+
"ML Analyze": lambda: initiate_root(root, settings_type='ml_analyze'),
|
2323
|
+
"Cellpose Masks": lambda: initiate_root(root, settings_type='cellpose_masks'),
|
2324
|
+
"Cellpose All": lambda: initiate_root(root, settings_type='cellpose_all'),
|
2325
|
+
"Map Barcodes": lambda: initiate_root(root, settings_type='map_barcodes'),
|
2326
|
+
"Regression": lambda: initiate_root(root, settings_type='regression'),
|
2327
|
+
"Recruitment": lambda: initiate_root(root, settings_type='recruitment')
|
2112
2328
|
}
|
2113
2329
|
|
2114
|
-
def load_app_wrapper(app_name, app_func):
|
2115
|
-
root.load_app(app_name, app_func)
|
2116
|
-
|
2117
2330
|
# Create the menu bar
|
2118
2331
|
menu_bar = tk.Menu(root, bg="#008080", fg="white")
|
2119
2332
|
|
@@ -2122,14 +2335,16 @@ def create_menu_bar(root):
|
|
2122
2335
|
menu_bar.add_cascade(label="SpaCr Applications", menu=app_menu)
|
2123
2336
|
|
2124
2337
|
# Add options to the "SpaCr Applications" menu
|
2125
|
-
for app_name,
|
2126
|
-
|
2127
|
-
|
2338
|
+
for app_name, app_func in gui_apps.items():
|
2339
|
+
app_menu.add_command(
|
2340
|
+
label=app_name,
|
2341
|
+
command=app_func
|
2342
|
+
)
|
2128
2343
|
|
2129
2344
|
# Add a separator and an exit option
|
2130
2345
|
app_menu.add_separator()
|
2131
|
-
app_menu.add_command(label="Help", command=lambda: webbrowser.open("https://readthedocs.
|
2346
|
+
app_menu.add_command(label="Help", command=lambda: webbrowser.open("https://spacr.readthedocs.io/en/latest/?badge=latest"))
|
2132
2347
|
app_menu.add_command(label="Exit", command=root.quit)
|
2133
2348
|
|
2134
2349
|
# Configure the menu for the root window
|
2135
|
-
root.config(menu=menu_bar)
|
2350
|
+
root.config(menu=menu_bar)
|