attempt adding scaling function to the gui
This commit is contained in:
parent
3d1692fbb3
commit
8734b9f22f
4 changed files with 159 additions and 18 deletions
|
@ -10,10 +10,14 @@ from core.gui.themes import FRAME_PAD, PADX, PADY
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from core.gui.app import Application
|
from core.gui.app import Application
|
||||||
|
|
||||||
|
WIDTH = 1000
|
||||||
|
HEIGHT = 800
|
||||||
|
|
||||||
|
|
||||||
class PreferencesDialog(Dialog):
|
class PreferencesDialog(Dialog):
|
||||||
def __init__(self, master: "Application", app: "Application"):
|
def __init__(self, master: "Application", app: "Application"):
|
||||||
super().__init__(master, app, "Preferences", modal=True)
|
super().__init__(master, app, "Preferences", modal=True)
|
||||||
|
self.gui_scale = tk.DoubleVar(value=self.app.canvas.app_scale)
|
||||||
preferences = self.app.guiconfig["preferences"]
|
preferences = self.app.guiconfig["preferences"]
|
||||||
self.editor = tk.StringVar(value=preferences["editor"])
|
self.editor = tk.StringVar(value=preferences["editor"])
|
||||||
self.theme = tk.StringVar(value=preferences["theme"])
|
self.theme = tk.StringVar(value=preferences["theme"])
|
||||||
|
@ -64,6 +68,27 @@ class PreferencesDialog(Dialog):
|
||||||
entry = ttk.Entry(frame, textvariable=self.gui3d)
|
entry = ttk.Entry(frame, textvariable=self.gui3d)
|
||||||
entry.grid(row=3, column=1, sticky="ew")
|
entry.grid(row=3, column=1, sticky="ew")
|
||||||
|
|
||||||
|
label = ttk.Label(frame, text="Scaling")
|
||||||
|
label.grid(row=4, column=0, pady=PADY, padx=PADX, sticky="w")
|
||||||
|
|
||||||
|
scale_frame = ttk.Frame(frame)
|
||||||
|
scale_frame.grid(row=4, column=1, sticky="ew")
|
||||||
|
scale_frame.columnconfigure(0, weight=1)
|
||||||
|
scale = ttk.Scale(
|
||||||
|
scale_frame,
|
||||||
|
from_=0.5,
|
||||||
|
to=5,
|
||||||
|
value=1,
|
||||||
|
orient=tk.HORIZONTAL,
|
||||||
|
variable=self.gui_scale,
|
||||||
|
command=self.scale_adjust,
|
||||||
|
)
|
||||||
|
scale.grid(row=0, column=0, sticky="ew")
|
||||||
|
entry = ttk.Entry(
|
||||||
|
scale_frame, textvariable=self.gui_scale, width=4, state="disabled"
|
||||||
|
)
|
||||||
|
entry.grid(row=0, column=1)
|
||||||
|
|
||||||
def draw_buttons(self):
|
def draw_buttons(self):
|
||||||
frame = ttk.Frame(self.top)
|
frame = ttk.Frame(self.top)
|
||||||
frame.grid(sticky="ew")
|
frame.grid(sticky="ew")
|
||||||
|
@ -89,3 +114,17 @@ class PreferencesDialog(Dialog):
|
||||||
preferences["theme"] = self.theme.get()
|
preferences["theme"] = self.theme.get()
|
||||||
self.app.save_config()
|
self.app.save_config()
|
||||||
self.destroy()
|
self.destroy()
|
||||||
|
|
||||||
|
def scale_adjust(self, scale: str):
|
||||||
|
self.gui_scale.set(round(self.gui_scale.get(), 2))
|
||||||
|
app_scale = self.gui_scale.get()
|
||||||
|
self.app.canvas.app_scale = app_scale
|
||||||
|
screen_width = self.app.master.winfo_screenwidth()
|
||||||
|
screen_height = self.app.master.winfo_screenheight()
|
||||||
|
scaled_width = WIDTH * app_scale
|
||||||
|
scaled_height = HEIGHT * app_scale
|
||||||
|
x = int(screen_width / 2 - scaled_width / 2)
|
||||||
|
y = int(screen_height / 2 - scaled_height / 2)
|
||||||
|
self.app.master.geometry(f"{int(scaled_width)}x{int(scaled_height)}+{x}+{y}")
|
||||||
|
|
||||||
|
self.app.toolbar.scale(app_scale)
|
||||||
|
|
|
@ -53,6 +53,9 @@ class CanvasGraph(tk.Canvas):
|
||||||
self.marker_tool = None
|
self.marker_tool = None
|
||||||
self.to_copy = []
|
self.to_copy = []
|
||||||
|
|
||||||
|
# app's scale, different scale values to support higher resolution display
|
||||||
|
self.app_scale = 1.0
|
||||||
|
|
||||||
# background related
|
# background related
|
||||||
self.wallpaper_id = None
|
self.wallpaper_id = None
|
||||||
self.wallpaper = None
|
self.wallpaper = None
|
||||||
|
|
|
@ -29,7 +29,7 @@ class StatusBar(ttk.Frame):
|
||||||
|
|
||||||
def draw(self):
|
def draw(self):
|
||||||
self.columnconfigure(0, weight=1)
|
self.columnconfigure(0, weight=1)
|
||||||
self.columnconfigure(1, weight=7)
|
self.columnconfigure(1, weight=5)
|
||||||
self.columnconfigure(2, weight=1)
|
self.columnconfigure(2, weight=1)
|
||||||
self.columnconfigure(3, weight=1)
|
self.columnconfigure(3, weight=1)
|
||||||
self.columnconfigure(4, weight=1)
|
self.columnconfigure(4, weight=1)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import logging
|
import logging
|
||||||
import time
|
import time
|
||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
|
from enum import Enum
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from tkinter import messagebox, ttk
|
from tkinter import messagebox, ttk
|
||||||
from tkinter.font import Font
|
from tkinter.font import Font
|
||||||
|
@ -25,6 +26,12 @@ TOOLBAR_SIZE = 32
|
||||||
PICKER_SIZE = 24
|
PICKER_SIZE = 24
|
||||||
|
|
||||||
|
|
||||||
|
class NodeTypeEnum(Enum):
|
||||||
|
NODE = 0
|
||||||
|
NETWORK = 1
|
||||||
|
OTHER = 2
|
||||||
|
|
||||||
|
|
||||||
def icon(image_enum, width=TOOLBAR_SIZE):
|
def icon(image_enum, width=TOOLBAR_SIZE):
|
||||||
return Images.get(image_enum, width)
|
return Images.get(image_enum, width)
|
||||||
|
|
||||||
|
@ -47,6 +54,7 @@ class Toolbar(ttk.Frame):
|
||||||
self.picker_font = Font(size=8)
|
self.picker_font = Font(size=8)
|
||||||
|
|
||||||
# design buttons
|
# design buttons
|
||||||
|
self.play_button = None
|
||||||
self.select_button = None
|
self.select_button = None
|
||||||
self.link_button = None
|
self.link_button = None
|
||||||
self.node_button = None
|
self.node_button = None
|
||||||
|
@ -71,9 +79,21 @@ class Toolbar(ttk.Frame):
|
||||||
# dialog
|
# dialog
|
||||||
self.marker_tool = None
|
self.marker_tool = None
|
||||||
|
|
||||||
|
# these variables help keep track of what images being drawn so that scaling is possible
|
||||||
|
# since ImageTk.PhotoImage does not have resize method
|
||||||
|
self.node_enum = None
|
||||||
|
self.network_enum = None
|
||||||
|
self.annotation_enum = None
|
||||||
|
|
||||||
# draw components
|
# draw components
|
||||||
self.draw()
|
self.draw()
|
||||||
|
|
||||||
|
def get_icon(self, image_enum, width=TOOLBAR_SIZE):
|
||||||
|
if not self.app.canvas:
|
||||||
|
return Images.get(image_enum, width)
|
||||||
|
else:
|
||||||
|
return Images.get(image_enum, int(width * self.app.canvas.app_scale))
|
||||||
|
|
||||||
def draw(self):
|
def draw(self):
|
||||||
self.columnconfigure(0, weight=1)
|
self.columnconfigure(0, weight=1)
|
||||||
self.rowconfigure(0, weight=1)
|
self.rowconfigure(0, weight=1)
|
||||||
|
@ -85,20 +105,26 @@ class Toolbar(ttk.Frame):
|
||||||
self.design_frame = ttk.Frame(self)
|
self.design_frame = ttk.Frame(self)
|
||||||
self.design_frame.grid(row=0, column=0, sticky="nsew")
|
self.design_frame.grid(row=0, column=0, sticky="nsew")
|
||||||
self.design_frame.columnconfigure(0, weight=1)
|
self.design_frame.columnconfigure(0, weight=1)
|
||||||
self.create_button(
|
self.play_button = self.create_button(
|
||||||
self.design_frame,
|
self.design_frame,
|
||||||
icon(ImageEnum.START),
|
# icon(ImageEnum.START),
|
||||||
|
self.get_icon(ImageEnum.START),
|
||||||
self.click_start,
|
self.click_start,
|
||||||
"start the session",
|
"start the session",
|
||||||
)
|
)
|
||||||
self.select_button = self.create_button(
|
self.select_button = self.create_button(
|
||||||
self.design_frame,
|
self.design_frame,
|
||||||
icon(ImageEnum.SELECT),
|
# icon(ImageEnum.SELECT),
|
||||||
|
self.get_icon(ImageEnum.SELECT),
|
||||||
self.click_selection,
|
self.click_selection,
|
||||||
"selection tool",
|
"selection tool",
|
||||||
)
|
)
|
||||||
self.link_button = self.create_button(
|
self.link_button = self.create_button(
|
||||||
self.design_frame, icon(ImageEnum.LINK), self.click_link, "link tool"
|
self.design_frame,
|
||||||
|
# icon(ImageEnum.LINK),
|
||||||
|
self.get_icon(ImageEnum.LINK),
|
||||||
|
self.click_link,
|
||||||
|
"link tool",
|
||||||
)
|
)
|
||||||
self.create_node_button()
|
self.create_node_button()
|
||||||
self.create_network_button()
|
self.create_network_button()
|
||||||
|
@ -130,18 +156,24 @@ class Toolbar(ttk.Frame):
|
||||||
|
|
||||||
self.stop_button = self.create_button(
|
self.stop_button = self.create_button(
|
||||||
self.runtime_frame,
|
self.runtime_frame,
|
||||||
icon(ImageEnum.STOP),
|
# icon(ImageEnum.STOP),
|
||||||
|
self.get_icon(ImageEnum.STOP),
|
||||||
self.click_stop,
|
self.click_stop,
|
||||||
"stop the session",
|
"stop the session",
|
||||||
)
|
)
|
||||||
self.runtime_select_button = self.create_button(
|
self.runtime_select_button = self.create_button(
|
||||||
self.runtime_frame,
|
self.runtime_frame,
|
||||||
icon(ImageEnum.SELECT),
|
# icon(ImageEnum.SELECT),
|
||||||
|
self.get_icon(ImageEnum.SELECT),
|
||||||
self.click_runtime_selection,
|
self.click_runtime_selection,
|
||||||
"selection tool",
|
"selection tool",
|
||||||
)
|
)
|
||||||
self.plot_button = self.create_button(
|
self.plot_button = self.create_button(
|
||||||
self.runtime_frame, icon(ImageEnum.PLOT), self.click_plot_button, "plot"
|
self.runtime_frame,
|
||||||
|
# icon(ImageEnum.PLOT),
|
||||||
|
self.get_icon(ImageEnum.PLOT),
|
||||||
|
self.click_plot_button,
|
||||||
|
"plot",
|
||||||
)
|
)
|
||||||
self.runtime_marker_button = self.create_button(
|
self.runtime_marker_button = self.create_button(
|
||||||
self.runtime_frame,
|
self.runtime_frame,
|
||||||
|
@ -165,22 +197,40 @@ class Toolbar(ttk.Frame):
|
||||||
# draw default nodes
|
# draw default nodes
|
||||||
for node_draw in NodeUtils.NODES:
|
for node_draw in NodeUtils.NODES:
|
||||||
toolbar_image = icon(node_draw.image_enum)
|
toolbar_image = icon(node_draw.image_enum)
|
||||||
image = icon(node_draw.image_enum, PICKER_SIZE)
|
# image = icon(node_draw.image_enum, PICKER_SIZE)
|
||||||
|
image = self.get_icon(
|
||||||
|
node_draw.image_enum, PICKER_SIZE * self.app.canvas.app_scale
|
||||||
|
)
|
||||||
func = partial(
|
func = partial(
|
||||||
self.update_button, self.node_button, toolbar_image, node_draw
|
self.update_button,
|
||||||
|
self.node_button,
|
||||||
|
toolbar_image,
|
||||||
|
node_draw,
|
||||||
|
NodeTypeEnum.NODE,
|
||||||
|
node_draw.image_enum,
|
||||||
)
|
)
|
||||||
self.create_picker_button(image, func, self.node_picker, node_draw.label)
|
self.create_picker_button(image, func, self.node_picker, node_draw.label)
|
||||||
# draw custom nodes
|
# draw custom nodes
|
||||||
for name in sorted(self.app.core.custom_nodes):
|
for name in sorted(self.app.core.custom_nodes):
|
||||||
node_draw = self.app.core.custom_nodes[name]
|
node_draw = self.app.core.custom_nodes[name]
|
||||||
toolbar_image = Images.get_custom(node_draw.image_file, TOOLBAR_SIZE)
|
toolbar_image = Images.get_custom(node_draw.image_file, TOOLBAR_SIZE)
|
||||||
image = Images.get_custom(node_draw.image_file, PICKER_SIZE)
|
image = Images.get_custom(
|
||||||
|
node_draw.image_file, int(PICKER_SIZE * self.app.canvas.app_scale)
|
||||||
|
)
|
||||||
func = partial(
|
func = partial(
|
||||||
self.update_button, self.node_button, toolbar_image, node_draw
|
self.update_button,
|
||||||
|
self.node_button,
|
||||||
|
toolbar_image,
|
||||||
|
node_draw,
|
||||||
|
NodeTypeEnum,
|
||||||
|
node_draw.image_file,
|
||||||
)
|
)
|
||||||
self.create_picker_button(image, func, self.node_picker, name)
|
self.create_picker_button(image, func, self.node_picker, name)
|
||||||
# draw edit node
|
# draw edit node
|
||||||
image = icon(ImageEnum.EDITNODE, PICKER_SIZE)
|
# image = icon(ImageEnum.EDITNODE, PICKER_SIZE)
|
||||||
|
image = self.get_icon(
|
||||||
|
ImageEnum.EDITNODE, PICKER_SIZE * self.app.canvas.app_scale
|
||||||
|
)
|
||||||
self.create_picker_button(
|
self.create_picker_button(
|
||||||
image, self.click_edit_node, self.node_picker, "Custom"
|
image, self.click_edit_node, self.node_picker, "Custom"
|
||||||
)
|
)
|
||||||
|
@ -284,13 +334,24 @@ class Toolbar(ttk.Frame):
|
||||||
dialog = CustomNodesDialog(self.app, self.app)
|
dialog = CustomNodesDialog(self.app, self.app)
|
||||||
dialog.show()
|
dialog.show()
|
||||||
|
|
||||||
def update_button(self, button: ttk.Button, image: "ImageTk", node_draw: NodeDraw):
|
def update_button(
|
||||||
|
self,
|
||||||
|
button: ttk.Button,
|
||||||
|
image: "ImageTk",
|
||||||
|
node_draw: NodeDraw,
|
||||||
|
type_enum,
|
||||||
|
image_enum,
|
||||||
|
):
|
||||||
logging.debug("update button(%s): %s", button, node_draw)
|
logging.debug("update button(%s): %s", button, node_draw)
|
||||||
self.hide_pickers()
|
self.hide_pickers()
|
||||||
button.configure(image=image)
|
button.configure(image=image)
|
||||||
button.image = image
|
button.image = image
|
||||||
self.app.canvas.mode = GraphMode.NODE
|
self.app.canvas.mode = GraphMode.NODE
|
||||||
self.app.canvas.node_draw = node_draw
|
self.app.canvas.node_draw = node_draw
|
||||||
|
if type_enum == NodeTypeEnum.NODE:
|
||||||
|
self.node_enum = image_enum
|
||||||
|
elif type_enum == NodeTypeEnum.NETWORK:
|
||||||
|
self.network_enum = image_enum
|
||||||
|
|
||||||
def hide_pickers(self):
|
def hide_pickers(self):
|
||||||
logging.debug("hiding pickers")
|
logging.debug("hiding pickers")
|
||||||
|
@ -308,13 +369,14 @@ class Toolbar(ttk.Frame):
|
||||||
"""
|
"""
|
||||||
Create network layer button
|
Create network layer button
|
||||||
"""
|
"""
|
||||||
image = icon(ImageEnum.ROUTER)
|
image = icon(ImageEnum.ROUTER, TOOLBAR_SIZE)
|
||||||
self.node_button = ttk.Button(
|
self.node_button = ttk.Button(
|
||||||
self.design_frame, image=image, command=self.draw_node_picker
|
self.design_frame, image=image, command=self.draw_node_picker
|
||||||
)
|
)
|
||||||
self.node_button.image = image
|
self.node_button.image = image
|
||||||
self.node_button.grid(sticky="ew")
|
self.node_button.grid(sticky="ew")
|
||||||
Tooltip(self.node_button, "Network-layer virtual nodes")
|
Tooltip(self.node_button, "Network-layer virtual nodes")
|
||||||
|
self.node_enum = ImageEnum.ROUTER
|
||||||
|
|
||||||
def draw_network_picker(self):
|
def draw_network_picker(self):
|
||||||
"""
|
"""
|
||||||
|
@ -328,7 +390,12 @@ class Toolbar(ttk.Frame):
|
||||||
self.create_picker_button(
|
self.create_picker_button(
|
||||||
image,
|
image,
|
||||||
partial(
|
partial(
|
||||||
self.update_button, self.network_button, toolbar_image, node_draw
|
self.update_button,
|
||||||
|
self.network_button,
|
||||||
|
toolbar_image,
|
||||||
|
node_draw,
|
||||||
|
NodeTypeEnum.NETWORK,
|
||||||
|
node_draw.image_enum,
|
||||||
),
|
),
|
||||||
self.network_picker,
|
self.network_picker,
|
||||||
node_draw.label,
|
node_draw.label,
|
||||||
|
@ -350,6 +417,7 @@ class Toolbar(ttk.Frame):
|
||||||
self.network_button.image = image
|
self.network_button.image = image
|
||||||
self.network_button.grid(sticky="ew")
|
self.network_button.grid(sticky="ew")
|
||||||
Tooltip(self.network_button, "link-layer nodes")
|
Tooltip(self.network_button, "link-layer nodes")
|
||||||
|
self.network_enum = ImageEnum.HUB
|
||||||
|
|
||||||
def draw_annotation_picker(self):
|
def draw_annotation_picker(self):
|
||||||
"""
|
"""
|
||||||
|
@ -368,7 +436,7 @@ class Toolbar(ttk.Frame):
|
||||||
image = icon(image_enum, PICKER_SIZE)
|
image = icon(image_enum, PICKER_SIZE)
|
||||||
self.create_picker_button(
|
self.create_picker_button(
|
||||||
image,
|
image,
|
||||||
partial(self.update_annotation, toolbar_image, shape_type),
|
partial(self.update_annotation, toolbar_image, shape_type, image_enum),
|
||||||
self.annotation_picker,
|
self.annotation_picker,
|
||||||
shape_type.value,
|
shape_type.value,
|
||||||
)
|
)
|
||||||
|
@ -388,6 +456,7 @@ class Toolbar(ttk.Frame):
|
||||||
self.annotation_button.image = image
|
self.annotation_button.image = image
|
||||||
self.annotation_button.grid(sticky="ew")
|
self.annotation_button.grid(sticky="ew")
|
||||||
Tooltip(self.annotation_button, "background annotation tools")
|
Tooltip(self.annotation_button, "background annotation tools")
|
||||||
|
self.annotation_enum = ImageEnum.MARKER
|
||||||
|
|
||||||
def create_observe_button(self):
|
def create_observe_button(self):
|
||||||
menu_button = ttk.Menubutton(
|
menu_button = ttk.Menubutton(
|
||||||
|
@ -434,13 +503,16 @@ class Toolbar(ttk.Frame):
|
||||||
if not response.result:
|
if not response.result:
|
||||||
messagebox.showerror("Stop Error", "Errors stopping session")
|
messagebox.showerror("Stop Error", "Errors stopping session")
|
||||||
|
|
||||||
def update_annotation(self, image: "ImageTk.PhotoImage", shape_type: ShapeType):
|
def update_annotation(
|
||||||
|
self, image: "ImageTk.PhotoImage", shape_type: ShapeType, image_enum
|
||||||
|
):
|
||||||
logging.debug("clicked annotation: ")
|
logging.debug("clicked annotation: ")
|
||||||
self.hide_pickers()
|
self.hide_pickers()
|
||||||
self.annotation_button.configure(image=image)
|
self.annotation_button.configure(image=image)
|
||||||
self.annotation_button.image = image
|
self.annotation_button.image = image
|
||||||
self.app.canvas.mode = GraphMode.ANNOTATION
|
self.app.canvas.mode = GraphMode.ANNOTATION
|
||||||
self.app.canvas.annotation_type = shape_type
|
self.app.canvas.annotation_type = shape_type
|
||||||
|
self.annotation_enum = image_enum
|
||||||
if is_marker(shape_type):
|
if is_marker(shape_type):
|
||||||
if self.marker_tool:
|
if self.marker_tool:
|
||||||
self.marker_tool.destroy()
|
self.marker_tool.destroy()
|
||||||
|
@ -465,3 +537,30 @@ class Toolbar(ttk.Frame):
|
||||||
|
|
||||||
def click_two_node_button(self):
|
def click_two_node_button(self):
|
||||||
logging.debug("Click TWONODE button")
|
logging.debug("Click TWONODE button")
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def scale_button(cls, button, image_enum, scale):
|
||||||
|
image = icon(image_enum, int(TOOLBAR_SIZE * scale))
|
||||||
|
button.config(image=image)
|
||||||
|
button.image = image
|
||||||
|
|
||||||
|
def scale(self, scale):
|
||||||
|
self.scale_button(self.play_button, ImageEnum.START, scale)
|
||||||
|
self.scale_button(self.select_button, ImageEnum.SELECT, scale)
|
||||||
|
self.scale_button(self.link_button, ImageEnum.LINK, scale)
|
||||||
|
self.scale_button(self.node_button, self.node_enum, scale)
|
||||||
|
self.scale_button(self.network_button, self.network_enum, scale)
|
||||||
|
self.scale_button(self.annotation_button, self.annotation_enum, scale)
|
||||||
|
|
||||||
|
self.scale_button(self.runtime_select_button, ImageEnum.SELECT, scale)
|
||||||
|
self.scale_button(self.stop_button, ImageEnum.STOP, scale)
|
||||||
|
self.scale_button(self.plot_button, ImageEnum.PLOT, scale)
|
||||||
|
self.scale_button(self.runtime_marker_button, ImageEnum.MARKER, scale)
|
||||||
|
self.scale_button(self.node_command_button, ImageEnum.TWONODE, scale)
|
||||||
|
self.scale_button(self.run_command_button, ImageEnum.RUN, scale)
|
||||||
|
|
||||||
|
# self.stop_button = None
|
||||||
|
# self.plot_button = None
|
||||||
|
# self.runtime_marker_button = None
|
||||||
|
# self.node_command_button = None
|
||||||
|
# self.run_command_button = None
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue