diff --git a/coretk/coretk/configutils.py b/coretk/coretk/configutils.py index 7c87f9dd..bb3e793e 100644 --- a/coretk/coretk/configutils.py +++ b/coretk/coretk/configutils.py @@ -78,9 +78,8 @@ def parse_config(options, values): :param dict options: option key mapping to configuration options :param dict values: option key mapping to widget values - :return: + :return: nothing """ - config = {} for key in options: option = options[key] value = values[key] @@ -88,8 +87,8 @@ def parse_config(options, values): config_value = value.get() if config_type == ConfigType.BOOL: if config_value == "On": - config_value = "1" + option.value = "1" else: - config_value = "0" - config[key] = config_value - return config + option.value = "0" + else: + option.value = config_value diff --git a/coretk/coretk/dialogs/setwallpaper.py b/coretk/coretk/dialogs/canvasbackground.py similarity index 60% rename from coretk/coretk/dialogs/setwallpaper.py rename to coretk/coretk/dialogs/canvasbackground.py index 81932208..fe9b5f6a 100644 --- a/coretk/coretk/dialogs/setwallpaper.py +++ b/coretk/coretk/dialogs/canvasbackground.py @@ -9,6 +9,7 @@ from tkinter import filedialog from PIL import Image, ImageTk from coretk.appdirs import BACKGROUNDS_PATH +from coretk.dialogs.dialog import Dialog class ScaleOption(enum.Enum): @@ -19,44 +20,116 @@ class ScaleOption(enum.Enum): TILED = 4 -class CanvasWallpaper: - def __init__(self, app): +class CanvasBackgroundDialog(Dialog): + def __init__(self, master, app): """ create an instance of CanvasWallpaper object :param coretk.app.Application app: root application """ - self.app = app + super().__init__(master, app, "Canvas Background", modal=True) self.canvas = self.app.canvas + self.radiovar = tk.IntVar(value=self.app.radiovar.get()) + self.show_grid_var = tk.IntVar(value=self.app.show_grid_var.get()) + self.adjust_to_dim_var = tk.IntVar(value=self.app.adjust_to_dim_var.get()) + self.image_label = None + self.file_name = tk.StringVar() + self.options = [] + self.draw() - self.top = tk.Toplevel() - self.top.title("Set Canvas Wallpaper") - self.radiovar = tk.IntVar() - print(self.app.radiovar.get()) - self.radiovar.set(self.app.radiovar.get()) - self.show_grid_var = tk.IntVar() - self.show_grid_var.set(self.app.show_grid_var.get()) - self.adjust_to_dim_var = tk.IntVar() - self.adjust_to_dim_var.set(self.app.adjust_to_dim_var.get()) + def draw(self): + self.columnconfigure(0, weight=1) + self.rowconfigure(0, weight=1) + self.draw_image() + self.draw_image_label() + self.draw_image_selection() + self.draw_options() + self.draw_additional_options() + self.draw_buttons() - self.create_image_label() - self.create_text_label() - self.open_image() - self.display_options() - self.additional_options() - self.apply_cancel() - - def create_image_label(self): - image_label = tk.Label( - self.top, text="(image preview)", height=8, width=32, bg="white" + def draw_image(self): + self.image_label = tk.Label( + self, text="(image preview)", height=8, width=32, bg="white" ) - image_label.grid(pady=5) + self.image_label.grid(row=0, column=0, pady=5, sticky="nsew") - def create_text_label(self): - text_label = tk.Label(self.top, text="Image filename: ") - text_label.grid() + def draw_image_label(self): + label = tk.Label(self, text="Image filename: ") + label.grid(row=1, column=0, sticky="ew") - def open_image_link(self): + def draw_image_selection(self): + frame = tk.Frame(self) + frame.columnconfigure(0, weight=2) + frame.columnconfigure(1, weight=1) + frame.columnconfigure(2, weight=1) + frame.grid(row=2, column=0, sticky="ew") + + entry = tk.Entry(frame, textvariable=self.file_name) + entry.focus() + entry.grid(row=0, column=0, sticky="ew") + + button = tk.Button(frame, text="...", command=self.click_open_image) + button.grid(row=0, column=1, sticky="ew") + + button = tk.Button(frame, text="Clear", command=self.click_clear) + button.grid(row=0, column=2, sticky="ew") + + def draw_options(self): + frame = tk.Frame(self) + frame.columnconfigure(0, weight=1) + frame.columnconfigure(1, weight=1) + frame.columnconfigure(2, weight=1) + frame.columnconfigure(3, weight=1) + frame.grid(row=3, column=0, sticky="ew") + + button = tk.Radiobutton( + frame, text="upper-left", value=1, variable=self.radiovar + ) + button.grid(row=0, column=0, sticky="ew") + self.options.append(button) + + button = tk.Radiobutton(frame, text="centered", value=2, variable=self.radiovar) + button.grid(row=0, column=1, sticky="ew") + self.options.append(button) + + button = tk.Radiobutton(frame, text="scaled", value=3, variable=self.radiovar) + button.grid(row=0, column=2, sticky="ew") + self.options.append(button) + + button = tk.Radiobutton(frame, text="titled", value=4, variable=self.radiovar) + button.grid(row=0, column=3, sticky="ew") + self.options.append(button) + + def draw_additional_options(self): + checkbutton = tk.Checkbutton( + self, text="Show grid", variable=self.show_grid_var + ) + checkbutton.grid(row=4, column=0, sticky="ew", padx=5) + + checkbutton = tk.Checkbutton( + self, + text="Adjust canvas size to image dimensions", + variable=self.adjust_to_dim_var, + command=self.click_adjust_canvas, + ) + checkbutton.grid(row=5, column=0, sticky="ew", padx=5) + + self.show_grid_var.set(1) + self.adjust_to_dim_var.set(0) + + def draw_buttons(self): + frame = tk.Frame(self) + frame.grid(row=6, column=0, pady=5, sticky="ew") + frame.columnconfigure(0, weight=1) + frame.columnconfigure(1, weight=1) + + button = tk.Button(frame, text="Apply", command=self.click_apply) + button.grid(row=0, column=0, sticky="ew") + + button = tk.Button(frame, text="Cancel", command=self.destroy) + button.grid(row=0, column=1, sticky="ew") + + def click_open_image(self): filename = filedialog.askopenfilename( initialdir=str(BACKGROUNDS_PATH), title="Open", @@ -65,102 +138,39 @@ class CanvasWallpaper: ("All Files", "*"), ), ) - - # fill the file name into the file name entry - img_open_frame = self.top.grid_slaves(2, 0)[0] - filename_entry = img_open_frame.grid_slaves(0, 0)[0] - filename_entry.delete(0, tk.END) - filename_entry.insert(tk.END, filename) - - # display that onto the label - img_label = self.top.grid_slaves(0, 0)[0] if filename: + self.file_name.set(filename) + width, height = 250, 135 img = Image.open(filename) - img = img.resize((250, 135), Image.ANTIALIAS) + img = img.resize((width, height), Image.ANTIALIAS) tk_img = ImageTk.PhotoImage(img) - img_label.config(image=tk_img, width=250, height=135) - img_label.image = tk_img + self.image_label.config(image=tk_img, width=width, height=height) + self.image_label.image = tk_img - def clear_link(self): + def click_clear(self): """ delete like shown in image link entry if there is any :return: nothing """ # delete entry - img_open_frame = self.top.grid_slaves(2, 0)[0] - filename_entry = img_open_frame.grid_slaves(0, 0)[0] - filename_entry.delete(0, tk.END) - + self.file_name.set("") # delete display image - img_label = self.top.grid_slaves(0, 0)[0] - img_label.config(image="", width=32, height=8) - - def open_image(self): - f = tk.Frame(self.top) - - var = tk.StringVar(f, value="") - e = tk.Entry(f, textvariable=var) - e.focus() - e.grid() - - b = tk.Button(f, text="...", command=self.open_image_link) - b.grid(row=0, column=1) - - b = tk.Button(f, text="Clear", command=self.clear_link) - b.grid(row=0, column=2) - - f.grid() - - def display_options(self): - f = tk.Frame(self.top) - - b1 = tk.Radiobutton(f, text="upper-left", value=1, variable=self.radiovar) - b1.grid(row=0, column=0) - - b2 = tk.Radiobutton(f, text="centered", value=2, variable=self.radiovar) - b2.grid(row=0, column=1) - - b3 = tk.Radiobutton(f, text="scaled", value=3, variable=self.radiovar) - b3.grid(row=0, column=2) - - b4 = tk.Radiobutton(f, text="titled", value=4, variable=self.radiovar) - b4.grid(row=0, column=3) - - # self.radiovar.set(1) - - f.grid() - - def adjust_canvas_size(self): + self.image_label.config(image="", width=32, height=8) + def click_adjust_canvas(self): # deselect all radio buttons and grey them out if self.adjust_to_dim_var.get() == 1: self.radiovar.set(0) - option_frame = self.top.grid_slaves(3, 0)[0] - for i in option_frame.grid_slaves(): - i.config(state=tk.DISABLED) - + for option in self.options: + option.config(state=tk.DISABLED) # turn back the radio button to active state so that user can choose again elif self.adjust_to_dim_var.get() == 0: - option_frame = self.top.grid_slaves(3, 0)[0] - for i in option_frame.grid_slaves(): - i.config(state=tk.NORMAL) - self.radiovar.set(1) + self.radiovar.set(1) + for option in self.options: + option.config(state=tk.NORMAL) else: - logging.error("setwallpaper.py adjust_canvas_size invalid value") - - def additional_options(self): - b = tk.Checkbutton(self.top, text="Show grid", variable=self.show_grid_var) - b.grid(sticky=tk.W, padx=5) - b = tk.Checkbutton( - self.top, - text="Adjust canvas size to image dimensions", - variable=self.adjust_to_dim_var, - command=self.adjust_canvas_size, - ) - b.grid(sticky=tk.W, padx=5) - self.show_grid_var.set(1) - self.adjust_to_dim_var.set(0) + logging.error("canvasbackground.py adjust_canvas_size invalid value") def delete_canvas_components(self, tag_list): """ @@ -316,7 +326,7 @@ class CanvasWallpaper: self.canvas.itemconfig(i, state=tk.NORMAL) self.canvas.lift(i) else: - logging.error("setwallpaper.py show_grid invalid value") + logging.error("canvasbackground.py show_grid invalid value") def save_wallpaper_options(self): self.app.radiovar.set(self.radiovar.get()) @@ -324,51 +334,39 @@ class CanvasWallpaper: self.app.adjust_to_dim_var.set(self.adjust_to_dim_var.get()) def click_apply(self): - img_link_frame = self.top.grid_slaves(2, 0)[0] - filename = img_link_frame.grid_slaves(0, 0)[0].get() + filename = self.file_name.get() if not filename: self.delete_canvas_components(["wallpaper"]) - self.top.destroy() + self.destroy() self.app.current_wallpaper = None self.save_wallpaper_options() return + try: img = Image.open(filename) self.app.current_wallpaper = img except FileNotFoundError: - print("invalid filename, draw original white plot") + logging.error("invalid background: %s", filename) if self.app.wallpaper_id: self.canvas.delete(self.app.wallpaper_id) - self.top.destroy() + self.destroy() return self.app.adjust_to_dim_var.set(self.adjust_to_dim_var.get()) if self.adjust_to_dim_var.get() == 0: - self.app.radiovar.set(self.radiovar.get()) - - if self.radiovar.get() == ScaleOption.UPPER_LEFT.value: + option = ScaleOption(self.radiovar.get()) + if option == ScaleOption.UPPER_LEFT: self.upper_left(img) - elif self.radiovar.get() == ScaleOption.CENTERED.value: + elif option == ScaleOption.CENTERED: self.center(img) - elif self.radiovar.get() == ScaleOption.SCALED.value: + elif option == ScaleOption.SCALED: self.scaled(img) - elif self.radiovar.get() == ScaleOption.TILED.value: + elif option == ScaleOption.TILED: print("not implemented yet") elif self.adjust_to_dim_var.get() == 1: self.canvas_to_image_dimension(img) self.show_grid() - self.top.destroy() - - def apply_cancel(self): - f = tk.Frame(self.top) - - b = tk.Button(f, text="Apply", command=self.click_apply) - b.grid(row=0, column=0) - - b = tk.Button(f, text="Cancel", command=self.top.destroy) - b.grid(row=0, column=1) - - f.grid(pady=5) + self.destroy() diff --git a/coretk/coretk/dialogs/canvassizeandscale.py b/coretk/coretk/dialogs/canvassizeandscale.py new file mode 100644 index 00000000..20b464d0 --- /dev/null +++ b/coretk/coretk/dialogs/canvassizeandscale.py @@ -0,0 +1,211 @@ +""" +size and scale +""" +import tkinter as tk +from tkinter import font + +from coretk.dialogs.canvasbackground import ScaleOption +from coretk.dialogs.dialog import Dialog + +DRAW_OBJECT_TAGS = ["edge", "node", "nodename", "linkinfo", "antenna"] + + +class SizeAndScaleDialog(Dialog): + def __init__(self, master, app): + """ + create an instance for size and scale object + + :param app: main application + """ + super().__init__(master, app, "Canvas Size and Scale", modal=True) + self.meter_per_pixel = self.app.canvas.meters_per_pixel + self.section_font = font.Font(weight="bold") + + # get current canvas dimensions + canvas = self.app.canvas + plot = canvas.find_withtag("rectangle") + x0, y0, x1, y1 = canvas.bbox(plot[0]) + width = abs(x0 - x1) - 2 + height = abs(y0 - y1) - 2 + self.pixel_width = tk.IntVar(value=width) + self.pixel_height = tk.IntVar(value=height) + self.meters_width = tk.IntVar(value=width * self.meter_per_pixel) + self.meters_height = tk.IntVar(value=height * self.meter_per_pixel) + self.scale = tk.IntVar(value=self.meter_per_pixel * 100) + self.x = tk.IntVar(value=0) + self.y = tk.IntVar(value=0) + self.lat = tk.DoubleVar(value=47.5791667) + self.lon = tk.DoubleVar(value=-122.132322) + self.alt = tk.DoubleVar(value=2.0) + self.save_default = tk.BooleanVar(value=False) + self.draw() + + def draw(self): + self.columnconfigure(0, weight=1) + self.draw_size() + self.draw_scale() + self.draw_reference_point() + self.draw_save_as_default() + self.draw_buttons() + + def draw_size(self): + label = tk.Label(self, text="Size", font=self.section_font) + label.grid(sticky="w") + + # draw size row 1 + frame = tk.Frame(self) + frame.grid(sticky="ew", pady=3) + frame.columnconfigure(1, weight=1) + frame.columnconfigure(3, weight=1) + label = tk.Label(frame, text="Width") + label.grid(row=0, column=0, sticky="w") + entry = tk.Entry(frame, textvariable=self.pixel_width) + entry.grid(row=0, column=1, sticky="ew") + label = tk.Label(frame, text="x Height") + label.grid(row=0, column=2, sticky="w") + entry = tk.Entry(frame, textvariable=self.pixel_height) + entry.grid(row=0, column=3, sticky="ew") + label = tk.Label(frame, text="Pixels") + label.grid(row=0, column=4, sticky="w") + + # draw size row 2 + frame = tk.Frame(self) + frame.grid(sticky="ew", pady=3) + frame.columnconfigure(1, weight=1) + frame.columnconfigure(3, weight=1) + label = tk.Label(frame, text="Width") + label.grid(row=0, column=0, sticky="w") + entry = tk.Entry(frame, textvariable=self.meters_width) + entry.grid(row=0, column=1, sticky="ew") + label = tk.Label(frame, text="x Height") + label.grid(row=0, column=2, sticky="w") + entry = tk.Entry(frame, textvariable=self.meters_height) + entry.grid(row=0, column=3, sticky="ew") + label = tk.Label(frame, text="Meters") + label.grid(row=0, column=4, sticky="w") + + def draw_scale(self): + label = tk.Label(self, text="Scale", font=self.section_font) + label.grid(sticky="w") + + frame = tk.Frame(self) + frame.grid(sticky="ew") + frame.columnconfigure(1, weight=1) + label = tk.Label(frame, text="100 Pixels =") + label.grid(row=0, column=0, sticky="w") + entry = tk.Entry(frame, textvariable=self.scale) + entry.grid(row=0, column=1, sticky="ew") + label = tk.Label(frame, text="Meters") + label.grid(row=0, column=2, sticky="w") + + def draw_reference_point(self): + label = tk.Label(self, text="Reference point", font=self.section_font) + label.grid(sticky="w") + label = tk.Label( + self, text="Default is (0, 0), the upper left corner of the canvas" + ) + label.grid(sticky="w") + + frame = tk.Frame(self) + frame.grid(sticky="ew", pady=3) + frame.columnconfigure(1, weight=1) + frame.columnconfigure(3, weight=1) + + label = tk.Label(frame, text="X") + label.grid(row=0, column=0, sticky="w") + x_var = tk.StringVar(value=0) + entry = tk.Entry(frame, textvariable=x_var) + entry.grid(row=0, column=1, sticky="ew") + + label = tk.Label(frame, text="Y") + label.grid(row=0, column=2, sticky="w") + y_var = tk.StringVar(value=0) + entry = tk.Entry(frame, textvariable=y_var) + entry.grid(row=0, column=3, sticky="ew") + + label = tk.Label(self, text="Translates To") + label.grid(sticky="w") + + frame = tk.Frame(self) + frame.grid(sticky="ew", pady=3) + frame.columnconfigure(1, weight=1) + frame.columnconfigure(3, weight=1) + frame.columnconfigure(5, weight=1) + + label = tk.Label(frame, text="Lat") + label.grid(row=0, column=0, sticky="w") + entry = tk.Entry(frame, textvariable=self.lat) + entry.grid(row=0, column=1, sticky="ew") + + label = tk.Label(frame, text="Lon") + label.grid(row=0, column=2, sticky="w") + entry = tk.Entry(frame, textvariable=self.lon) + entry.grid(row=0, column=3, sticky="ew") + + label = tk.Label(frame, text="Alt") + label.grid(row=0, column=4, sticky="w") + entry = tk.Entry(frame, textvariable=self.alt) + entry.grid(row=0, column=5, sticky="ew") + + def draw_save_as_default(self): + button = tk.Checkbutton( + self, text="Save as default?", variable=self.save_default + ) + button.grid(sticky="w", pady=3) + + def draw_buttons(self): + frame = tk.Frame(self) + frame.columnconfigure(0, weight=1) + frame.columnconfigure(1, weight=1) + frame.grid(sticky="ew") + + button = tk.Button(frame, text="Apply", command=self.click_apply) + button.grid(row=0, column=0, pady=5, sticky="ew") + + button = tk.Button(frame, text="Cancel", command=self.destroy) + button.grid(row=0, column=1, pady=5, sticky="ew") + + def redraw_grid(self): + """ + redraw grid with new dimension + + :return: nothing + """ + width, height = self.pixel_width.get(), self.pixel_height.get() + + canvas = self.app.canvas + canvas.config(scrollregion=(0, 0, width + 200, height + 200)) + + # delete old plot and redraw + for i in canvas.find_withtag("gridline"): + canvas.delete(i) + for i in canvas.find_withtag("rectangle"): + canvas.delete(i) + + canvas.draw_grid(width=width, height=height) + # lift anything that is drawn on the plot before + for tag in DRAW_OBJECT_TAGS: + for i in canvas.find_withtag(tag): + canvas.lift(i) + + def click_apply(self): + meter_per_pixel = float(self.scale.get()) / 100 + self.app.canvas.meters_per_pixel = meter_per_pixel + self.redraw_grid() + # if there is a current wallpaper showing, redraw it based on current wallpaper options + wallpaper_tool = self.app.set_wallpaper + current_wallpaper = self.app.current_wallpaper + if current_wallpaper: + if self.app.adjust_to_dim_var.get() == 0: + if self.app.radiovar.get() == ScaleOption.UPPER_LEFT.value: + wallpaper_tool.upper_left(current_wallpaper) + elif self.app.radiovar.get() == ScaleOption.CENTERED.value: + wallpaper_tool.center(current_wallpaper) + elif self.app.radiovar.get() == ScaleOption.SCALED.value: + wallpaper_tool.scaled(current_wallpaper) + elif self.app.radiovar.get() == ScaleOption.TILED.value: + print("not implemented") + elif self.app.adjust_to_dim_var.get() == 1: + wallpaper_tool.canvas_to_image_dimension(current_wallpaper) + wallpaper_tool.show_grid() + self.destroy() diff --git a/coretk/coretk/dialogs/nodeconfig.py b/coretk/coretk/dialogs/nodeconfig.py index d670853c..f1de2e50 100644 --- a/coretk/coretk/dialogs/nodeconfig.py +++ b/coretk/coretk/dialogs/nodeconfig.py @@ -3,7 +3,7 @@ from tkinter import ttk from coretk.dialogs.dialog import Dialog from coretk.dialogs.nodeicon import NodeIconDialog -from coretk.dialogs.nodeservice import NodeServices +from coretk.dialogs.nodeservice import NodeServicesDialog NETWORKNODETYPES = ["switch", "hub", "wlan", "rj45", "tunnel"] DEFAULTNODES = ["router", "host", "PC"] @@ -56,7 +56,7 @@ class NodeConfigDialog(Dialog): frame.columnconfigure(0, weight=1) frame.columnconfigure(1, weight=1) - button = tk.Button(frame, text="Services", command=lambda: NodeServices()) + button = tk.Button(frame, text="Services", command=self.click_services) button.grid(row=0, column=0, padx=2, sticky="ew") self.image_button = tk.Button( @@ -80,6 +80,10 @@ class NodeConfigDialog(Dialog): button = tk.Button(frame, text="Cancel", command=self.destroy) button.grid(row=0, column=1, sticky="ew") + def click_services(self): + dialog = NodeServicesDialog(self, self.app, self.canvas_node) + dialog.show() + def click_icon(self): dialog = NodeIconDialog(self, self.app, self.canvas_node) dialog.show() diff --git a/coretk/coretk/dialogs/nodeservice.py b/coretk/coretk/dialogs/nodeservice.py index 3bcedfb7..82d36cca 100644 --- a/coretk/coretk/dialogs/nodeservice.py +++ b/coretk/coretk/dialogs/nodeservice.py @@ -4,6 +4,8 @@ core node services import tkinter as tk from tkinter import messagebox +from coretk.dialogs.dialog import Dialog + CORE_DEFAULT_GROUPS = ["EMANE", "FRR", "ProtoSvc", "Quagga", "Security", "Utility"] DEFAULT_GROUP_RADIO_VALUE = { "EMANE": 1, @@ -57,35 +59,28 @@ DEFAULT_GROUP_SERVICES = { } -class NodeServices: - def __init__(self): +class NodeServicesDialog(Dialog): + def __init__(self, master, app, canvas_node): + super().__init__(master, app, "Node Services", modal=True) + self.canvas_node = canvas_node self.core_groups = [] self.service_to_config = None + self.config_frame = None + self.draw() - self.top = tk.Toplevel() - self.top.title("Node services") - self.config_frame = tk.Frame(self.top) - self.config_frame.grid() + def draw(self): + self.columnconfigure(0, weight=1) + self.rowconfigure(0, weight=1) + self.config_frame = tk.Frame(self) + self.config_frame.columnconfigure(0, weight=1) + self.config_frame.columnconfigure(1, weight=1) + self.config_frame.columnconfigure(2, weight=1) + self.config_frame.rowconfigure(0, weight=1) + self.config_frame.grid(row=0, column=0, sticky="nsew") self.draw_group() - self.group_services() - self.current_services() - self.node_service_options() - - def display_group_services(self, group_name): - group_services_frame = self.config_frame.grid_slaves(row=0, column=1)[0] - listbox = group_services_frame.grid_slaves(row=1, column=0)[0] - listbox.delete(0, tk.END) - for s in DEFAULT_GROUP_SERVICES[group_name]: - listbox.insert(tk.END, s) - for i in range(listbox.size()): - listbox.itemconfig(i, selectbackground="white") - - def group_select(self, event): - listbox = event.widget - cur_selection = listbox.curselection() - if cur_selection: - s = listbox.get(listbox.curselection()) - self.display_group_services(s) + self.draw_services() + self.draw_current_services() + self.draw_buttons() def draw_group(self): """ @@ -93,36 +88,113 @@ class NodeServices: :return: nothing """ - f = tk.Frame(self.config_frame) + frame = tk.Frame(self.config_frame) + frame.columnconfigure(0, weight=1) + frame.rowconfigure(1, weight=1) + frame.grid(row=0, column=0, padx=3, pady=3, sticky="nsew") - lbl = tk.Label(f, text="Group") - lbl.grid() + label = tk.Label(frame, text="Group") + label.grid(row=0, column=0, sticky="ew") - sb = tk.Scrollbar(f, orient=tk.VERTICAL) - sb.grid(row=1, column=1, sticky=tk.S + tk.N) + scrollbar = tk.Scrollbar(frame, orient=tk.VERTICAL) + scrollbar.grid(row=1, column=1, sticky="ns") listbox = tk.Listbox( - f, + frame, selectmode=tk.SINGLE, - yscrollcommand=sb.set, + yscrollcommand=scrollbar.set, relief=tk.FLAT, - highlightbackground="#b3b3b3", - highlightcolor="#b3b3b3", highlightthickness=0.5, bd=0, ) + listbox.grid(row=1, column=0, sticky="nsew") + listbox.bind("<>", self.handle_group_change) - for grp in CORE_DEFAULT_GROUPS: - listbox.insert(tk.END, grp) - for i in range(0, listbox.size()): - listbox.itemconfig(i, selectbackground="white") - listbox.grid(row=1, column=0) + for group in CORE_DEFAULT_GROUPS: + listbox.insert(tk.END, group) - sb.config(command=listbox.yview) - f.grid(padx=3, pady=3) - listbox.bind("<>", self.group_select) + scrollbar.config(command=listbox.yview) - def group_service_select(self, event): + def draw_services(self): + frame = tk.Frame(self.config_frame) + frame.columnconfigure(0, weight=1) + frame.rowconfigure(1, weight=1) + frame.grid(row=0, column=1, padx=3, pady=3, sticky="nsew") + + label = tk.Label(frame, text="Group services") + label.grid(row=0, column=0, sticky="ew") + + scrollbar = tk.Scrollbar(frame, orient=tk.VERTICAL) + scrollbar.grid(row=1, column=1, sticky="ns") + + listbox = tk.Listbox( + frame, + selectmode=tk.SINGLE, + yscrollcommand=scrollbar.set, + relief=tk.FLAT, + highlightthickness=0.5, + bd=0, + ) + listbox.grid(row=1, column=0, sticky="nsew") + listbox.bind("<>", self.handle_service_change) + + scrollbar.config(command=listbox.yview) + + def draw_current_services(self): + frame = tk.Frame(self.config_frame) + frame.columnconfigure(0, weight=1) + frame.rowconfigure(1, weight=1) + frame.grid(row=0, column=2, padx=3, pady=3, sticky="nsew") + + label = tk.Label(frame, text="Current services") + label.grid(row=0, column=0, sticky="ew") + + scrollbar = tk.Scrollbar(frame, orient=tk.VERTICAL) + scrollbar.grid(row=1, column=1, sticky="ns") + + listbox = tk.Listbox( + frame, + selectmode=tk.MULTIPLE, + yscrollcommand=scrollbar.set, + relief=tk.FLAT, + highlightthickness=0.5, + bd=0, + ) + listbox.grid(row=1, column=0, sticky="nsew") + + scrollbar.config(command=listbox.yview) + + def draw_buttons(self): + frame = tk.Frame(self) + frame.columnconfigure(0, weight=1) + frame.columnconfigure(1, weight=1) + frame.columnconfigure(2, weight=1) + frame.grid(row=1, column=0, sticky="ew") + + button = tk.Button(frame, text="Configure", command=self.click_configure) + button.grid(row=0, column=0, sticky="ew") + + button = tk.Button(frame, text="Apply") + button.grid(row=0, column=1, sticky="ew") + + button = tk.Button(frame, text="Cancel", command=self.destroy) + button.grid(row=0, column=2, sticky="ew") + + def handle_group_change(self, event): + listbox = event.widget + cur_selection = listbox.curselection() + if cur_selection: + s = listbox.get(listbox.curselection()) + self.display_group_services(s) + + def display_group_services(self, group_name): + group_services_frame = self.config_frame.grid_slaves(row=0, column=1)[0] + listbox = group_services_frame.grid_slaves(row=1, column=0)[0] + listbox.delete(0, tk.END) + for s in DEFAULT_GROUP_SERVICES[group_name]: + listbox.insert(tk.END, s) + + def handle_service_change(self, event): print("select group service") listbox = event.widget cur_selection = listbox.curselection() @@ -132,64 +204,8 @@ class NodeServices: else: self.service_to_config = None - def group_services(self): - f = tk.Frame(self.config_frame) - lbl = tk.Label(f, text="Group services") - lbl.grid() - - sb = tk.Scrollbar(f, orient=tk.VERTICAL) - sb.grid(row=1, column=1, sticky=tk.S + tk.N) - - listbox = tk.Listbox( - f, - selectmode=tk.SINGLE, - yscrollcommand=sb.set, - relief=tk.FLAT, - highlightbackground="#b3b3b3", - highlightcolor="#b3b3b3", - highlightthickness=0.5, - bd=0, - ) - listbox.grid(row=1, column=0) - sb.config(command=listbox.yview) - f.grid(padx=3, pady=3, row=0, column=1) - - listbox.bind("<>", self.group_service_select) - - def current_services(self): - f = tk.Frame(self.config_frame) - lbl = tk.Label(f, text="Current services") - lbl.grid() - - sb = tk.Scrollbar(f, orient=tk.VERTICAL) - sb.grid(row=1, column=1, sticky=tk.S + tk.N) - - listbox = tk.Listbox( - f, - selectmode=tk.MULTIPLE, - yscrollcommand=sb.set, - relief=tk.FLAT, - highlightbackground="#b3b3b3", - highlightcolor="#b3b3b3", - highlightthickness=0.5, - bd=0, - ) - listbox.grid(row=1, column=0) - sb.config(command=listbox.yview) - f.grid(padx=3, pady=3, row=0, column=2) - - def config_service(self): + def click_configure(self): if self.service_to_config is None: messagebox.showinfo("CORE info", "Choose a service to configure.") else: print(self.service_to_config) - - def node_service_options(self): - f = tk.Frame(self.top) - b = tk.Button(f, text="Connfigure", command=self.config_service) - b.grid(row=0, column=0) - b = tk.Button(f, text="Apply") - b.grid(row=0, column=1) - b = tk.Button(f, text="Cancel", command=self.top.destroy) - b.grid(row=0, column=2) - f.grid(sticky=tk.E) diff --git a/coretk/coretk/dialogs/sessionoptions.py b/coretk/coretk/dialogs/sessionoptions.py index 6279d844..e887c2a1 100644 --- a/coretk/coretk/dialogs/sessionoptions.py +++ b/coretk/coretk/dialogs/sessionoptions.py @@ -27,8 +27,9 @@ class SessionOptionsDialog(Dialog): self.cancel_button.grid(row=1, column=1, pady=PAD_Y, padx=PAD_X, sticky="ew") def save(self): - config = configutils.parse_config(self.options, self.values) + configutils.parse_config(self.options, self.values) session_id = self.app.core.session_id + config = {x: self.options[x].value for x in self.options} response = self.app.core.client.set_session_options(session_id, config) logging.info("saved session config: %s", response) self.destroy() diff --git a/coretk/coretk/dialogs/sizeandscale.py b/coretk/coretk/dialogs/sizeandscale.py deleted file mode 100644 index 0267a300..00000000 --- a/coretk/coretk/dialogs/sizeandscale.py +++ /dev/null @@ -1,277 +0,0 @@ -""" -size and scale -""" -import tkinter as tk -from functools import partial - -from coretk.dialogs.setwallpaper import ScaleOption - -DRAW_OBJECT_TAGS = ["edge", "node", "nodename", "linkinfo", "antenna"] - - -class SizeAndScale: - def __init__(self, app): - """ - create an instance for size and scale object - - :param app: main application - """ - self.app = app - self.top = tk.Toplevel() - self.top.title("Canvas Size and Scale") - self.meter_per_pixel = self.app.canvas.meters_per_pixel - - self.size_chart() - self.scale_chart() - self.reference_point_chart() - self.save_as_default() - self.apply_cancel() - - def pixel_scrollbar_command(self, size_frame, entry_row, entry_column, event): - """ - change the value shown based on scrollbar action - - :param tkinter.Frame frame: pixel dimension frame - :param int entry_row: row number of entry of the frame - :param int entry_column: column number of entry of the frame - :param event: scrollbar event - :return: nothing - """ - pixel_frame = size_frame.grid_slaves(0, 0)[0] - pixel_entry = pixel_frame.grid_slaves(entry_row, entry_column)[0] - val = int(pixel_entry.get()) - - if event == "-1": - new_val = val + 2 - elif event == "1": - new_val = val - 2 - - pixel_entry.delete(0, tk.END) - pixel_entry.insert(tk.END, str(new_val)) - - # change meter dimension - meter_frame = size_frame.grid_slaves(1, 0)[0] - meter_entry = meter_frame.grid_slaves(entry_row, entry_column)[0] - meter_entry.delete(0, tk.END) - meter_entry.insert(tk.END, str(new_val * self.meter_per_pixel)) - - def meter_scrollbar_command(self, size_frame, entry_row, entry_column, event): - """ - change the value shown based on scrollbar action - - :param tkinter.Frame size_frame: size frame - :param int entry_row: row number of entry in the frame it is contained in - :param int entry_column: column number of entry in the frame in is contained in - :param event: scroolbar event - :return: nothing - """ - meter_frame = size_frame.grid_slaves(1, 0)[0] - meter_entry = meter_frame.grid_slaves(entry_row, entry_column)[0] - val = float(meter_entry.get()) - - if event == "-1": - val += 100.0 - elif event == "1": - val -= 100.0 - meter_entry.delete(0, tk.END) - meter_entry.insert(tk.END, str(val)) - - # change pixel dimension - pixel_frame = size_frame.grid_slaves(0, 0)[0] - pixel_entry = pixel_frame.grid_slaves(entry_row, entry_column)[0] - pixel_entry.delete(0, tk.END) - pixel_entry.insert(tk.END, str(int(val / self.meter_per_pixel))) - - def create_text_label(self, frame, text, row, column, sticky=None): - """ - create text label - :param tkinter.Frame frame: parent frame - :param str text: label text - :param int row: row number - :param int column: column number - :param sticky: sticky value - - :return: nothing - """ - text_label = tk.Label(frame, text=text) - text_label.grid(row=row, column=column, sticky=sticky, padx=3, pady=3) - - def create_entry(self, frame, default_value, row, column, width): - text_var = tk.StringVar(frame, value=str(default_value)) - entry = tk.Entry( - frame, textvariable=text_var, width=width, bg="white", state=tk.NORMAL - ) - entry.focus() - entry.grid(row=row, column=column, padx=3, pady=3) - - def size_chart(self): - label = tk.Label(self.top, text="Size") - label.grid(sticky=tk.W, padx=5) - - canvas = self.app.canvas - plot = canvas.find_withtag("rectangle") - x0, y0, x1, y1 = canvas.bbox(plot[0]) - w = abs(x0 - x1) - 2 - h = abs(y0 - y1) - 2 - - f = tk.Frame( - self.top, - highlightbackground="#b3b3b3", - highlightcolor="#b3b3b3", - highlightthickness=0.5, - bd=0, - ) - - f1 = tk.Frame(f) - pw_scrollbar = tk.Scrollbar(f1, orient=tk.VERTICAL) - pw_scrollbar.grid(row=0, column=1) - self.create_entry(f1, w, 0, 0, 6) - pw_scrollbar.config(command=partial(self.pixel_scrollbar_command, f, 0, 0)) - - self.create_text_label(f1, " W x ", 0, 2) - - scrollbar = tk.Scrollbar(f1, orient=tk.VERTICAL) - scrollbar.grid(row=0, column=4) - self.create_entry(f1, h, 0, 3, 6) - scrollbar.config(command=partial(self.pixel_scrollbar_command, f, 0, 3)) - self.create_text_label(f1, " H pixels ", 0, 7) - f1.grid(sticky=tk.W, pady=3) - - f2 = tk.Frame(f) - scrollbar = tk.Scrollbar(f2, orient=tk.VERTICAL) - scrollbar.grid(row=0, column=1) - self.create_entry(f2, w * self.meter_per_pixel, 0, 0, 8) - scrollbar.config(command=partial(self.meter_scrollbar_command, f, 0, 0)) - self.create_text_label(f2, " x ", 0, 2) - - scrollbar = tk.Scrollbar(f2, orient=tk.VERTICAL) - scrollbar.grid(row=0, column=4) - self.create_entry(f2, h * self.meter_per_pixel, 0, 3, 8) - scrollbar.config(command=partial(self.meter_scrollbar_command, f, 0, 3)) - self.create_text_label(f2, " meters ", 0, 5) - - f2.grid(sticky=tk.W, pady=3) - - f.grid(sticky=tk.W + tk.E, padx=5, pady=5, columnspan=2) - - def scale_chart(self): - label = tk.Label(self.top, text="Scale") - label.grid(padx=5, sticky=tk.W) - f = tk.Frame( - self.top, - highlightbackground="#b3b3b3", - highlightcolor="#b3b3b3", - highlightthickness=0.5, - bd=0, - ) - # self.create_text_label(f, "Scale", 0, 0, tk.W) - # f1 = tk.Frame(f) - self.create_text_label(f, "100 pixels = ", 0, 0) - self.create_entry(f, self.meter_per_pixel * 100, 0, 1, 10) - self.create_text_label(f, "meters", 0, 2) - # f1.grid(sticky=tk.W, pady=3) - f.grid(sticky=tk.W + tk.E, padx=5, pady=5, columnspan=2) - - def reference_point_chart(self): - label = tk.Label(self.top, text="Reference point") - label.grid(padx=5, sticky=tk.W) - - f = tk.Frame( - self.top, - highlightbackground="#b3b3b3", - highlightcolor="#b3b3b3", - highlightthickness=0.5, - bd=0, - ) - self.create_text_label( - f, - "The default reference point is (0, 0), the upper left corner of the canvas.", - 1, - 0, - tk.W, - ) - f1 = tk.Frame(f) - self.create_entry(f1, 0, 0, 0, 4) - self.create_text_label(f1, " X, ", 0, 1) - self.create_entry(f1, 0, 0, 2, 4) - self.create_text_label(f1, "Y = ", 0, 3) - self.create_entry(f1, 47.5791667, 0, 4, 13) - self.create_text_label(f1, " lat, ", 0, 5) - self.create_entry(f1, -122.132322, 0, 6, 13) - self.create_text_label(f1, "long", 0, 7) - f1.grid(row=2, column=0, sticky=tk.W, pady=3) - - f2 = tk.Frame(f) - self.create_text_label(f2, "Altitude: ", 0, 0) - self.create_entry(f2, 2.0, 0, 1, 11) - self.create_text_label(f2, " meters ", 0, 2) - f2.grid(row=3, column=0, sticky=tk.W, pady=3) - - f.grid(sticky=tk.W, padx=5, pady=5, columnspan=2) - - def save_as_default(self): - var = tk.IntVar() - button = tk.Checkbutton(self.top, text="Save as default", variable=var) - button.grid(sticky=tk.W, padx=5, pady=5, columnspan=2) - - def redraw_grid(self, pixel_width, pixel_height): - """ - redraw grid with new dimension - - :param int pixel_width: width in pixel - :param int pixel_height: height in pixel - :return: nothing - """ - canvas = self.app.canvas - canvas.config(scrollregion=(0, 0, pixel_width + 200, pixel_height + 200)) - - # delete old plot and redraw - for i in canvas.find_withtag("gridline"): - canvas.delete(i) - for i in canvas.find_withtag("rectangle"): - canvas.delete(i) - - canvas.draw_grid(width=pixel_width, height=pixel_height) - # lift anything that is drawn on the plot before - for tag in DRAW_OBJECT_TAGS: - for i in canvas.find_withtag(tag): - canvas.lift(i) - - def click_apply(self): - size_frame = self.top.grid_slaves(1, 0)[0] - pixel_size_frame = size_frame.grid_slaves(0, 0)[0] - - pixel_width = int(pixel_size_frame.grid_slaves(0, 0)[0].get()) - pixel_height = int(pixel_size_frame.grid_slaves(0, 3)[0].get()) - - scale_frame = self.top.grid_slaves(3, 0)[0] - meter_per_pixel = float(scale_frame.grid_slaves(0, 1)[0].get()) / 100 - self.app.canvas.meters_per_pixel = meter_per_pixel - self.redraw_grid(pixel_width, pixel_height) - print(self.app.current_wallpaper) - print(self.app.radiovar) - # if there is a current wallpaper showing, redraw it based on current wallpaper options - wallpaper_tool = self.app.set_wallpaper - current_wallpaper = self.app.current_wallpaper - if current_wallpaper: - if self.app.adjust_to_dim_var.get() == 0: - if self.app.radiovar.get() == ScaleOption.UPPER_LEFT.value: - wallpaper_tool.upper_left(current_wallpaper) - elif self.app.radiovar.get() == ScaleOption.CENTERED.value: - wallpaper_tool.center(current_wallpaper) - elif self.app.radiovar.get() == ScaleOption.SCALED.value: - wallpaper_tool.scaled(current_wallpaper) - elif self.app.radiovar.get() == ScaleOption.TILED.value: - print("not implemented") - elif self.app.adjust_to_dim_var.get() == 1: - wallpaper_tool.canvas_to_image_dimension(current_wallpaper) - - wallpaper_tool.show_grid() - - self.top.destroy() - - def apply_cancel(self): - apply_button = tk.Button(self.top, text="Apply", command=self.click_apply) - apply_button.grid(row=7, column=0, pady=5) - cancel_button = tk.Button(self.top, text="Cancel", command=self.top.destroy) - cancel_button.grid(row=7, column=1, pady=5) diff --git a/coretk/coretk/menuaction.py b/coretk/coretk/menuaction.py index 1d9adca1..7971553d 100644 --- a/coretk/coretk/menuaction.py +++ b/coretk/coretk/menuaction.py @@ -8,11 +8,11 @@ from tkinter import filedialog, messagebox from core.api.grpc import core_pb2 from coretk.appdirs import XML_PATH +from coretk.dialogs.canvasbackground import CanvasBackgroundDialog +from coretk.dialogs.canvassizeandscale import SizeAndScaleDialog from coretk.dialogs.hooks import HooksDialog from coretk.dialogs.sessionoptions import SessionOptionsDialog from coretk.dialogs.sessions import SessionsDialog -from coretk.dialogs.setwallpaper import CanvasWallpaper -from coretk.dialogs.sizeandscale import SizeAndScale def sub_menu_items(): @@ -155,15 +155,6 @@ def canvas_delete(): logging.debug("Click canvas delete") -def canvas_size_scale(): - logging.debug("Click canvas size/scale") - SizeAndScale() - - -def canvas_wallpaper(): - logging.debug("CLick canvas wallpaper") - - def canvas_previous(): logging.debug("Click canvas previous") @@ -383,10 +374,12 @@ class MenuAction: # self.application.core_editbar.create_toolbar() def canvas_size_and_scale(self): - self.app.size_and_scale = SizeAndScale(self.app) + dialog = SizeAndScaleDialog(self.app, self.app) + dialog.show() def canvas_set_wallpaper(self): - self.app.set_wallpaper = CanvasWallpaper(self.app) + dialog = CanvasBackgroundDialog(self.app, self.app) + dialog.show() def help_core_github(self): webbrowser.open_new("https://github.com/coreemu/core")