Esempio n. 1
0
    def draw_emane_buttons(self) -> None:
        frame = ttk.Frame(self.top)
        frame.grid(sticky=tk.EW, pady=PADY)
        for i in range(2):
            frame.columnconfigure(i, weight=1)

        image = Images.get(ImageEnum.EDITNODE, 16)
        self.emane_model_button = ttk.Button(
            frame,
            text=f"{self.emane_model.get()} options",
            image=image,
            compound=tk.RIGHT,
            command=self.click_model_config,
        )
        self.emane_model_button.image = image
        self.emane_model_button.grid(row=0, column=0, padx=PADX, sticky=tk.EW)

        image = Images.get(ImageEnum.EDITNODE, 16)
        button = ttk.Button(
            frame,
            text="EMANE options",
            image=image,
            compound=tk.RIGHT,
            command=self.click_emane_config,
        )
        button.image = image
        button.grid(row=0, column=1, sticky=tk.EW)
Esempio n. 2
0
    def draw_buttons(self) -> None:
        frame = ttk.Frame(self.top)
        for i in range(4):
            frame.columnconfigure(i, weight=1)
        frame.grid(sticky="ew")

        image = Images.get(ImageEnum.DOCUMENTNEW, 16)
        b = ttk.Button(frame,
                       image=image,
                       text="New",
                       compound=tk.LEFT,
                       command=self.click_new)
        b.image = image
        b.grid(row=0, padx=PADX, sticky="ew")

        image = Images.get(ImageEnum.FILEOPEN, 16)
        self.connect_button = ttk.Button(
            frame,
            image=image,
            text="Connect",
            compound=tk.LEFT,
            command=self.click_connect,
            state=tk.DISABLED,
        )
        self.connect_button.image = image
        self.connect_button.grid(row=0, column=1, padx=PADX, sticky="ew")

        image = Images.get(ImageEnum.DELETE, 16)
        self.delete_button = ttk.Button(
            frame,
            image=image,
            text="Delete",
            compound=tk.LEFT,
            command=self.click_delete,
            state=tk.DISABLED,
        )
        self.delete_button.image = image
        self.delete_button.grid(row=0, column=2, padx=PADX, sticky="ew")

        image = Images.get(ImageEnum.CANCEL, 16)
        if self.is_start_app:
            b = ttk.Button(
                frame,
                image=image,
                text="Exit",
                compound=tk.LEFT,
                command=self.click_exit,
            )
        else:
            b = ttk.Button(
                frame,
                image=image,
                text="Cancel",
                compound=tk.LEFT,
                command=self.destroy,
            )
        b.image = image
        b.grid(row=0, column=3, sticky="ew")
Esempio n. 3
0
    def __init__(self, master: Any, app: "Application", service_name: str,
                 node_id: int):
        title = f"{service_name} Service"
        super().__init__(master, app, title, modal=True)
        self.master = master
        self.app = app
        self.core = app.core
        self.node_id = node_id
        self.service_name = service_name
        self.service_configs = app.core.service_configs
        self.file_configs = app.core.file_configs

        self.radiovar = tk.IntVar()
        self.radiovar.set(2)
        self.metadata = ""
        self.filenames = []
        self.dependencies = []
        self.executables = []
        self.startup_commands = []
        self.validation_commands = []
        self.shutdown_commands = []
        self.default_startup = []
        self.default_validate = []
        self.default_shutdown = []
        self.validation_mode = None
        self.validation_time = None
        self.validation_period = None
        self.directory_entry = None
        self.default_directories = []
        self.temp_directories = []
        self.documentnew_img = Images.get(ImageEnum.DOCUMENTNEW,
                                          int(16 * app.app_scale))
        self.editdelete_img = Images.get(ImageEnum.EDITDELETE,
                                         int(16 * app.app_scale))

        self.notebook = None
        self.metadata_entry = None
        self.filename_combobox = None
        self.dir_list = None
        self.startup_commands_listbox = None
        self.shutdown_commands_listbox = None
        self.validate_commands_listbox = None
        self.validation_time_entry = None
        self.validation_mode_entry = None
        self.service_file_data = None
        self.validation_period_entry = None
        self.original_service_files = {}
        self.default_config = None
        self.temp_service_files = {}
        self.modified_files = set()

        self.has_error = False

        self.load()
        if not self.has_error:
            self.draw()
Esempio n. 4
0
    def draw(self):
        self.top.columnconfigure(0, weight=1)

        file_name = self.config["file"].value
        label = ttk.Label(self.top, text=file_name)
        label.grid(sticky="ew", pady=PADY)

        self.progressbar = ttk.Progressbar(self.top, mode="indeterminate")
        self.progressbar.grid(sticky="ew", pady=PADY)

        frame = ttk.Frame(self.top)
        frame.grid(sticky="ew", pady=PADY)
        for i in range(3):
            frame.columnconfigure(i, weight=1)

        image = Images.get(ImageEnum.START,
                           width=int(ICON_SIZE * self.app.app_scale))
        self.play_button = ttk.Button(frame,
                                      image=image,
                                      command=self.click_play)
        self.play_button.image = image
        self.play_button.grid(row=0, column=0, sticky="ew", padx=PADX)

        image = Images.get(ImageEnum.PAUSE,
                           width=int(ICON_SIZE * self.app.app_scale))
        self.pause_button = ttk.Button(frame,
                                       image=image,
                                       command=self.click_pause)
        self.pause_button.image = image
        self.pause_button.grid(row=0, column=1, sticky="ew", padx=PADX)

        image = Images.get(ImageEnum.STOP,
                           width=int(ICON_SIZE * self.app.app_scale))
        self.stop_button = ttk.Button(frame,
                                      image=image,
                                      command=self.click_stop)
        self.stop_button.image = image
        self.stop_button.grid(row=0, column=2, sticky="ew", padx=PADX)

        loop = tk.IntVar(value=int(self.config["loop"].value == "1"))
        checkbutton = ttk.Checkbutton(frame,
                                      text="Loop?",
                                      variable=loop,
                                      state=tk.DISABLED)
        checkbutton.grid(row=0, column=3, padx=PADX)

        rate = self.config["refresh_ms"].value
        label = ttk.Label(frame, text=f"rate {rate} ms")
        label.grid(row=0, column=4)
Esempio n. 5
0
    def setup(cls):
        nodes = [
            (ImageEnum.ROUTER, NodeType.DEFAULT, "Router", "router"),
            (ImageEnum.HOST, NodeType.DEFAULT, "Host", "host"),
            (ImageEnum.PC, NodeType.DEFAULT, "PC", "PC"),
            (ImageEnum.MDR, NodeType.DEFAULT, "MDR", "mdr"),
            (ImageEnum.PROUTER, NodeType.DEFAULT, "PRouter", "prouter"),
            (ImageEnum.DOCKER, NodeType.DOCKER, "Docker", None),
            (ImageEnum.LXC, NodeType.LXC, "LXC", None),
        ]
        for image_enum, node_type, label, model in nodes:
            node_draw = NodeDraw.from_setup(image_enum, node_type, label, model)
            cls.NODES.append(node_draw)
            cls.NODE_ICONS[(node_type, model)] = node_draw.image

        network_nodes = [
            (ImageEnum.HUB, NodeType.HUB, "Hub"),
            (ImageEnum.SWITCH, NodeType.SWITCH, "Switch"),
            (ImageEnum.WLAN, NodeType.WIRELESS_LAN, "WLAN"),
            (ImageEnum.EMANE, NodeType.EMANE, "EMANE"),
            (ImageEnum.RJ45, NodeType.RJ45, "RJ45"),
            (ImageEnum.TUNNEL, NodeType.TUNNEL, "Tunnel"),
        ]
        for image_enum, node_type, label in network_nodes:
            node_draw = NodeDraw.from_setup(image_enum, node_type, label)
            cls.NETWORK_NODES.append(node_draw)
            cls.NODE_ICONS[(node_type, None)] = node_draw.image
        cls.ANTENNA_ICON = Images.get(ImageEnum.ANTENNA, ANTENNA_SIZE)
Esempio n. 6
0
    def draw_emane_configuration(self) -> None:
        """
        draw the main frame for emane configuration
        """
        label = ttk.Label(
            self.top,
            text=
            "The EMANE emulation system provides more complex wireless radio "
            "emulation \nusing pluggable MAC and PHY modules. Refer to the wiki "
            "for configuration option details",
            justify=tk.CENTER,
        )
        label.grid(pady=PADY)

        image = Images.get(ImageEnum.EDITNODE, 16)
        button = ttk.Button(
            self.top,
            image=image,
            text="EMANE Wiki",
            compound=tk.RIGHT,
            command=lambda: webbrowser.open_new(
                "https://github.com/adjacentlink/emane/wiki"),
        )
        button.image = image
        button.grid(sticky=tk.EW, pady=PADY)
Esempio n. 7
0
 def setup_app(self) -> None:
     self.master.title("CORE")
     self.center()
     self.master.protocol("WM_DELETE_WINDOW", self.on_closing)
     image = Images.get(ImageEnum.CORE, 16)
     self.master.tk.call("wm", "iconphoto", self.master._w, image)
     self.master.option_add("*tearOff", tk.FALSE)
     self.setup_file_dialogs()
Esempio n. 8
0
 def setup_app(self):
     self.master.title("CORE")
     self.center()
     self.master.protocol("WM_DELETE_WINDOW", self.on_closing)
     image = Images.get(ImageEnum.CORE, 16)
     self.master.tk.call("wm", "iconphoto", self.master._w, image)
     self.pack(fill=tk.BOTH, expand=True)
     self.validation = InputValidation(self)
Esempio n. 9
0
 def from_setup(cls, image_enum, node_type, label, model=None, tooltip=None):
     node_draw = NodeDraw()
     node_draw.image_enum = image_enum
     node_draw.image = Images.get(image_enum, ICON_SIZE)
     node_draw.node_type = node_type
     node_draw.label = label
     node_draw.model = model
     node_draw.tooltip = tooltip
     return node_draw
Esempio n. 10
0
 def draw(self):
     self.top.columnconfigure(0, weight=1)
     self.top.rowconfigure(0, weight=1)
     image = Images.get(ImageEnum.ERROR, 36)
     label = ttk.Label(self.top, image=image)
     label.image = image
     label.grid(row=0, column=0)
     self.error_message = CodeText(self.top)
     self.error_message.text.insert("1.0", self.details)
     self.error_message.text.config(state="disabled")
     self.error_message.grid(row=1, column=0, sticky="nsew")
Esempio n. 11
0
    def node_icon(
        cls, node_type: NodeType, model: str, gui_config: GuiConfig, scale: float = 1.0
    ) -> PhotoImage:

        image_enum = TypeToImage.get(node_type, model)
        if image_enum:
            return Images.get(image_enum, int(ICON_SIZE * scale))
        else:
            image_stem = cls.get_image_file(gui_config, model)
            if image_stem:
                return Images.get_with_image_file(image_stem, int(ICON_SIZE * scale))
Esempio n. 12
0
File: node.py Progetto: lsh23/core
 def scale_antennas(self):
     for i in range(len(self.antennas)):
         antenna_id = self.antennas[i]
         image = Images.get(ImageEnum.ANTENNA,
                            int(ANTENNA_SIZE * self.app.app_scale))
         self.canvas.itemconfig(antenna_id, image=image)
         self.antenna_images[antenna_id] = image
         node_x, node_y = self.canvas.coords(self.id)
         x, y = self.canvas.coords(antenna_id)
         dx = node_x - 16 + (i * 8 * self.app.app_scale) - x
         dy = node_y - int(23 * self.app.app_scale) - y
         self.canvas.move(antenna_id, dx, dy)
Esempio n. 13
0
    def draw_buttons(self):
        frame = ttk.Frame(self.top)
        for i in range(4):
            frame.columnconfigure(i, weight=1)
        frame.grid(sticky="ew")

        image = Images.get(ImageEnum.DOCUMENTNEW, 16)
        b = ttk.Button(frame,
                       image=image,
                       text="New",
                       compound=tk.LEFT,
                       command=self.click_new)
        b.image = image
        b.grid(row=0, padx=PADX, sticky="ew")

        image = Images.get(ImageEnum.FILEOPEN, 16)
        b = ttk.Button(
            frame,
            image=image,
            text="Connect",
            compound=tk.LEFT,
            command=self.click_connect,
        )
        b.image = image
        b.grid(row=0, column=1, padx=PADX, sticky="ew")

        image = Images.get(ImageEnum.EDITDELETE, 16)
        b = ttk.Button(
            frame,
            image=image,
            text="Shutdown",
            compound=tk.LEFT,
            command=self.click_shutdown,
        )
        b.image = image
        b.grid(row=0, column=2, padx=PADX, sticky="ew")

        b = ttk.Button(frame, text="Cancel", command=self.click_new)
        b.grid(row=0, column=3, sticky="ew")
Esempio n. 14
0
 def __init__(self, master, app, title, modal=False):
     super().__init__(master)
     self.withdraw()
     self.app = app
     self.modal = modal
     self.title(title)
     self.protocol("WM_DELETE_WINDOW", self.destroy)
     image = Images.get(ImageEnum.CORE, 16)
     self.tk.call("wm", "iconphoto", self._w, image)
     self.columnconfigure(0, weight=1)
     self.rowconfigure(0, weight=1)
     self.top = ttk.Frame(self, padding=DIALOG_PAD)
     self.top.grid(sticky="nsew")
Esempio n. 15
0
File: node.py Progetto: lyma/core
 def add_antenna(self):
     x, y = self.canvas.coords(self.id)
     offset = len(self.antennas) * 8 * self.app.app_scale
     img = Images.get(ImageEnum.ANTENNA, int(ANTENNA_SIZE * self.app.app_scale))
     antenna_id = self.canvas.create_image(
         x - 16 + offset,
         y - int(23 * self.app.app_scale),
         anchor=tk.CENTER,
         image=img,
         tags=tags.ANTENNA,
     )
     self.antennas.append(antenna_id)
     self.antenna_images[antenna_id] = img
Esempio n. 16
0
    def __init__(self, master, app, service_name, node_id):
        title = f"{service_name} Service"
        super().__init__(master, app, title, modal=True)
        self.app = app
        self.core = app.core
        self.node_id = node_id
        self.service_name = service_name
        self.radiovar = tk.IntVar()
        self.radiovar.set(2)
        self.metadata = ""
        self.filenames = []
        self.dependencies = []
        self.executables = []
        self.startup_commands = []
        self.validation_commands = []
        self.shutdown_commands = []
        self.validation_mode = None
        self.validation_time = None
        self.validation_period = None
        self.documentnew_img = Images.get(ImageEnum.DOCUMENTNEW, 16)
        self.editdelete_img = Images.get(ImageEnum.EDITDELETE, 16)

        self.notebook = None
        self.metadata_entry = None
        self.filename_combobox = None
        self.startup_commands_listbox = None
        self.shutdown_commands_listbox = None
        self.validate_commands_listbox = None
        self.validation_time_entry = None
        self.validation_mode_entry = None
        self.service_file_data = None
        self.validation_period_entry = None
        self.original_service_files = {}
        self.temp_service_files = {}
        self.modified_files = set()
        self.load()
        self.draw()
Esempio n. 17
0
 def from_setup(
     cls,
     image_enum: ImageEnum,
     node_type: "core_pb2.NodeType",
     label: str,
     model: str = None,
     tooltip=None,
 ):
     node_draw = NodeDraw()
     node_draw.image_enum = image_enum
     node_draw.image = Images.get(image_enum, ICON_SIZE)
     node_draw.node_type = node_type
     node_draw.label = label
     node_draw.model = model
     node_draw.tooltip = tooltip
     return node_draw
Esempio n. 18
0
    def node_icon(
        cls,
        node_type: NodeType,
        model: str,
        gui_config: Dict[str, List[Dict[str, str]]],
        scale=1.0,
    ) -> "ImageTk.PhotoImage":

        image_enum = TypeToImage.get(node_type, model)
        if image_enum:
            return Images.get(image_enum, int(ICON_SIZE * scale))
        else:
            image_stem = cls.get_image_file(gui_config, model)
            if image_stem:
                return Images.get_with_image_file(image_stem,
                                                  int(ICON_SIZE * scale))
Esempio n. 19
0
 def add_node(self, x: float, y: float) -> None:
     if self.selected is not None and self.selected not in self.shapes:
         return
     actual_x, actual_y = self.get_actual_coords(x, y)
     core_node = self.core.create_node(actual_x, actual_y,
                                       self.node_draw.node_type,
                                       self.node_draw.model)
     if not core_node:
         return
     try:
         self.node_draw.image = Images.get(
             self.node_draw.image_enum, int(ICON_SIZE * self.app.app_scale))
     except AttributeError:
         self.node_draw.image = Images.get_custom(
             self.node_draw.image_file, int(ICON_SIZE * self.app.app_scale))
     node = CanvasNode(self.app, x, y, core_node, self.node_draw.image)
     self.core.canvas_nodes[core_node.id] = node
     self.nodes[node.id] = node
Esempio n. 20
0
File: error.py Progetto: umr-ds/core
 def draw(self) -> None:
     self.top.columnconfigure(0, weight=1)
     self.top.rowconfigure(1, weight=1)
     image = Images.get(ImageEnum.ERROR, 24)
     label = ttk.Label(self.top,
                       text=self.title,
                       image=image,
                       compound=tk.LEFT,
                       anchor=tk.CENTER)
     label.image = image
     label.grid(sticky=tk.EW, pady=PADY)
     self.error_message = CodeText(self.top)
     self.error_message.text.insert("1.0", self.details)
     self.error_message.text.config(state=tk.DISABLED)
     self.error_message.grid(sticky=tk.NSEW, pady=PADY)
     button = ttk.Button(self.top,
                         text="Close",
                         command=lambda: self.destroy())
     button.grid(sticky=tk.EW)
Esempio n. 21
0
 def __init__(
     self,
     app: "Application",
     title: str,
     modal: bool = True,
     master: tk.BaseWidget = None,
 ):
     if master is None:
         master = app
     super().__init__(master)
     self.withdraw()
     self.app = app
     self.modal = modal
     self.title(title)
     self.protocol("WM_DELETE_WINDOW", self.destroy)
     image = Images.get(ImageEnum.CORE, 16)
     self.tk.call("wm", "iconphoto", self._w, image)
     self.columnconfigure(0, weight=1)
     self.rowconfigure(0, weight=1)
     self.top = ttk.Frame(self, padding=DIALOG_PAD)
     self.top.grid(sticky="nsew")
Esempio n. 22
0
    def draw(self) -> None:
        self.top.columnconfigure(0, weight=1)
        self.top.rowconfigure(1, weight=1)

        frame = ttk.Frame(self.top, padding=FRAME_PAD)
        frame.grid(pady=PADY, sticky="ew")
        frame.columnconfigure(1, weight=1)
        image = Images.get(ImageEnum.ERROR, 36)
        label = ttk.Label(frame, image=image)
        label.image = image
        label.grid(row=0, column=0, padx=PADX)
        label = ttk.Label(frame, text=self.title)
        label.grid(row=0, column=1, sticky="ew")

        self.error_message = CodeText(self.top)
        self.error_message.text.insert("1.0", self.details)
        self.error_message.text.config(state="disabled")
        self.error_message.grid(sticky="nsew", pady=PADY)

        button = ttk.Button(self.top,
                            text="Close",
                            command=lambda: self.destroy())
        button.grid(sticky="ew")
Esempio n. 23
0
    def scale_graph(self):
        for nid, canvas_node in self.nodes.items():
            img = None
            if NodeUtils.is_custom(canvas_node.core_node.type,
                                   canvas_node.core_node.model):
                for custom_node in self.app.guiconfig.nodes:
                    if custom_node.name == canvas_node.core_node.model:
                        img = Images.get_custom(
                            custom_node.image,
                            int(ICON_SIZE * self.app.app_scale))
            else:
                image_enum = TypeToImage.get(canvas_node.core_node.type,
                                             canvas_node.core_node.model)
                img = Images.get(image_enum,
                                 int(ICON_SIZE * self.app.app_scale))

            self.itemconfig(nid, image=img)
            canvas_node.image = img
            canvas_node.scale_text()
            canvas_node.scale_antennas()

            for edge_id in self.find_withtag(tags.EDGE):
                self.itemconfig(edge_id,
                                width=int(EDGE_WIDTH * self.app.app_scale))
Esempio n. 24
0
def icon(image_enum, width=TOOLBAR_SIZE):
    return Images.get(image_enum, width)
Esempio n. 25
0
 def get_icon(self, image_enum, width=TOOLBAR_SIZE):
     return Images.get(image_enum, int(width * self.app.app_scale))
Esempio n. 26
0
 def get_icon(self, image_enum: ImageEnum, width: int) -> PhotoImage:
     return Images.get(image_enum, int(width * self.app_scale))
Esempio n. 27
0
    def draw_tab_files(self) -> None:
        tab = ttk.Frame(self.notebook, padding=FRAME_PAD)
        tab.grid(sticky=tk.NSEW)
        tab.columnconfigure(0, weight=1)
        self.notebook.add(tab, text="Files")

        label = ttk.Label(
            tab,
            text="Config files and scripts that are generated for this service."
        )
        label.grid()

        frame = ttk.Frame(tab)
        frame.grid(sticky=tk.EW, pady=PADY)
        frame.columnconfigure(1, weight=1)
        label = ttk.Label(frame, text="File Name")
        label.grid(row=0, column=0, padx=PADX, sticky=tk.W)
        self.filename_combobox = ttk.Combobox(frame, values=self.filenames)
        self.filename_combobox.bind("<<ComboboxSelected>>",
                                    self.display_service_file_data)
        self.filename_combobox.grid(row=0, column=1, sticky=tk.EW, padx=PADX)
        button = ttk.Button(frame,
                            image=self.documentnew_img,
                            command=self.add_filename)
        button.grid(row=0, column=2, padx=PADX)
        button = ttk.Button(frame,
                            image=self.editdelete_img,
                            command=self.delete_filename)
        button.grid(row=0, column=3)

        frame = ttk.Frame(tab)
        frame.grid(sticky=tk.EW, pady=PADY)
        frame.columnconfigure(1, weight=1)
        button = ttk.Radiobutton(
            frame,
            variable=self.radiovar,
            text="Copy Source File",
            value=1,
            state=tk.DISABLED,
        )
        button.grid(row=0, column=0, sticky=tk.W, padx=PADX)
        entry = ttk.Entry(frame, state=tk.DISABLED)
        entry.grid(row=0, column=1, sticky=tk.EW, padx=PADX)
        image = Images.get(ImageEnum.FILEOPEN, 16)
        button = ttk.Button(frame, image=image)
        button.image = image
        button.grid(row=0, column=2)

        frame = ttk.Frame(tab)
        frame.grid(sticky=tk.EW, pady=PADY)
        frame.columnconfigure(0, weight=1)
        button = ttk.Radiobutton(
            frame,
            variable=self.radiovar,
            text="Use text below for file contents",
            value=2,
        )
        button.grid(row=0, column=0, sticky=tk.EW)
        image = Images.get(ImageEnum.FILEOPEN, 16)
        button = ttk.Button(frame, image=image)
        button.image = image
        button.grid(row=0, column=1)
        image = Images.get(ImageEnum.DOCUMENTSAVE, 16)
        button = ttk.Button(frame, image=image)
        button.image = image
        button.grid(row=0, column=2)

        self.service_file_data = CodeText(tab)
        self.service_file_data.grid(sticky=tk.NSEW)
        tab.rowconfigure(self.service_file_data.grid_info()["row"], weight=1)
        if len(self.filenames) > 0:
            self.filename_combobox.current(0)
            self.service_file_data.text.delete(1.0, "end")
            self.service_file_data.text.insert(
                "end", self.temp_service_files[self.filenames[0]])
        self.service_file_data.text.bind("<FocusOut>",
                                         self.update_temp_service_file_data)
Esempio n. 28
0
    def draw_session(self, session: core_pb2.Session):
        """
        Draw existing session.
        """
        # draw existing nodes
        for core_node in session.nodes:
            logging.debug("drawing node %s", core_node)
            # peer to peer node is not drawn on the GUI
            if NodeUtils.is_ignore_node(core_node.type):
                continue
            image = NodeUtils.node_image(core_node, self.app.guiconfig,
                                         self.app.app_scale)
            # if the gui can't find node's image, default to the "edit-node" image
            if not image:
                image = Images.get(ImageEnum.EDITNODE,
                                   int(ICON_SIZE * self.app.app_scale))
            x = core_node.position.x
            y = core_node.position.y
            node = CanvasNode(self.app, x, y, core_node, image)
            self.nodes[node.id] = node
            self.core.canvas_nodes[core_node.id] = node

        # draw existing links
        for link in session.links:
            logging.debug("drawing link: %s", link)
            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
            token = create_edge_token(canvas_node_one.id, canvas_node_two.id)

            if link.type == core_pb2.LinkType.WIRELESS:
                self.add_wireless_edge(canvas_node_one, canvas_node_two, link)
            else:
                if token not in self.edges:
                    src_pos = (node_one.position.x, node_one.position.y)
                    dst_pos = (node_two.position.x, node_two.position.y)
                    edge = CanvasEdge(self, canvas_node_one.id, src_pos,
                                      dst_pos)
                    edge.token = token
                    edge.dst = canvas_node_two.id
                    edge.set_link(link)
                    edge.check_wireless()
                    canvas_node_one.edges.add(edge)
                    canvas_node_two.edges.add(edge)
                    self.edges[edge.token] = edge
                    self.core.links[edge.token] = edge
                    if link.HasField("interface_one"):
                        canvas_node_one.interfaces.append(link.interface_one)
                        edge.src_interface = link.interface_one
                    if link.HasField("interface_two"):
                        canvas_node_two.interfaces.append(link.interface_two)
                        edge.dst_interface = link.interface_two
                elif link.options.unidirectional:
                    edge = self.edges[token]
                    edge.asymmetric_link = link
                else:
                    logging.error("duplicate link received: %s", link)

        # raise the nodes so they on top of the links
        self.tag_raise(tags.NODE)