def draw_node_picker(self): self.hide_pickers() self.node_picker = ttk.Frame(self.master) # draw default nodes for node_draw in NodeUtils.NODES: toolbar_image = icon(node_draw.image_enum) image = icon(node_draw.image_enum, PICKER_SIZE) func = partial(self.update_button, self.node_button, toolbar_image, node_draw) self.create_picker_button(image, func, self.node_picker, node_draw.label) # draw custom nodes for name in sorted(self.app.core.custom_nodes): node_draw = self.app.core.custom_nodes[name] toolbar_image = Images.get_custom(node_draw.image_file, TOOLBAR_SIZE) image = Images.get_custom(node_draw.image_file, PICKER_SIZE) func = partial(self.update_button, self.node_button, toolbar_image, node_draw) self.create_picker_button(image, func, self.node_picker, name) # draw edit node image = icon(ImageEnum.EDITNODE, PICKER_SIZE) self.create_picker_button(image, self.click_edit_node, self.node_picker, "Custom") self.design_select(self.node_button) self.node_button.after( 0, lambda: self.show_picker(self.node_button, self.node_picker))
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 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 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 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 update_icon(self, icon_path: str) -> None: if not Path(icon_path).exists(): logging.error(f"node icon does not exist: {icon_path}") return self.core_node.icon = icon_path self.image = Images.create(icon_path, nodeutils.ICON_SIZE) self.canvas.itemconfig(self.id, image=self.image)
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 click_icon(self) -> None: file_path = image_chooser(self, ICONS_PATH) if file_path: image = Images.create(file_path, nodeutils.ICON_SIZE) self.image = image self.image_file = file_path self.image_button.config(image=self.image)
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): 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 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 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 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 node_image( cls, core_node: Node, gui_config: GuiConfig, scale: float = 1.0 ) -> PhotoImage: image = cls.node_icon(core_node.type, core_node.model, gui_config, scale) if core_node.icon: try: image = Images.create(core_node.icon, int(ICON_SIZE * scale)) except OSError: logging.error("invalid icon: %s", core_node.icon) return image
def node_image( cls, core_node: "core_pb2.Node", gui_config: Dict[str, List[Dict[str, str]]]) -> "ImageTk.PhotoImage": image = cls.node_icon(core_node.type, core_node.model, gui_config) if core_node.icon: try: image = Images.create(core_node.icon, ICON_SIZE) except OSError: logging.error("invalid icon: %s", core_node.icon) return image
def from_custom(cls, name, image_file, services): node_draw = NodeDraw() node_draw.custom = True node_draw.image_file = image_file node_draw.image = Images.get_custom(image_file, ICON_SIZE) node_draw.node_type = NodeType.DEFAULT node_draw.services = services node_draw.label = name node_draw.model = name node_draw.tooltip = name 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 from_custom(cls, custom_node: CustomNode) -> "NodeDraw": node_draw = NodeDraw() node_draw.custom = True node_draw.image_file = custom_node.image node_draw.image = Images.get_custom(custom_node.image, ICON_SIZE) node_draw.node_type = NodeType.DEFAULT node_draw.services = custom_node.services node_draw.label = custom_node.name node_draw.model = custom_node.name node_draw.tooltip = custom_node.name return node_draw
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 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 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 __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 node_icon( cls, node_type: NodeType, model: str, gui_config: Dict[str, List[Dict[str, str]]], ) -> "ImageTk.PhotoImage": if model == "": model = None try: image = cls.NODE_ICONS[(node_type, model)] return image except KeyError: image_stem = cls.get_image_file(gui_config, model) if image_stem: return Images.get_with_image_file(image_stem, ICON_SIZE)
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 draw_node_picker(self): self.hide_pickers() self.node_picker = ttk.Frame(self.master) # draw default nodes for node_draw in NodeUtils.NODES: toolbar_image = self.get_icon(node_draw.image_enum, TOOLBAR_SIZE) image = self.get_icon(node_draw.image_enum, PICKER_SIZE) func = partial( self.update_button, self.node_button, toolbar_image, node_draw, NodeTypeEnum.NODE, node_draw.image_enum, ) self.create_picker_button(image, func, self.node_picker, node_draw.label) # draw custom nodes for name in sorted(self.app.core.custom_nodes): node_draw = self.app.core.custom_nodes[name] toolbar_image = Images.get_custom( node_draw.image_file, int(TOOLBAR_SIZE * self.app.app_scale)) image = Images.get_custom(node_draw.image_file, int(PICKER_SIZE * self.app.app_scale)) func = partial( self.update_button, self.node_button, toolbar_image, node_draw, NodeTypeEnum, node_draw.image_file, ) self.create_picker_button(image, func, self.node_picker, name) self.design_select(self.node_button) self.node_button.after( 0, lambda: self.show_picker(self.node_button, self.node_picker))
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 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)