pygui: fix redrawing edge labels for multiple canvases, updated edit menu to account for multiple canvases, fixed issue with not setting menubar state when joining a session, starting point for hide/show nodes and related edges

This commit is contained in:
Blake Harnden 2021-01-08 10:10:46 -08:00
parent bc540e0669
commit 35cc8fab65
8 changed files with 83 additions and 23 deletions

View file

@ -189,8 +189,10 @@ class Application(ttk.Frame):
def joined_session_update(self) -> None: def joined_session_update(self) -> None:
if self.core.is_runtime(): if self.core.is_runtime():
self.menubar.set_state(is_runtime=True)
self.toolbar.set_runtime() self.toolbar.set_runtime()
else: else:
self.menubar.set_state(is_runtime=False)
self.toolbar.set_design() self.toolbar.set_design()
def get_icon(self, image_enum: ImageEnum, width: int) -> PhotoImage: def get_icon(self, image_enum: ImageEnum, width: int) -> PhotoImage:

View file

@ -634,10 +634,10 @@ class CanvasEdge(Edge):
if not self.linked_wireless: if not self.linked_wireless:
return return
if self.id: if self.id:
# self.src.canvas.itemconfig(self.id, state=tk.HIDDEN) self.src.canvas.itemconfig(self.id, state=tk.HIDDEN)
self.src.canvas.dtag(self.id, tags.EDGE) self.src.canvas.dtag(self.id, tags.EDGE)
if self.id2: if self.id2:
# self.dst.canvas.itemconfig(self.id2, state=tk.HIDDEN) self.dst.canvas.itemconfig(self.id2, state=tk.HIDDEN)
self.dst.canvas.dtag(self.id2, tags.EDGE) self.dst.canvas.dtag(self.id2, tags.EDGE)
# add antenna to node # add antenna to node
if self.src.is_wireless() and not self.dst.is_wireless(): if self.src.is_wireless() and not self.dst.is_wireless():

View file

@ -306,6 +306,32 @@ class CanvasGraph(tk.Canvas):
self.selection.clear() self.selection.clear()
self.core.deleted_canvas_nodes(nodes) self.core.deleted_canvas_nodes(nodes)
def hide_selected_objects(self) -> None:
edges = set()
for object_id in self.selection:
# delete selection box
selection_id = self.selection[object_id]
self.delete(selection_id)
# hide node and related edges
if object_id in self.nodes:
canvas_node = self.nodes[object_id]
canvas_node.hide()
# hide related edges
for edge in canvas_node.edges:
if edge in edges:
continue
edges.add(edge)
def show_hidden(self) -> None:
edges = set()
for node in self.nodes.values():
node.show()
for edge in node.edges:
if edge in edges:
continue
edges.add(edge)
def zoom(self, event: tk.Event, factor: float = None) -> None: def zoom(self, event: tk.Event, factor: float = None) -> None:
if not factor: if not factor:
factor = ZOOM_IN if event.delta > 0 else ZOOM_OUT factor = ZOOM_IN if event.delta > 0 else ZOOM_OUT

View file

@ -165,8 +165,16 @@ class CanvasManager:
unique_id = self.notebook.select() unique_id = self.notebook.select()
self.notebook.forget(unique_id) self.notebook.forget(unique_id)
canvas_id = self.canvas_ids.pop(unique_id) canvas_id = self.canvas_ids.pop(unique_id)
self.canvases.pop(canvas_id) canvas = self.canvases.pop(canvas_id)
# TODO: handle clearing out canvas related nodes and links from core client edges = set()
for node in canvas.nodes.values():
node.delete()
while node.edges:
edge = node.edges.pop()
if edge in edges:
continue
edges.add(edge)
edge.delete()
def join(self, session: Session) -> None: def join(self, session: Session) -> None:
# clear out all canvas # clear out all canvas

View file

@ -63,6 +63,7 @@ class CanvasNode:
self.wireless_edges: Set[CanvasWirelessEdge] = set() self.wireless_edges: Set[CanvasWirelessEdge] = set()
self.antennas: List[int] = [] self.antennas: List[int] = []
self.antenna_images: Dict[int, PhotoImage] = {} self.antenna_images: Dict[int, PhotoImage] = {}
self.hidden: bool = False
self.setup_bindings() self.setup_bindings()
self.context: tk.Menu = tk.Menu(self.canvas) self.context: tk.Menu = tk.Menu(self.canvas)
themes.style_menu(self.context) themes.style_menu(self.context)
@ -409,3 +410,13 @@ class CanvasNode:
def is_wireless(self) -> bool: def is_wireless(self) -> bool:
return NodeUtils.is_wireless_node(self.core_node.type) return NodeUtils.is_wireless_node(self.core_node.type)
def hide(self) -> None:
self.hidden = True
self.canvas.itemconfig(self.id, state=tk.HIDDEN)
self.canvas.itemconfig(self.text_id, state=tk.HIDDEN)
def show(self) -> None:
self.hidden = False
self.canvas.itemconfig(self.id, state=tk.NORMAL)
self.canvas.itemconfig(self.text_id, state=tk.NORMAL)

View file

@ -14,6 +14,7 @@ NODE: str = "node"
WALLPAPER: str = "wallpaper" WALLPAPER: str = "wallpaper"
SELECTION: str = "selectednodes" SELECTION: str = "selectednodes"
MARKER: str = "marker" MARKER: str = "marker"
HIDDEN: str = "hidden"
ORGANIZE_TAGS: List[str] = [ ORGANIZE_TAGS: List[str] = [
WALLPAPER, WALLPAPER,
GRIDLINE, GRIDLINE,

View file

@ -48,6 +48,7 @@ class Menubar(tk.Menu):
self.manager: CanvasManager = app.manager self.manager: CanvasManager = app.manager
self.recent_menu: Optional[tk.Menu] = None self.recent_menu: Optional[tk.Menu] = None
self.edit_menu: Optional[tk.Menu] = None self.edit_menu: Optional[tk.Menu] = None
self.canvas_menu: Optional[tk.Menu] = None
self.observers_menu: Optional[ObserversMenu] = None self.observers_menu: Optional[ObserversMenu] = None
self.draw() self.draw()
@ -106,6 +107,7 @@ class Menubar(tk.Menu):
menu = tk.Menu(self) menu = tk.Menu(self)
menu.add_command(label="Preferences", command=self.click_preferences) menu.add_command(label="Preferences", command=self.click_preferences)
menu.add_command(label="Custom Nodes", command=self.click_custom_nodes) menu.add_command(label="Custom Nodes", command=self.click_custom_nodes)
menu.add_command(label="Show Hidden Nodes", command=self.click_show_hidden)
menu.add_separator() menu.add_separator()
menu.add_command(label="Undo", accelerator="Ctrl+Z", state=tk.DISABLED) menu.add_command(label="Undo", accelerator="Ctrl+Z", state=tk.DISABLED)
menu.add_command(label="Redo", accelerator="Ctrl+Y", state=tk.DISABLED) menu.add_command(label="Redo", accelerator="Ctrl+Y", state=tk.DISABLED)
@ -116,11 +118,13 @@ class Menubar(tk.Menu):
menu.add_command( menu.add_command(
label="Delete", accelerator="Ctrl+D", command=self.click_delete label="Delete", accelerator="Ctrl+D", command=self.click_delete
) )
menu.add_command(label="Hide", accelerator="Ctrl+H", command=self.click_hide)
self.add_cascade(label="Edit", menu=menu) self.add_cascade(label="Edit", menu=menu)
self.app.master.bind_all("<Control-x>", self.click_cut) self.app.master.bind_all("<Control-x>", self.click_cut)
self.app.master.bind_all("<Control-c>", self.click_copy) self.app.master.bind_all("<Control-c>", self.click_copy)
self.app.master.bind_all("<Control-v>", self.click_paste) self.app.master.bind_all("<Control-v>", self.click_paste)
self.app.master.bind_all("<Control-d>", self.click_delete) self.app.master.bind_all("<Control-d>", self.click_delete)
self.app.master.bind_all("<Control-h>", self.click_hide)
self.edit_menu = menu self.edit_menu = menu
def draw_canvas_menu(self) -> None: def draw_canvas_menu(self) -> None:
@ -134,6 +138,7 @@ class Menubar(tk.Menu):
menu.add_command(label="Delete", command=self.click_canvas_delete) menu.add_command(label="Delete", command=self.click_canvas_delete)
menu.add_command(label="Wallpaper", command=self.click_canvas_wallpaper) menu.add_command(label="Wallpaper", command=self.click_canvas_wallpaper)
self.add_cascade(label="Canvas", menu=menu) self.add_cascade(label="Canvas", menu=menu)
self.canvas_menu = menu
def draw_view_menu(self) -> None: def draw_view_menu(self) -> None:
""" """
@ -337,17 +342,12 @@ class Menubar(tk.Menu):
self.app.save_config() self.app.save_config()
self.app.menubar.update_recent_files() self.app.menubar.update_recent_files()
def change_menubar_item_state(self, is_runtime: bool) -> None: def set_state(self, is_runtime: bool) -> None:
labels = {"Copy", "Paste", "Delete", "Cut"}
for i in range(self.edit_menu.index(tk.END) + 1):
try:
label = self.edit_menu.entrycget(i, "label")
if label not in labels:
continue
state = tk.DISABLED if is_runtime else tk.NORMAL state = tk.DISABLED if is_runtime else tk.NORMAL
self.edit_menu.entryconfig(i, state=state) for entry in {"Copy", "Paste", "Delete", "Cut"}:
except tk.TclError: self.edit_menu.entryconfigure(entry, state=state)
pass for entry in {"Delete"}:
self.canvas_menu.entryconfigure(entry, state=state)
def prompt_save_running_session(self, quit_app: bool = False) -> None: def prompt_save_running_session(self, quit_app: bool = False) -> None:
""" """
@ -410,17 +410,29 @@ class Menubar(tk.Menu):
dialog.show() dialog.show()
def click_copy(self, _event: tk.Event = None) -> None: def click_copy(self, _event: tk.Event = None) -> None:
self.canvas.copy() canvas = self.manager.current()
canvas.copy()
def click_paste(self, _event: tk.Event = None) -> None: def click_paste(self, _event: tk.Event = None) -> None:
self.canvas.paste() canvas = self.manager.current()
canvas.paste()
def click_delete(self, _event: tk.Event = None) -> None: def click_delete(self, _event: tk.Event = None) -> None:
self.canvas.delete_selected_objects() canvas = self.manager.current()
canvas.delete_selected_objects()
def click_hide(self, _event: tk.Event = None) -> None:
canvas = self.manager.current()
canvas.hide_selected_objects()
def click_cut(self, _event: tk.Event = None) -> None: def click_cut(self, _event: tk.Event = None) -> None:
self.canvas.copy() canvas = self.manager.current()
self.canvas.delete_selected_objects() canvas.copy()
canvas.delete_selected_objects()
def click_show_hidden(self, _event: tk.Event = None) -> None:
canvas = self.manager.current()
canvas.show_hidden()
def click_session_options(self) -> None: def click_session_options(self) -> None:
logging.debug("Click options") logging.debug("Click options")
@ -470,7 +482,7 @@ class Menubar(tk.Menu):
self.app.hide_info() self.app.hide_info()
def click_edge_label_change(self) -> None: def click_edge_label_change(self) -> None:
for edge in self.canvas.edges.values(): for edge in self.manager.edges.values():
edge.draw_labels() edge.draw_labels()
def click_mac_config(self) -> None: def click_mac_config(self) -> None:

View file

@ -292,7 +292,7 @@ class Toolbar(ttk.Frame):
Start session handler redraw buttons, send node and link messages to grpc Start session handler redraw buttons, send node and link messages to grpc
server. server.
""" """
self.app.menubar.change_menubar_item_state(is_runtime=True) self.app.menubar.set_state(is_runtime=True)
self.app.manager.mode = GraphMode.SELECT self.app.manager.mode = GraphMode.SELECT
enable_buttons(self.design_frame, enabled=False) enable_buttons(self.design_frame, enabled=False)
task = ProgressTask( task = ProgressTask(
@ -397,7 +397,7 @@ class Toolbar(ttk.Frame):
redraw buttons on the toolbar, send node and link messages to grpc server redraw buttons on the toolbar, send node and link messages to grpc server
""" """
logging.info("clicked stop button") logging.info("clicked stop button")
self.app.menubar.change_menubar_item_state(is_runtime=False) self.app.menubar.set_state(is_runtime=False)
self.app.core.close_mobility_players() self.app.core.close_mobility_players()
enable_buttons(self.runtime_frame, enabled=False) enable_buttons(self.runtime_frame, enabled=False)
task = ProgressTask( task = ProgressTask(