def handle_edge_release(self, _event: tk.Event) -> None: edge = self.drawing_edge self.drawing_edge = None # not drawing edge return if edge is None: return # edge dst must be a node logging.debug("current selected: %s", self.selected) src_node = self.nodes.get(edge.src) dst_node = self.nodes.get(self.selected) if not dst_node or not src_node: edge.delete() return # edge dst is same as src, delete edge if edge.src == self.selected: edge.delete() return # ignore repeated edges token = create_edge_token(edge.src, self.selected) if token in self.edges: edge.delete() return # rj45 nodes can only support one link if NodeUtils.is_rj45_node(src_node.core_node.type) and src_node.edges: edge.delete() return if NodeUtils.is_rj45_node(dst_node.core_node.type) and dst_node.edges: edge.delete() return # set dst node and snap edge to center edge.complete(self.selected) self.edges[edge.token] = edge src_node.edges.add(edge) dst_node.edges.add(edge) self.core.create_link(edge, src_node, dst_node)
def handle_edge_release(self, _event: tk.Event) -> None: edge = self.drawing_edge self.drawing_edge = None # not drawing edge return if edge is None: return # edge dst must be a node logging.debug("current selected: %s", self.selected) src_node = self.nodes.get(edge.src) dst_node = self.nodes.get(self.selected) if not dst_node or not src_node: edge.delete() return # edge dst is same as src, delete edge if edge.src == self.selected: edge.delete() return # rj45 nodes can only support one link if NodeUtils.is_rj45_node(src_node.core_node.type) and src_node.edges: edge.delete() return if NodeUtils.is_rj45_node(dst_node.core_node.type) and dst_node.edges: edge.delete() return # only 1 link between bridge based nodes is_src_bridge = NodeUtils.is_bridge_node(src_node.core_node) is_dst_bridge = NodeUtils.is_bridge_node(dst_node.core_node) common_links = src_node.edges & dst_node.edges if all([is_src_bridge, is_dst_bridge, common_links]): edge.delete() return # finalize edge creation self.complete_edge(src_node, dst_node, edge)
def draw(self) -> None: self.top.columnconfigure(0, weight=1) row = 0 # field states state = tk.DISABLED if self.app.core.is_runtime() else tk.NORMAL combo_state = tk.DISABLED if self.app.core.is_runtime() else "readonly" # field frame frame = ttk.Frame(self.top) frame.grid(sticky=tk.EW) frame.columnconfigure(1, weight=1) # icon field label = ttk.Label(frame, text="Icon") label.grid(row=row, column=0, sticky=tk.EW, padx=PADX, pady=PADY) self.image_button = ttk.Button( frame, text="Icon", image=self.image, compound=tk.NONE, command=self.click_icon, ) self.image_button.grid(row=row, column=1, sticky=tk.EW) row += 1 # name field label = ttk.Label(frame, text="Name") label.grid(row=row, column=0, sticky=tk.EW, padx=PADX, pady=PADY) entry = validation.NodeNameEntry(frame, textvariable=self.name, state=state) entry.grid(row=row, column=1, sticky=tk.EW) row += 1 # node type field if NodeUtils.is_model_node(self.node.type): label = ttk.Label(frame, text="Type") label.grid(row=row, column=0, sticky=tk.EW, padx=PADX, pady=PADY) combobox = ttk.Combobox( frame, textvariable=self.type, values=list(NodeUtils.NODE_MODELS), state=combo_state, ) combobox.grid(row=row, column=1, sticky=tk.EW) row += 1 # container image field if NodeUtils.is_image_node(self.node.type): label = ttk.Label(frame, text="Image") label.grid(row=row, column=0, sticky=tk.EW, padx=PADX, pady=PADY) entry = ttk.Entry(frame, textvariable=self.container_image, state=state) entry.grid(row=row, column=1, sticky=tk.EW) row += 1 if NodeUtils.is_container_node(self.node.type): # server frame.grid(sticky=tk.EW) frame.columnconfigure(1, weight=1) label = ttk.Label(frame, text="Server") label.grid(row=row, column=0, sticky=tk.EW, padx=PADX, pady=PADY) servers = ["localhost"] servers.extend(list(sorted(self.app.core.servers.keys()))) combobox = ttk.Combobox(frame, textvariable=self.server, values=servers, state=combo_state) combobox.grid(row=row, column=1, sticky=tk.EW) row += 1 if NodeUtils.is_rj45_node(self.node.type): response = self.app.core.client.get_ifaces() logging.debug("host machine available interfaces: %s", response) ifaces = ListboxScroll(frame) ifaces.listbox.config(state=state) ifaces.grid(row=row, column=0, columnspan=2, sticky=tk.EW, padx=PADX, pady=PADY) for inf in sorted(response.ifaces[:]): ifaces.listbox.insert(tk.END, inf) row += 1 ifaces.listbox.bind("<<ListboxSelect>>", self.iface_select) # interfaces if self.canvas_node.ifaces: self.draw_ifaces() self.draw_spacer() self.draw_buttons()
def draw(self): self.top.columnconfigure(0, weight=1) row = 0 # field frame frame = ttk.Frame(self.top) frame.grid(sticky="ew") frame.columnconfigure(1, weight=1) # icon field label = ttk.Label(frame, text="Icon") label.grid(row=row, column=0, sticky="ew", padx=PADX, pady=PADY) self.image_button = ttk.Button( frame, text="Icon", image=self.image, compound=tk.NONE, command=self.click_icon, ) self.image_button.grid(row=row, column=1, sticky="ew") row += 1 # name field label = ttk.Label(frame, text="Name") label.grid(row=row, column=0, sticky="ew", padx=PADX, pady=PADY) entry = ttk.Entry( frame, textvariable=self.name, validate="key", validatecommand=(self.app.validation.name, "%P"), ) entry.bind( "<FocusOut>", lambda event: self.app.validation.focus_out(event, "noname")) entry.grid(row=row, column=1, sticky="ew") row += 1 # node type field if NodeUtils.is_model_node(self.node.type): label = ttk.Label(frame, text="Type") label.grid(row=row, column=0, sticky="ew", padx=PADX, pady=PADY) combobox = ttk.Combobox( frame, textvariable=self.type, values=list(NodeUtils.NODE_MODELS), state="readonly", ) combobox.grid(row=row, column=1, sticky="ew") row += 1 # container image field if NodeUtils.is_image_node(self.node.type): label = ttk.Label(frame, text="Image") label.grid(row=row, column=0, sticky="ew", padx=PADX, pady=PADY) entry = ttk.Entry(frame, textvariable=self.container_image) entry.grid(row=row, column=1, sticky="ew") row += 1 if NodeUtils.is_container_node(self.node.type): # server frame.grid(sticky="ew") frame.columnconfigure(1, weight=1) label = ttk.Label(frame, text="Server") label.grid(row=row, column=0, sticky="ew", padx=PADX, pady=PADY) servers = ["localhost"] servers.extend(list(sorted(self.app.core.servers.keys()))) combobox = ttk.Combobox(frame, textvariable=self.server, values=servers, state="readonly") combobox.grid(row=row, column=1, sticky="ew") row += 1 if NodeUtils.is_rj45_node(self.node.type): response = self.app.core.client.get_interfaces() logging.debug("host machine available interfaces: %s", response) interfaces = ListboxScroll(frame) interfaces.grid(row=row, column=0, columnspan=2, sticky="ew", padx=PADX, pady=PADY) for inf in sorted(response.interfaces[:]): interfaces.listbox.insert(tk.END, inf) row += 1 interfaces.listbox.bind("<<ListboxSelect>>", self.interface_select) # interfaces if self.canvas_node.interfaces: self.draw_interfaces() self.draw_spacer() self.draw_buttons()