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

This commit is contained in:
Blake Harnden 2020-12-12 23:17:43 -08:00
parent 9621df6bc4
commit b01249bb4e
5 changed files with 67 additions and 25 deletions

View file

@ -67,6 +67,7 @@ def add_node_data(node_proto: core_pb2.Node) -> Tuple[NodeTypes, int, NodeOption
image=node_proto.image, image=node_proto.image,
services=node_proto.services, services=node_proto.services,
config_services=node_proto.config_services, config_services=node_proto.config_services,
canvas=node_proto.canvas,
) )
if node_proto.emane: if node_proto.emane:
options.emane = 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, config_services=config_services,
dir=node_dir, dir=node_dir,
channel=channel, channel=channel,
canvas=node.canvas,
) )

View file

@ -649,6 +649,7 @@ class Node:
geo: Geo = None geo: Geo = None
dir: str = None dir: str = None
channel: str = None channel: str = None
canvas: int = None
# configurations # configurations
emane_model_configs: Dict[ emane_model_configs: Dict[
@ -683,6 +684,7 @@ class Node:
geo=Geo.from_proto(proto.geo), geo=Geo.from_proto(proto.geo),
dir=proto.dir, dir=proto.dir,
channel=proto.channel, channel=proto.channel,
canvas=proto.canvas,
) )
def to_proto(self) -> core_pb2.Node: def to_proto(self) -> core_pb2.Node:
@ -700,6 +702,7 @@ class Node:
server=self.server, server=self.server,
dir=self.dir, dir=self.dir,
channel=self.channel, channel=self.channel,
canvas=self.canvas,
) )

View file

@ -704,6 +704,7 @@ class CanvasGraph(tk.Canvas):
) )
if not core_node: if not core_node:
return return
core_node.canvas = self.id
try: try:
image_enum = self.manager.node_draw.image_enum image_enum = self.manager.node_draw.image_enum
self.manager.node_draw.image = self.app.get_icon(image_enum, ICON_SIZE) self.manager.node_draw.image = self.app.get_icon(image_enum, ICON_SIZE)

View file

@ -3,12 +3,12 @@ import tkinter as tk
from tkinter import BooleanVar, messagebox, ttk from tkinter import BooleanVar, messagebox, ttk
from typing import TYPE_CHECKING, Dict, Optional, Set, Tuple, ValuesView 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 import tags
from core.gui.graph.enums import GraphMode from core.gui.graph.enums import GraphMode
from core.gui.graph.graph import CanvasGraph from core.gui.graph.graph import CanvasGraph
from core.gui.graph.shapeutils import ShapeType from core.gui.graph.shapeutils import ShapeType
from core.gui.nodeutils import NodeDraw from core.gui.nodeutils import NodeDraw, NodeUtils
if TYPE_CHECKING: if TYPE_CHECKING:
from core.gui.app import Application from core.gui.app import Application
@ -79,35 +79,36 @@ class CanvasManager:
def _next_id(self) -> int: def _next_id(self) -> int:
_id = 1 _id = 1
tab_ids = set(self.unique_ids.values()) canvas_ids = set(self.unique_ids.values())
while _id in tab_ids: while _id in canvas_ids:
_id += 1 _id += 1
return _id return _id
def current(self) -> CanvasGraph: def current(self) -> CanvasGraph:
unique_id = self.notebook.select() unique_id = self.notebook.select()
tab_id = self.unique_ids[unique_id] canvas_id = self.unique_ids[unique_id]
return self.canvases[tab_id] return self.canvases[canvas_id]
def all(self) -> ValuesView[CanvasGraph]: def all(self) -> ValuesView[CanvasGraph]:
return self.canvases.values() return self.canvases.values()
def add_canvas(self) -> CanvasGraph: def add_canvas(self, canvas_id: int = None) -> CanvasGraph:
# create tab frame # create tab frame
tab = ttk.Frame(self.notebook, padding=0) tab = ttk.Frame(self.notebook, padding=0)
tab.grid(sticky=tk.NSEW) tab.grid(sticky=tk.NSEW)
tab.columnconfigure(0, weight=1) tab.columnconfigure(0, weight=1)
tab.rowconfigure(0, weight=1) tab.rowconfigure(0, weight=1)
tab_id = self._next_id() if canvas_id is None:
self.notebook.add(tab, text=f"Canvas {tab_id}") canvas_id = self._next_id()
self.notebook.add(tab, text=f"Canvas {canvas_id}")
unique_id = self.notebook.tabs()[-1] unique_id = self.notebook.tabs()[-1]
logging.info("tab(%s) is %s", unique_id, tab_id) logging.info("tab(%s) is %s", unique_id, canvas_id)
self.unique_ids[unique_id] = tab_id self.unique_ids[unique_id] = canvas_id
# create canvas # 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) canvas.grid(sticky=tk.NSEW)
self.canvases[tab_id] = canvas self.canvases[canvas_id] = canvas
# add scrollbars # add scrollbars
scroll_y = ttk.Scrollbar(tab, command=canvas.yview) scroll_y = ttk.Scrollbar(tab, command=canvas.yview)
@ -124,14 +125,14 @@ class CanvasManager:
return return
unique_id = self.notebook.select() unique_id = self.notebook.select()
self.notebook.forget(unique_id) self.notebook.forget(unique_id)
tab_id = self.unique_ids.pop(unique_id) canvas_id = self.unique_ids.pop(unique_id)
self.canvases.pop(tab_id) self.canvases.pop(canvas_id)
# TODO: handle clearing out canvas related nodes and links # TODO: handle clearing out canvas related nodes and links from core client
def join(self, session: Session) -> None: def join(self, session: Session) -> None:
# clear out all canvas # clear out all canvas
for tab_id in self.notebook.tabs(): for canvas_id in self.notebook.tabs():
self.notebook.forget(tab_id) self.notebook.forget(canvas_id)
self.canvases.clear() self.canvases.clear()
# reset settings # reset settings
@ -147,11 +148,45 @@ class CanvasManager:
self.annotation_type = None self.annotation_type = None
self.node_draw = None self.node_draw = None
# TODO: create and add nodes to all associated canvases if session.nodes:
# draw initial tab(s) and session self.draw_session(session)
canvas = self.add_canvas() else:
self.add_canvas()
# draw session on canvas def draw_session(self, session: Session) -> None:
canvas.reset_and_redraw(session) # create session nodes
self.core.parse_metadata(canvas) for core_node in session.nodes.values():
canvas.organize() # 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()

View file

@ -752,6 +752,7 @@ message Node {
Geo geo = 12; Geo geo = 12;
string dir = 13; string dir = 13;
string channel = 14; string channel = 14;
int32 canvas = 15;
} }
message Link { message Link {