diff --git a/coretk/coretk/canvasaction.py b/coretk/coretk/canvasaction.py index 5b9c08c3..08aa8c3d 100644 --- a/coretk/coretk/canvasaction.py +++ b/coretk/coretk/canvasaction.py @@ -30,7 +30,7 @@ class CanvasAction: def display_wlan_configuration(self, canvas_node): wlan_config = self.master.core.wlanconfig_management.configurations[ - canvas_node.core_id + canvas_node.core_node.id ] dialog = WlanConfigDialog( self.master, self.master, self.node_to_show_config, wlan_config diff --git a/coretk/coretk/dialogs/emaneconfig.py b/coretk/coretk/dialogs/emaneconfig.py index d64e9089..2c885511 100644 --- a/coretk/coretk/dialogs/emaneconfig.py +++ b/coretk/coretk/dialogs/emaneconfig.py @@ -20,6 +20,7 @@ class EmaneConfiguration(Dialog): super().__init__(master, app, "emane configuration", modal=False) self.app = app self.canvas_node = canvas_node + self.node = canvas_node.core_node self.radiovar = tk.IntVar() self.radiovar.set(1) self.columnconfigure(0, weight=1) @@ -122,20 +123,15 @@ class EmaneConfiguration(Dialog): # add string emane_ infront for grpc call response = self.app.core.client.set_emane_model_config( - self.app.core.session_id, - self.canvas_node.core_id, - "emane_" + model_name, - config, + self.app.core.session_id, self.node.id, f"emane_{model_name}", config ) logging.info( - "emaneconfig.py config emane model (%s), result: %s", - self.canvas_node.core_id, - response, + "emaneconfig.py config emane model (%s), result: %s", self.node.id, response ) # store the change locally self.app.core.emaneconfig_management.set_custom_emane_cloud_config( - self.canvas_node.core_id, "emane_" + model_name + self.node.id, f"emane_{model_name}" ) self.emane_model_dialog.destroy() @@ -161,7 +157,7 @@ class EmaneConfiguration(Dialog): session_id = self.app.core.session_id # add string emane_ before model name for grpc call response = self.app.core.client.get_emane_model_config( - session_id, self.canvas_node.core_id, "emane_" + model_name + session_id, self.node.id, f"emane_{model_name}" ) logging.info("emane model config %s", response) diff --git a/coretk/coretk/dialogs/mobilityconfig.py b/coretk/coretk/dialogs/mobilityconfig.py index 1f53b4a0..2c20229a 100644 --- a/coretk/coretk/dialogs/mobilityconfig.py +++ b/coretk/coretk/dialogs/mobilityconfig.py @@ -19,9 +19,10 @@ class MobilityConfigDialog(Dialog): """ super().__init__(master, app, "ns2script configuration", modal=True) self.canvas_node = canvas_node + self.node = canvas_node.core_node logging.info(app.canvas.core.mobilityconfig_management.configurations) self.node_config = app.canvas.core.mobilityconfig_management.configurations[ - canvas_node.core_id + self.node.id ] self.mobility_script_parameters() @@ -208,7 +209,7 @@ class MobilityConfigDialog(Dialog): else: loop = "0" self.app.canvas.core.mobilityconfig_management.set_custom_configuration( - node_id=self.canvas_node.core_id, + node_id=self.node.id, file=file, refresh_ms=refresh_time, loop=loop, diff --git a/coretk/coretk/dialogs/nodeconfig.py b/coretk/coretk/dialogs/nodeconfig.py index a8252336..8a0d4522 100644 --- a/coretk/coretk/dialogs/nodeconfig.py +++ b/coretk/coretk/dialogs/nodeconfig.py @@ -1,14 +1,36 @@ +import logging import tkinter as tk +from functools import partial from tkinter import ttk from coretk.dialogs.dialog import Dialog from coretk.dialogs.icondialog import IconDialog from coretk.dialogs.nodeservice import NodeService +from coretk.widgets import FrameScroll DEFAULT_NODES = {"router", "host", "PC", "mdr", "prouter"} PAD = 5 +def mac_auto(is_auto, entry): + logging.info("mac auto clicked") + if is_auto.get(): + logging.info("disabling mac") + entry.var.set("") + entry.config(state=tk.DISABLED) + else: + entry.var.set("00:00:00:00:00:00") + entry.config(state=tk.NORMAL) + + +class InterfaceData: + def __init__(self, is_auto, mac, ip4, ip6): + self.is_auto = is_auto + self.mac = mac + self.ip4 = ip4 + self.ip6 = ip6 + + class NodeConfigDialog(Dialog): def __init__(self, master, app, canvas_node): """ @@ -18,13 +40,20 @@ class NodeConfigDialog(Dialog): :param coretk.app.Application: main app :param coretk.graph.CanvasNode canvas_node: canvas node object """ - super().__init__(master, app, f"{canvas_node.name} Configuration", modal=True) + super().__init__( + master, app, f"{canvas_node.core_node.name} Configuration", modal=True + ) self.canvas_node = canvas_node + self.node = canvas_node.core_node self.image = canvas_node.image self.image_button = None - self.name = tk.StringVar(value=canvas_node.name) - self.type = tk.StringVar(value=canvas_node.core_node.model) - self.server = tk.StringVar() + self.name = tk.StringVar(value=self.node.name) + self.type = tk.StringVar(value=self.node.model) + server = "localhost" + if self.node.server: + server = self.node.server + self.server = tk.StringVar(value=server) + self.interfaces = {} self.draw() def draw(self): @@ -82,8 +111,50 @@ class NodeConfigDialog(Dialog): button = ttk.Button(self.top, text="Services", command=self.click_services) button.grid(sticky="ew", pady=PAD) + # interfaces + if self.canvas_node.interfaces: + self.draw_interfaces() + self.draw_buttons() + def draw_interfaces(self): + scroll = FrameScroll(self.top, self.app, text="Interfaces") + scroll.grid(sticky="nsew") + scroll.frame.columnconfigure(0, weight=1) + scroll.frame.rowconfigure(0, weight=1) + for interface in self.canvas_node.interfaces: + logging.info("interface: %s", interface) + frame = ttk.LabelFrame(scroll.frame, text=interface.name, padding=PAD) + frame.grid(sticky="ew", pady=PAD) + frame.columnconfigure(1, weight=1) + frame.columnconfigure(2, weight=1) + + label = ttk.Label(frame, text="MAC") + label.grid(row=0, column=0, padx=PAD, pady=PAD) + is_auto = tk.BooleanVar(value=True) + checkbutton = ttk.Checkbutton(frame, text="Auto?", variable=is_auto) + checkbutton.var = is_auto + checkbutton.grid(row=0, column=1, padx=PAD) + mac = tk.StringVar(value=interface.mac) + entry = ttk.Entry(frame, textvariable=mac, state=tk.DISABLED) + entry.grid(row=0, column=2, sticky="ew") + func = partial(mac_auto, is_auto, entry) + checkbutton.config(command=func) + + label = ttk.Label(frame, text="IPv4") + label.grid(row=1, column=0, padx=PAD, pady=PAD) + ip4 = tk.StringVar(value=f"{interface.ip4}/{interface.ip4mask}") + entry = ttk.Entry(frame, textvariable=ip4) + entry.grid(row=1, column=1, columnspan=2, sticky="ew") + + label = ttk.Label(frame, text="IPv6") + label.grid(row=2, column=0, padx=PAD, pady=PAD) + ip6 = tk.StringVar(value=f"{interface.ip6}/{interface.ip6mask}") + entry = ttk.Entry(frame, textvariable=ip6) + entry.grid(row=2, column=1, columnspan=2, sticky="ew") + + self.interfaces[interface.id] = InterfaceData(is_auto, mac, ip4, ip6) + def draw_buttons(self): frame = ttk.Frame(self.top) frame.grid(sticky="ew") @@ -101,16 +172,20 @@ class NodeConfigDialog(Dialog): dialog.show() def click_icon(self): - dialog = IconDialog( - self, self.app, self.canvas_node.name, self.canvas_node.image - ) + dialog = IconDialog(self, self.app, self.node.name, self.canvas_node.image) dialog.show() if dialog.image: self.image = dialog.image self.image_button.config(image=self.image) def config_apply(self): - self.canvas_node.name = self.name.get() + # update core node + self.node.name = self.name.get() + + # update canvas node self.canvas_node.image = self.image - self.canvas_node.canvas.itemconfig(self.canvas_node.id, image=self.image) + + # redraw + self.canvas_node.redraw() + self.destroy() diff --git a/coretk/coretk/dialogs/wlanconfig.py b/coretk/coretk/dialogs/wlanconfig.py index 85a2a18f..4f213e68 100644 --- a/coretk/coretk/dialogs/wlanconfig.py +++ b/coretk/coretk/dialogs/wlanconfig.py @@ -13,13 +13,14 @@ from coretk.dialogs.mobilityconfig import MobilityConfigDialog class WlanConfigDialog(Dialog): def __init__(self, master, app, canvas_node, config): super().__init__( - master, app, f"{canvas_node.name} Wlan Configuration", modal=True + master, app, f"{canvas_node.core_node.name} Wlan Configuration", modal=True ) self.image = canvas_node.image self.canvas_node = canvas_node + self.node = canvas_node.core_node self.config = config - self.name = tk.StringVar(value=canvas_node.name) + self.name = tk.StringVar(value=self.node.name) self.range_var = tk.StringVar(value=config["range"]) self.bandwidth_var = tk.StringVar(value=config["bandwidth"]) self.delay_var = tk.StringVar(value=config["delay"]) @@ -169,9 +170,7 @@ class WlanConfigDialog(Dialog): dialog.show() def click_icon(self): - dialog = IconDialog( - self, self.app, self.canvas_node.name, self.canvas_node.image - ) + dialog = IconDialog(self, self.app, self.node.name, self.canvas_node.image) dialog.show() if dialog.image: self.image = dialog.image @@ -192,7 +191,7 @@ class WlanConfigDialog(Dialog): # set wireless node configuration here wlanconfig_manager = self.app.core.wlanconfig_management wlanconfig_manager.set_custom_config( - node_id=self.canvas_node.core_id, + node_id=self.node.id, range=basic_range, bandwidth=bandwidth, jitter=jitter, diff --git a/coretk/coretk/graph.py b/coretk/coretk/graph.py index 38d67079..3eb002e6 100644 --- a/coretk/coretk/graph.py +++ b/coretk/coretk/graph.py @@ -155,21 +155,22 @@ class CanvasGraph(tk.Canvas): # draw nodes on the canvas image = NodeUtils.node_icon(core_node.type, core_node.model) - position = core_node.position - node = CanvasNode(position.x, position.y, image, self.master, core_node) + node = CanvasNode(self.master, core_node, image) self.nodes[node.id] = node self.core.canvas_nodes[core_node.id] = node # draw existing links for link in session.links: canvas_node_one = self.core.canvas_nodes[link.node_one_id] + node_one = canvas_node_one.core_node canvas_node_two = self.core.canvas_nodes[link.node_two_id] + node_two = canvas_node_two.core_node is_wired = link.type == core_pb2.LinkType.WIRED edge = CanvasEdge( - canvas_node_one.x_coord, - canvas_node_one.y_coord, - canvas_node_two.x_coord, - canvas_node_two.y_coord, + node_one.position.x, + node_one.position.y, + node_two.position.x, + node_two.position.y, canvas_node_one.id, self, is_wired=is_wired, @@ -402,7 +403,7 @@ class CanvasGraph(tk.Canvas): core_node = self.core.create_node( int(x), int(y), self.node_draw.node_type, self.node_draw.model ) - node = CanvasNode(x, y, self.node_draw.image, self.master, core_node) + node = CanvasNode(self.master, core_node, self.node_draw.image) self.core.canvas_nodes[core_node.id] = node self.nodes[node.id] = node return node @@ -590,19 +591,18 @@ class CanvasEdge: class CanvasNode: - def __init__(self, x, y, image, app, core_node): - self.image = image + def __init__(self, app, core_node, image): self.app = app self.canvas = app.canvas + self.image = image + self.core_node = core_node + x = self.core_node.position.x + y = self.core_node.position.y self.id = self.canvas.create_image( x, y, anchor=tk.CENTER, image=self.image, tags="node" ) - self.core_node = core_node - self.name = core_node.name - self.x_coord = x - self.y_coord = y self.text_id = self.canvas.create_text( - x, y + 20, text=self.name, tags="nodename" + x, y + 20, text=self.core_node.name, tags="nodename" ) self.antenna_draw = WlanAntennaManager(self.canvas, self.id) self.tooltip = CanvasTooltip(self.canvas) @@ -620,6 +620,10 @@ class CanvasNode: self.wlans = [] self.moving = None + def redraw(self): + self.canvas.itemconfig(self.id, image=self.image) + self.canvas.itemconfig(self.text_id, text=self.core_node.name) + def on_enter(self, event): if self.app.core.is_runtime() and self.app.core.observer: self.tooltip.text.set("waiting...") @@ -640,18 +644,18 @@ class CanvasNode: self.canvas.canvas_action.display_configuration(self) def update_coords(self): - self.x_coord, self.y_coord = self.canvas.coords(self.id) - self.core_node.position.x = int(self.x_coord) - self.core_node.position.y = int(self.y_coord) + x, y = self.canvas.coords(self.id) + self.core_node.position.x = int(x) + self.core_node.position.y = int(y) def click_press(self, event): - logging.debug(f"node click press {self.name}: {event}") + logging.debug(f"node click press {self.core_node.name}: {event}") self.moving = self.canvas.canvas_xy(event) self.canvas.canvas_management.node_select(self) def click_release(self, event): - logging.debug(f"node click release {self.name}: {event}") + logging.debug(f"node click release {self.core_node.name}: {event}") self.update_coords() self.moving = None @@ -681,7 +685,6 @@ class CanvasNode: else: self.canvas.coords(edge.id, x1, y1, new_x, new_y) edge.link_info.recalculate_info() - # self.canvas.core_grpc.throughput_draw.update_throughtput_location(edge) self.canvas.helper.update_wlan_connection( old_x, old_y, new_x, new_y, self.wlans @@ -691,4 +694,4 @@ class CanvasNode: self.canvas.canvas_management.node_select(self, True) def context(self, event): - logging.debug(f"context click {self.name}: {event}") + logging.debug(f"context click {self.core_node.name}: {event}") diff --git a/coretk/coretk/themes.py b/coretk/coretk/themes.py index 0cf54eb8..267c3a3c 100644 --- a/coretk/coretk/themes.py +++ b/coretk/coretk/themes.py @@ -85,7 +85,8 @@ def load(style): "fieldbackground": Colors.white, "foreground": Colors.black, "padding": (2, 0), - } + }, + "map": {"fieldbackground": [("disabled", Colors.frame)]}, }, "TCombobox": { "configure": {