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)
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")
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()
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)
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)
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)
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()
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)
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
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")
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))
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)
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")
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")
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
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()
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
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))
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
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)
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")
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")
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))
def icon(image_enum, width=TOOLBAR_SIZE): return Images.get(image_enum, width)
def get_icon(self, image_enum, width=TOOLBAR_SIZE): return Images.get(image_enum, int(width * self.app.app_scale))
def get_icon(self, image_enum: ImageEnum, width: int) -> PhotoImage: return Images.get(image_enum, int(width * self.app_scale))
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)
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)