From b01249bb4edd5f7f37315b03f7aa3ede57e16840 Mon Sep 17 00:00:00 2001 From: Blake Harnden <32446120+bharnden@users.noreply.github.com> Date: Sat, 12 Dec 2020 23:17:43 -0800 Subject: [PATCH] added canvas to protobuf node messages, added node canvas id to grpc server handling, updating pygui to draw canvases based on joined session and add nodes to respective canvas --- daemon/core/api/grpc/grpcutils.py | 2 + daemon/core/api/grpc/wrappers.py | 3 + daemon/core/gui/graph/graph.py | 1 + daemon/core/gui/graph/manager.py | 85 +++++++++++++++++++-------- daemon/proto/core/api/grpc/core.proto | 1 + 5 files changed, 67 insertions(+), 25 deletions(-) diff --git a/daemon/core/api/grpc/grpcutils.py b/daemon/core/api/grpc/grpcutils.py index 145f7029..d27da28e 100644 --- a/daemon/core/api/grpc/grpcutils.py +++ b/daemon/core/api/grpc/grpcutils.py @@ -67,6 +67,7 @@ def add_node_data(node_proto: core_pb2.Node) -> Tuple[NodeTypes, int, NodeOption image=node_proto.image, services=node_proto.services, config_services=node_proto.config_services, + canvas=node_proto.canvas, ) if node_proto.emane: options.emane = node_proto.emane @@ -290,6 +291,7 @@ def get_node_proto(session: Session, node: NodeBase) -> core_pb2.Node: config_services=config_services, dir=node_dir, channel=channel, + canvas=node.canvas, ) diff --git a/daemon/core/api/grpc/wrappers.py b/daemon/core/api/grpc/wrappers.py index 8cc55446..1ef43be2 100644 --- a/daemon/core/api/grpc/wrappers.py +++ b/daemon/core/api/grpc/wrappers.py @@ -649,6 +649,7 @@ class Node: geo: Geo = None dir: str = None channel: str = None + canvas: int = None # configurations emane_model_configs: Dict[ @@ -683,6 +684,7 @@ class Node: geo=Geo.from_proto(proto.geo), dir=proto.dir, channel=proto.channel, + canvas=proto.canvas, ) def to_proto(self) -> core_pb2.Node: @@ -700,6 +702,7 @@ class Node: server=self.server, dir=self.dir, channel=self.channel, + canvas=self.canvas, ) diff --git a/daemon/core/gui/graph/graph.py b/daemon/core/gui/graph/graph.py index 52c64af2..21238798 100644 --- a/daemon/core/gui/graph/graph.py +++ b/daemon/core/gui/graph/graph.py @@ -704,6 +704,7 @@ class CanvasGraph(tk.Canvas): ) if not core_node: return + core_node.canvas = self.id try: image_enum = self.manager.node_draw.image_enum self.manager.node_draw.image = self.app.get_icon(image_enum, ICON_SIZE) diff --git a/daemon/core/gui/graph/manager.py b/daemon/core/gui/graph/manager.py index a68240f3..5124fb2f 100644 --- a/daemon/core/gui/graph/manager.py +++ b/daemon/core/gui/graph/manager.py @@ -3,12 +3,12 @@ import tkinter as tk from tkinter import BooleanVar, messagebox, ttk from typing import TYPE_CHECKING, Dict, Optional, Set, Tuple, ValuesView -from core.api.grpc.wrappers import Session +from core.api.grpc.wrappers import LinkType, Session from core.gui.graph import tags from core.gui.graph.enums import GraphMode from core.gui.graph.graph import CanvasGraph from core.gui.graph.shapeutils import ShapeType -from core.gui.nodeutils import NodeDraw +from core.gui.nodeutils import NodeDraw, NodeUtils if TYPE_CHECKING: from core.gui.app import Application @@ -79,35 +79,36 @@ class CanvasManager: def _next_id(self) -> int: _id = 1 - tab_ids = set(self.unique_ids.values()) - while _id in tab_ids: + canvas_ids = set(self.unique_ids.values()) + while _id in canvas_ids: _id += 1 return _id def current(self) -> CanvasGraph: unique_id = self.notebook.select() - tab_id = self.unique_ids[unique_id] - return self.canvases[tab_id] + canvas_id = self.unique_ids[unique_id] + return self.canvases[canvas_id] def all(self) -> ValuesView[CanvasGraph]: return self.canvases.values() - def add_canvas(self) -> CanvasGraph: + def add_canvas(self, canvas_id: int = None) -> CanvasGraph: # create tab frame tab = ttk.Frame(self.notebook, padding=0) tab.grid(sticky=tk.NSEW) tab.columnconfigure(0, weight=1) tab.rowconfigure(0, weight=1) - tab_id = self._next_id() - self.notebook.add(tab, text=f"Canvas {tab_id}") + if canvas_id is None: + canvas_id = self._next_id() + self.notebook.add(tab, text=f"Canvas {canvas_id}") unique_id = self.notebook.tabs()[-1] - logging.info("tab(%s) is %s", unique_id, tab_id) - self.unique_ids[unique_id] = tab_id + logging.info("tab(%s) is %s", unique_id, canvas_id) + self.unique_ids[unique_id] = canvas_id # create canvas - canvas = CanvasGraph(tab, self.app, self, self.core, tab_id) + canvas = CanvasGraph(tab, self.app, self, self.core, canvas_id) canvas.grid(sticky=tk.NSEW) - self.canvases[tab_id] = canvas + self.canvases[canvas_id] = canvas # add scrollbars scroll_y = ttk.Scrollbar(tab, command=canvas.yview) @@ -124,14 +125,14 @@ class CanvasManager: return unique_id = self.notebook.select() self.notebook.forget(unique_id) - tab_id = self.unique_ids.pop(unique_id) - self.canvases.pop(tab_id) - # TODO: handle clearing out canvas related nodes and links + canvas_id = self.unique_ids.pop(unique_id) + self.canvases.pop(canvas_id) + # TODO: handle clearing out canvas related nodes and links from core client def join(self, session: Session) -> None: # clear out all canvas - for tab_id in self.notebook.tabs(): - self.notebook.forget(tab_id) + for canvas_id in self.notebook.tabs(): + self.notebook.forget(canvas_id) self.canvases.clear() # reset settings @@ -147,11 +148,45 @@ class CanvasManager: self.annotation_type = None self.node_draw = None - # TODO: create and add nodes to all associated canvases - # draw initial tab(s) and session - canvas = self.add_canvas() + if session.nodes: + self.draw_session(session) + else: + self.add_canvas() - # draw session on canvas - canvas.reset_and_redraw(session) - self.core.parse_metadata(canvas) - canvas.organize() + def draw_session(self, session: Session) -> None: + # create session nodes + for core_node in session.nodes.values(): + # get tab id for node + canvas_id = core_node.canvas if core_node.canvas > 0 else 1 + + # get or create canvas + canvas = self.canvases.get(canvas_id) + if not canvas: + canvas = self.add_canvas(canvas_id) + + # add node, avoiding ignored nodes + if NodeUtils.is_ignore_node(core_node.type): + continue + logging.debug("drawing node: %s", core_node) + canvas.add_core_node(core_node) + + # draw existing links + for link in session.links: + logging.debug("drawing link: %s", link) + node1 = self.core.get_canvas_node(link.node1_id) + node2 = self.core.get_canvas_node(link.node2_id) + # TODO: handle edges for nodes on different canvases + if node1.canvas == node2.canvas: + canvas = node1.canvas + if link.type == LinkType.WIRELESS: + canvas.add_wireless_edge(node1, node2, link) + else: + canvas.add_wired_edge(node1, node2, link) + else: + logging.error("cant handle nodes linked between canvases") + + # TODO: handle metadata + # self.core.parse_metadata(canvas) + # organize all canvases + for canvas in self.canvases.values(): + canvas.organize() diff --git a/daemon/proto/core/api/grpc/core.proto b/daemon/proto/core/api/grpc/core.proto index d168afe0..cdc89202 100644 --- a/daemon/proto/core/api/grpc/core.proto +++ b/daemon/proto/core/api/grpc/core.proto @@ -752,6 +752,7 @@ message Node { Geo geo = 12; string dir = 13; string channel = 14; + int32 canvas = 15; } message Link {