From d11ce3ef7f3c7072eec092053406a146d0e56775 Mon Sep 17 00:00:00 2001 From: Huy Pham <42948410+hpham@users.noreply.github.com> Date: Tue, 17 Dec 2019 11:47:05 -0800 Subject: [PATCH] create layout for link configuration --- coretk/coretk/dialogs/linkconfig.py | 212 ++++++++++++++++++++++++++++ coretk/coretk/graph/edges.py | 28 +++- 2 files changed, 239 insertions(+), 1 deletion(-) create mode 100644 coretk/coretk/dialogs/linkconfig.py diff --git a/coretk/coretk/dialogs/linkconfig.py b/coretk/coretk/dialogs/linkconfig.py new file mode 100644 index 00000000..3ece4ec0 --- /dev/null +++ b/coretk/coretk/dialogs/linkconfig.py @@ -0,0 +1,212 @@ +""" +link configuration +""" +import logging +import tkinter as tk +from tkinter import ttk + +from coretk.dialogs.dialog import Dialog + + +class LinkConfiguration(Dialog): + def __init__(self, master, app, edge): + super().__init__(master, app, "link configuration", modal=True) + self.app = app + self.edge = edge + self.is_symmetric = True + if self.is_symmetric: + self.symmetry_var = tk.StringVar(value=">>") + else: + self.symmetry_var = tk.StringVar(value="<<") + + self.bandwidth = tk.DoubleVar() + self.delay = tk.DoubleVar() + self.jitter = tk.DoubleVar() + self.loss = tk.DoubleVar() + self.duplicate = tk.DoubleVar() + self.color = "#000000" + self.width = tk.DoubleVar() + + self.down_bandwidth = tk.DoubleVar() + self.down_delay = tk.DoubleVar() + self.down_jitter = tk.DoubleVar() + self.down_loss = tk.DoubleVar() + self.down_duplicate = tk.DoubleVar() + + self.load_link_config() + self.symmetric_frame = None + self.asymmetric_frame = None + + self.draw() + + def draw(self): + self.top.columnconfigure(0, weight=1) + source_name = self.app.canvas.nodes[self.edge.src].core_node.name + dest_name = self.app.canvas.nodes[self.edge.dst].core_node.name + label = ttk.Label( + self.top, + text="Link from %s to %s" % (source_name, dest_name), + anchor=tk.CENTER, + ) + label.grid(row=0, column=0, sticky="nsew") + frame = ttk.Frame(self.top) + frame.columnconfigure(0, weight=1) + frame.columnconfigure(1, weight=1) + frame.grid(row=1, column=0, sticky="nsew") + button = ttk.Button(frame, text="unlimited") + button.grid(row=0, column=0, sticky="nsew") + if self.is_symmetric: + button = ttk.Button( + frame, textvariable=self.symmetry_var, command=self.change_symmetry + ) + else: + button = ttk.Button( + frame, textvariable=self.symmetry_var, command=self.change_symmetry + ) + button.grid(row=0, column=1, sticky="nsew") + + if self.is_symmetric: + self.symmetric_frame = self.get_frame() + self.symmetric_frame.grid(row=2, column=0, sticky="nsew") + else: + self.asymmetric_frame = self.get_frame() + self.asymmetric_frame.grid(row=2, column=0, sticky="nsew") + + frame = ttk.Frame(self.top) + frame.columnconfigure(0, weight=1) + frame.columnconfigure(1, weight=1) + frame.grid(row=3, column=0, sticky="nsew") + + button = ttk.Button(frame, text="Apply") + button.grid(row=0, column=0, sticky="nsew") + button = ttk.Button(frame, text="Cancel", command=self.destroy) + button.grid(row=0, column=1, sticky="nsew") + + def get_frame(self): + main_frame = ttk.Frame(self.top) + main_frame.columnconfigure(0, weight=1) + if self.is_symmetric: + label_name = "Symmetric link effects: " + else: + label_name = "Asymmetric effects: downstream / upstream " + row = 0 + label = ttk.Label(main_frame, text=label_name, anchor=tk.CENTER) + label.grid(row=row, column=0, sticky="nsew") + row = row + 1 + + frame = ttk.Frame(main_frame) + frame.columnconfigure(0, weight=1) + frame.columnconfigure(1, weight=4) + frame.grid(row=row, column=0, sticky="nsew") + label = ttk.Label(frame, text="Bandwidth (bps): ") + label.grid(row=0, column=0, sticky="nsew") + entry = ttk.Entry(frame, textvariable=self.bandwidth) + entry.grid(row=0, column=1, sticky="nsew") + if not self.is_symmetric: + entry = ttk.Entry(frame, textvariable=self.down_bandwidth) + entry.grid(row=0, column=2, sticky="nsew") + + row = row + 1 + + frame = ttk.Frame(main_frame) + frame.columnconfigure(0, weight=1) + frame.columnconfigure(1, weight=4) + frame.grid(row=row, column=0, sticky="nsew") + label = ttk.Label(frame, text="Delay (us): ") + label.grid(row=0, column=0, sticky="nsew") + entry = ttk.Entry(frame, textvariable=self.delay) + entry.grid(row=0, column=1, sticky="nsew") + if not self.is_symmetric: + entry = ttk.Entry(frame, textvariable=self.down_delay) + entry.grid(row=0, column=2, sticky="nsew") + row = row + 1 + + frame = ttk.Frame(main_frame) + frame.columnconfigure(0, weight=1) + frame.columnconfigure(1, weight=4) + frame.grid(row=row, column=0, sticky="nsew") + label = ttk.Label(frame, text="Jitter (us): ") + label.grid(row=0, column=0, sticky="nsew") + entry = ttk.Entry(frame, textvariable=self.jitter) + entry.grid(row=0, column=1, sticky="nsew") + if not self.is_symmetric: + entry = ttk.Entry(frame, textvariable=self.down_jitter) + entry.grid(row=0, column=2, sticky="nsew") + row = row + 1 + + frame = ttk.Frame(main_frame) + frame.columnconfigure(0, weight=1) + frame.columnconfigure(1, weight=4) + frame.grid(row=row, column=0, sticky="nsew") + label = ttk.Label(frame, text="Loss (%): ") + label.grid(row=0, column=0, sticky="nsew") + entry = ttk.Entry(frame, textvariable=self.loss) + entry.grid(row=0, column=1, sticky="nsew") + if not self.is_symmetric: + entry = ttk.Entry(frame, textvariable=self.down_loss) + entry.grid(row=0, column=1, sticky="nsew") + row = row + 1 + + frame = ttk.Frame(main_frame) + frame.columnconfigure(0, weight=1) + frame.columnconfigure(1, weight=4) + frame.grid(row=row, column=0, sticky="nsew") + label = ttk.Label(frame, text="Duplicate (%): ") + label.grid(row=0, column=0, sticky="nsew") + entry = ttk.Entry(frame, textvariable=self.duplicate) + entry.grid(row=0, column=1, sticky="nsew") + if not self.is_symmetric: + entry = ttk.Entry(frame, textvariable=self.down_duplicate) + entry.grid(row=0, column=1, sticky="nsew") + row = row + 1 + + frame = ttk.Frame(main_frame) + frame.columnconfigure(0, weight=1) + frame.columnconfigure(1, weight=4) + frame.grid(row=row, column=0, sticky="nsew") + label = ttk.Label(frame, text="Color: ") + label.grid(row=0, column=0, sticky="nsew") + button = ttk.Button(frame, text=self.color) + button.grid(row=0, column=1, sticky="nsew") + row = row + 1 + + frame = ttk.Frame(main_frame) + frame.columnconfigure(0, weight=1) + frame.columnconfigure(1, weight=4) + frame.grid(row=row, column=0, sticky="nsew") + label = ttk.Label(frame, text="Width: ") + label.grid(row=0, column=0, sticky="nsew") + entry = ttk.Entry(frame, textvariable=self.width) + entry.grid(row=0, column=1, sticky="nsew") + + return main_frame + + def apply(self): + logging.debug("click apply") + + def change_symmetry(self): + logging.debug("change symmetry") + + if self.is_symmetric: + self.is_symmetric = False + self.symmetry_var.set("<<") + if not self.asymmetric_frame: + self.asymmetric_frame = self.get_frame() + self.symmetric_frame.grid_forget() + self.asymmetric_frame.grid(row=2, column=0) + else: + self.is_symmetric = True + self.symmetry_var.set(">>") + if not self.symmetric_frame: + self.symmetric_frame = self.get_frame() + self.asymmetric_frame.grid_forget() + self.symmetric_frame.grid(row=2, column=0) + + def load_link_config(self): + """ + populate link config to the table + + :return: nothing + """ + width = self.app.canvas.itemcget(self.edge.id, "width") + self.width.set(width) diff --git a/coretk/coretk/graph/edges.py b/coretk/coretk/graph/edges.py index 94d847bc..ab9447be 100644 --- a/coretk/coretk/graph/edges.py +++ b/coretk/coretk/graph/edges.py @@ -1,5 +1,8 @@ +import logging import tkinter as tk +from coretk import themes +from coretk.dialogs.linkconfig import LinkConfiguration from coretk.graph import tags from coretk.nodeutils import NodeUtils @@ -23,7 +26,7 @@ class CanvasEdge: Canvas edge class """ - width = 1.4 + width = 3 def __init__(self, x1, y1, x2, y2, src, canvas): """ @@ -46,6 +49,10 @@ class CanvasEdge: self.token = None self.link_info = None self.throughput = None + self.set_binding() + + def set_binding(self): + self.canvas.tag_bind(self.id, "", self.create_context) def complete(self, dst): self.dst = dst @@ -89,3 +96,22 @@ class CanvasEdge: if self.link_info: self.canvas.delete(self.link_info.id1) self.canvas.delete(self.link_info.id2) + + def create_context(self, event): + logging.debug("create link context") + context = tk.Menu(self.canvas) + themes.style_menu(context) + context.add_command(label="Configure", command=self.configure) + context.add_command(label="Delete") + context.add_command(label="Split") + context.add_command(label="Merge") + if self.canvas.app.core.is_runtime(): + context.entryconfigure(1, state="disabled") + context.entryconfigure(2, state="disabled") + context.entryconfigure(3, state="disabled") + context.post(event.x_root, event.y_root) + + def configure(self): + logging.debug("link configuration") + dialog = LinkConfiguration(self.canvas, self.canvas.app, self) + dialog.show()