pygui: further refactoring to work towards multiple canvas support
This commit is contained in:
parent
e34c00a431
commit
886bfc093b
8 changed files with 161 additions and 134 deletions
|
@ -14,6 +14,7 @@ from core.gui.dialogs.error import ErrorDialog
|
|||
from core.gui.frames.base import InfoFrameBase
|
||||
from core.gui.frames.default import DefaultInfoFrame
|
||||
from core.gui.graph.graph import CanvasGraph
|
||||
from core.gui.graph.manager import CanvasManager
|
||||
from core.gui.images import ImageEnum, Images
|
||||
from core.gui.menubar import Menubar
|
||||
from core.gui.nodeutils import NodeUtils
|
||||
|
@ -35,6 +36,7 @@ class Application(ttk.Frame):
|
|||
self.menubar: Optional[Menubar] = None
|
||||
self.toolbar: Optional[Toolbar] = None
|
||||
self.right_frame: Optional[ttk.Frame] = None
|
||||
self.manager: Optional[CanvasManager] = None
|
||||
self.canvas: Optional[CanvasGraph] = None
|
||||
self.statusbar: Optional[StatusBar] = None
|
||||
self.progress: Optional[Progressbar] = None
|
||||
|
@ -140,16 +142,18 @@ class Application(ttk.Frame):
|
|||
canvas_frame.rowconfigure(0, weight=1)
|
||||
canvas_frame.columnconfigure(0, weight=1)
|
||||
canvas_frame.grid(row=0, column=0, sticky=tk.NSEW, pady=1)
|
||||
self.canvas = CanvasGraph(canvas_frame, self, self.core)
|
||||
self.canvas.grid(sticky=tk.NSEW)
|
||||
scroll_y = ttk.Scrollbar(canvas_frame, command=self.canvas.yview)
|
||||
scroll_y.grid(row=0, column=1, sticky=tk.NS)
|
||||
scroll_x = ttk.Scrollbar(
|
||||
canvas_frame, orient=tk.HORIZONTAL, command=self.canvas.xview
|
||||
)
|
||||
scroll_x.grid(row=1, column=0, sticky=tk.EW)
|
||||
self.canvas.configure(xscrollcommand=scroll_x.set)
|
||||
self.canvas.configure(yscrollcommand=scroll_y.set)
|
||||
self.manager = CanvasManager(canvas_frame, self, self.core)
|
||||
self.manager.notebook.grid(sticky=tk.NSEW)
|
||||
# self.canvas = CanvasGraph(canvas_frame, self, self.core)
|
||||
# self.canvas.grid(sticky=tk.NSEW)
|
||||
# scroll_y = ttk.Scrollbar(canvas_frame, command=self.canvas.yview)
|
||||
# scroll_y.grid(row=0, column=1, sticky=tk.NS)
|
||||
# scroll_x = ttk.Scrollbar(
|
||||
# canvas_frame, orient=tk.HORIZONTAL, command=self.canvas.xview
|
||||
# )
|
||||
# scroll_x.grid(row=1, column=0, sticky=tk.EW)
|
||||
# self.canvas.configure(xscrollcommand=scroll_x.set)
|
||||
# self.canvas.configure(yscrollcommand=scroll_y.set)
|
||||
|
||||
def draw_status(self) -> None:
|
||||
self.statusbar = StatusBar(self.right_frame, self)
|
||||
|
|
|
@ -47,6 +47,7 @@ from core.gui.dialogs.error import ErrorDialog
|
|||
from core.gui.dialogs.mobilityplayer import MobilityPlayer
|
||||
from core.gui.dialogs.sessions import SessionsDialog
|
||||
from core.gui.graph.edges import CanvasEdge
|
||||
from core.gui.graph.graph import CanvasGraph
|
||||
from core.gui.graph.node import CanvasNode
|
||||
from core.gui.graph.shape import AnnotationData, Shape
|
||||
from core.gui.graph.shapeutils import ShapeType
|
||||
|
@ -315,9 +316,7 @@ class CoreClient:
|
|||
self.session.id, self.handle_events
|
||||
)
|
||||
self.ifaces_manager.joined(self.session.links)
|
||||
self.app.canvas.reset_and_redraw(self.session)
|
||||
self.parse_metadata()
|
||||
self.app.canvas.organize()
|
||||
self.app.manager.join(self.session)
|
||||
if self.is_runtime():
|
||||
self.show_mobility_players()
|
||||
self.app.after(0, self.app.joined_session_update)
|
||||
|
@ -327,7 +326,7 @@ class CoreClient:
|
|||
def is_runtime(self) -> bool:
|
||||
return self.session and self.session.state == SessionState.RUNTIME
|
||||
|
||||
def parse_metadata(self) -> None:
|
||||
def parse_metadata(self, canvas: CanvasGraph) -> None:
|
||||
# canvas setting
|
||||
config = self.session.metadata
|
||||
canvas_config = config.get("canvas")
|
||||
|
@ -347,10 +346,10 @@ class CoreClient:
|
|||
wallpaper = canvas_config.get("wallpaper")
|
||||
if wallpaper:
|
||||
wallpaper = str(appconfig.BACKGROUNDS_PATH.joinpath(wallpaper))
|
||||
self.app.canvas.set_wallpaper(wallpaper)
|
||||
canvas.set_wallpaper(wallpaper)
|
||||
else:
|
||||
self.app.canvas.redraw_canvas()
|
||||
self.app.canvas.set_wallpaper(None)
|
||||
canvas.redraw_canvas()
|
||||
canvas.set_wallpaper(None)
|
||||
|
||||
# load saved shapes
|
||||
shapes_config = config.get("shapes")
|
||||
|
@ -377,7 +376,7 @@ class CoreClient:
|
|||
shape = Shape(
|
||||
self.app, self.app.canvas, shape_type, *coords, data=data
|
||||
)
|
||||
self.app.canvas.shapes[shape.id] = shape
|
||||
canvas.shapes[shape.id] = shape
|
||||
except ValueError:
|
||||
logging.exception("unknown shape: %s", shape_type)
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import logging
|
||||
import tkinter as tk
|
||||
from copy import deepcopy
|
||||
from tkinter import BooleanVar
|
||||
from typing import TYPE_CHECKING, Dict, List, Optional, Set, Tuple
|
||||
|
||||
from PIL import Image
|
||||
|
@ -31,10 +30,11 @@ from core.gui.graph.node import CanvasNode
|
|||
from core.gui.graph.shape import Shape
|
||||
from core.gui.graph.shapeutils import ShapeType, is_draw_shape, is_marker
|
||||
from core.gui.images import ImageEnum, TypeToImage
|
||||
from core.gui.nodeutils import NodeDraw, NodeUtils
|
||||
from core.gui.nodeutils import NodeUtils
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from core.gui.app import Application
|
||||
from core.gui.graph.manager import CanvasManager
|
||||
from core.gui.coreclient import CoreClient
|
||||
|
||||
ZOOM_IN = 1.1
|
||||
|
@ -44,32 +44,23 @@ MOVE_NODE_MODES = {GraphMode.NODE, GraphMode.SELECT}
|
|||
MOVE_SHAPE_MODES = {GraphMode.ANNOTATION, GraphMode.SELECT}
|
||||
|
||||
|
||||
class ShowVar(BooleanVar):
|
||||
def __init__(self, canvas: "CanvasGraph", tag: str, value: bool) -> None:
|
||||
super().__init__(value=value)
|
||||
self.canvas = canvas
|
||||
self.tag = tag
|
||||
|
||||
def state(self) -> str:
|
||||
return tk.NORMAL if self.get() else tk.HIDDEN
|
||||
|
||||
def click_handler(self) -> None:
|
||||
self.canvas.itemconfigure(self.tag, state=self.state())
|
||||
|
||||
|
||||
class CanvasGraph(tk.Canvas):
|
||||
def __init__(
|
||||
self, master: tk.BaseWidget, app: "Application", core: "CoreClient"
|
||||
self,
|
||||
master: tk.BaseWidget,
|
||||
app: "Application",
|
||||
canvas_manager: "CanvasManager",
|
||||
core: "CoreClient",
|
||||
_id: int,
|
||||
) -> None:
|
||||
super().__init__(master, highlightthickness=0, background="#cccccc")
|
||||
self.id: int = _id
|
||||
self.app: "Application" = app
|
||||
self.manager: "CanvasManager" = canvas_manager
|
||||
self.core: "CoreClient" = core
|
||||
self.mode: GraphMode = GraphMode.SELECT
|
||||
self.annotation_type: Optional[ShapeType] = None
|
||||
self.selection: Dict[int, int] = {}
|
||||
self.select_box: Optional[Shape] = None
|
||||
self.selected: Optional[int] = None
|
||||
self.node_draw: Optional[NodeDraw] = None
|
||||
self.nodes: Dict[int, CanvasNode] = {}
|
||||
self.edges: Dict[str, CanvasEdge] = {}
|
||||
self.shapes: Dict[int, Shape] = {}
|
||||
|
@ -103,18 +94,6 @@ class CanvasGraph(tk.Canvas):
|
|||
self.throughput_width: int = 10
|
||||
self.throughput_color: str = "#FF0000"
|
||||
|
||||
# drawing related
|
||||
self.show_node_labels: ShowVar = ShowVar(self, tags.NODE_LABEL, value=True)
|
||||
self.show_link_labels: ShowVar = ShowVar(self, tags.LINK_LABEL, value=True)
|
||||
self.show_links: ShowVar = ShowVar(self, tags.EDGE, value=True)
|
||||
self.show_wireless: ShowVar = ShowVar(self, tags.WIRELESS_EDGE, value=True)
|
||||
self.show_grid: ShowVar = ShowVar(self, tags.GRIDLINE, value=True)
|
||||
self.show_annotations: ShowVar = ShowVar(self, tags.ANNOTATION, value=True)
|
||||
self.show_loss_links: ShowVar = ShowVar(self, tags.LOSS_EDGES, value=True)
|
||||
self.show_iface_names: BooleanVar = BooleanVar(value=False)
|
||||
self.show_ip4s: BooleanVar = BooleanVar(value=True)
|
||||
self.show_ip6s: BooleanVar = BooleanVar(value=True)
|
||||
|
||||
# bindings
|
||||
self.setup_bindings()
|
||||
|
||||
|
@ -140,24 +119,11 @@ class CanvasGraph(tk.Canvas):
|
|||
self.configure(scrollregion=self.bbox(tk.ALL))
|
||||
|
||||
def reset_and_redraw(self, session: Session) -> None:
|
||||
# reset view options to default state
|
||||
self.show_node_labels.set(True)
|
||||
self.show_link_labels.set(True)
|
||||
self.show_grid.set(True)
|
||||
self.show_annotations.set(True)
|
||||
self.show_iface_names.set(False)
|
||||
self.show_ip4s.set(True)
|
||||
self.show_ip6s.set(True)
|
||||
self.show_loss_links.set(True)
|
||||
|
||||
# delete any existing drawn items
|
||||
for tag in tags.RESET_TAGS:
|
||||
self.delete(tag)
|
||||
|
||||
# set the private variables to default value
|
||||
self.mode = GraphMode.SELECT
|
||||
self.annotation_type = None
|
||||
self.node_draw = None
|
||||
self.selected = None
|
||||
self.nodes.clear()
|
||||
self.edges.clear()
|
||||
|
@ -307,7 +273,7 @@ class CanvasGraph(tk.Canvas):
|
|||
image = self.app.get_icon(ImageEnum.EDITNODE, ICON_SIZE)
|
||||
x = core_node.position.x
|
||||
y = core_node.position.y
|
||||
node = CanvasNode(self.app, x, y, core_node, image)
|
||||
node = CanvasNode(self.app, self, x, y, core_node, image)
|
||||
self.nodes[node.id] = node
|
||||
self.core.set_canvas_node(core_node, node)
|
||||
|
||||
|
@ -381,13 +347,13 @@ class CanvasGraph(tk.Canvas):
|
|||
x, y = self.canvas_xy(event)
|
||||
if not self.inside_canvas(x, y):
|
||||
return
|
||||
if self.mode == GraphMode.ANNOTATION:
|
||||
if self.manager.mode == GraphMode.ANNOTATION:
|
||||
self.focus_set()
|
||||
if self.shape_drawing:
|
||||
shape = self.shapes[self.selected]
|
||||
shape.shape_complete(x, y)
|
||||
self.shape_drawing = False
|
||||
elif self.mode == GraphMode.SELECT:
|
||||
elif self.manager.mode == GraphMode.SELECT:
|
||||
self.focus_set()
|
||||
if self.select_box:
|
||||
x0, y0, x1, y1 = self.coords(self.select_box.id)
|
||||
|
@ -403,13 +369,15 @@ class CanvasGraph(tk.Canvas):
|
|||
else:
|
||||
self.focus_set()
|
||||
self.selected = self.get_selected(event)
|
||||
logging.debug(f"click release selected({self.selected}) mode({self.mode})")
|
||||
if self.mode == GraphMode.EDGE:
|
||||
logging.debug(
|
||||
"click release selected(%s) mode(%s)", self.selected, self.manager.mode
|
||||
)
|
||||
if self.manager.mode == GraphMode.EDGE:
|
||||
self.handle_edge_release(event)
|
||||
elif self.mode == GraphMode.NODE:
|
||||
elif self.manager.mode == GraphMode.NODE:
|
||||
self.add_node(x, y)
|
||||
elif self.mode == GraphMode.PICKNODE:
|
||||
self.mode = GraphMode.NODE
|
||||
elif self.manager.mode == GraphMode.PICKNODE:
|
||||
self.manager.mode = GraphMode.NODE
|
||||
self.selected = None
|
||||
|
||||
def handle_edge_release(self, _event: tk.Event) -> None:
|
||||
|
@ -588,13 +556,13 @@ class CanvasGraph(tk.Canvas):
|
|||
y_check = self.cursor[1] - self.offset[1]
|
||||
logging.debug("click press offset(%s, %s)", x_check, y_check)
|
||||
is_node = selected in self.nodes
|
||||
if self.mode == GraphMode.EDGE and is_node:
|
||||
if self.manager.mode == GraphMode.EDGE and is_node:
|
||||
pos = self.coords(selected)
|
||||
self.drawing_edge = CanvasEdge(self, selected, pos, pos)
|
||||
self.organize()
|
||||
|
||||
if self.mode == GraphMode.ANNOTATION:
|
||||
if is_marker(self.annotation_type):
|
||||
if self.manager.mode == GraphMode.ANNOTATION:
|
||||
if is_marker(self.manager.annotation_type):
|
||||
r = self.app.toolbar.marker_frame.size.get()
|
||||
self.create_oval(
|
||||
x - r,
|
||||
|
@ -604,11 +572,11 @@ class CanvasGraph(tk.Canvas):
|
|||
fill=self.app.toolbar.marker_frame.color,
|
||||
outline="",
|
||||
tags=(tags.MARKER, tags.ANNOTATION),
|
||||
state=self.show_annotations.state(),
|
||||
state=self.manager.show_annotations.state(),
|
||||
)
|
||||
return
|
||||
if selected is None:
|
||||
shape = Shape(self.app, self, self.annotation_type, x, y)
|
||||
shape = Shape(self.app, self, self.manager.annotation_type, x, y)
|
||||
self.selected = shape.id
|
||||
self.shape_drawing = True
|
||||
self.shapes[shape.id] = shape
|
||||
|
@ -630,7 +598,7 @@ class CanvasGraph(tk.Canvas):
|
|||
node.core_node.position.y,
|
||||
)
|
||||
else:
|
||||
if self.mode == GraphMode.SELECT:
|
||||
if self.manager.mode == GraphMode.SELECT:
|
||||
shape = Shape(self.app, self, ShapeType.RECTANGLE, x, y)
|
||||
self.select_box = shape
|
||||
self.clear_selection()
|
||||
|
@ -659,7 +627,7 @@ class CanvasGraph(tk.Canvas):
|
|||
if self.select_box:
|
||||
self.select_box.delete()
|
||||
self.select_box = None
|
||||
if is_draw_shape(self.annotation_type) and self.shape_drawing:
|
||||
if is_draw_shape(self.manager.annotation_type) and self.shape_drawing:
|
||||
shape = self.shapes.pop(self.selected)
|
||||
shape.delete()
|
||||
self.shape_drawing = False
|
||||
|
@ -669,14 +637,14 @@ class CanvasGraph(tk.Canvas):
|
|||
y_offset = y - self.cursor[1]
|
||||
self.cursor = x, y
|
||||
|
||||
if self.mode == GraphMode.EDGE and self.drawing_edge is not None:
|
||||
if self.manager.mode == GraphMode.EDGE and self.drawing_edge is not None:
|
||||
self.drawing_edge.move_dst(self.cursor)
|
||||
if self.mode == GraphMode.ANNOTATION:
|
||||
if is_draw_shape(self.annotation_type) and self.shape_drawing:
|
||||
if self.manager.mode == GraphMode.ANNOTATION:
|
||||
if is_draw_shape(self.manager.annotation_type) and self.shape_drawing:
|
||||
shape = self.shapes[self.selected]
|
||||
shape.shape_motion(x, y)
|
||||
return
|
||||
elif is_marker(self.annotation_type):
|
||||
elif is_marker(self.manager.annotation_type):
|
||||
r = self.app.toolbar.marker_frame.size.get()
|
||||
self.create_oval(
|
||||
x - r,
|
||||
|
@ -689,21 +657,21 @@ class CanvasGraph(tk.Canvas):
|
|||
)
|
||||
return
|
||||
|
||||
if self.mode == GraphMode.EDGE:
|
||||
if self.manager.mode == GraphMode.EDGE:
|
||||
return
|
||||
|
||||
# move selected objects
|
||||
if self.selection:
|
||||
for selected_id in self.selection:
|
||||
if self.mode in MOVE_SHAPE_MODES and selected_id in self.shapes:
|
||||
if self.manager.mode in MOVE_SHAPE_MODES and selected_id in self.shapes:
|
||||
shape = self.shapes[selected_id]
|
||||
shape.motion(x_offset, y_offset)
|
||||
|
||||
if self.mode in MOVE_NODE_MODES and selected_id in self.nodes:
|
||||
if self.manager.mode in MOVE_NODE_MODES and selected_id in self.nodes:
|
||||
node = self.nodes[selected_id]
|
||||
node.motion(x_offset, y_offset, update=self.core.is_runtime())
|
||||
else:
|
||||
if self.select_box and self.mode == GraphMode.SELECT:
|
||||
if self.select_box and self.manager.mode == GraphMode.SELECT:
|
||||
self.select_box.shape_motion(x, y)
|
||||
|
||||
def press_delete(self, _event: tk.Event) -> None:
|
||||
|
@ -729,17 +697,22 @@ class CanvasGraph(tk.Canvas):
|
|||
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
|
||||
actual_x,
|
||||
actual_y,
|
||||
self.manager.node_draw.node_type,
|
||||
self.manager.node_draw.model,
|
||||
)
|
||||
if not core_node:
|
||||
return
|
||||
try:
|
||||
image_enum = self.node_draw.image_enum
|
||||
self.node_draw.image = self.app.get_icon(image_enum, ICON_SIZE)
|
||||
image_enum = self.manager.node_draw.image_enum
|
||||
self.manager.node_draw.image = self.app.get_icon(image_enum, ICON_SIZE)
|
||||
except AttributeError:
|
||||
image_file = self.node_draw.image_file
|
||||
self.node_draw.image = self.app.get_custom_icon(image_file, ICON_SIZE)
|
||||
node = CanvasNode(self.app, x, y, core_node, self.node_draw.image)
|
||||
image_file = self.manager.node_draw.image_file
|
||||
self.manager.node_draw.image = self.app.get_custom_icon(
|
||||
image_file, ICON_SIZE
|
||||
)
|
||||
node = CanvasNode(self.app, self, x, y, core_node, self.manager.node_draw.image)
|
||||
self.nodes[node.id] = node
|
||||
self.core.set_canvas_node(core_node, node)
|
||||
|
||||
|
@ -847,7 +820,7 @@ class CanvasGraph(tk.Canvas):
|
|||
# redraw gridlines to new canvas size
|
||||
self.delete(tags.GRIDLINE)
|
||||
self.draw_grid()
|
||||
self.app.canvas.show_grid.click_handler()
|
||||
self.app.manager.show_grid.click_handler()
|
||||
|
||||
def redraw_wallpaper(self) -> None:
|
||||
if self.adjust_to_dim.get():
|
||||
|
@ -884,7 +857,7 @@ class CanvasGraph(tk.Canvas):
|
|||
self.wallpaper_file = None
|
||||
|
||||
def is_selection_mode(self) -> bool:
|
||||
return self.mode == GraphMode.SELECT
|
||||
return self.manager.mode == GraphMode.SELECT
|
||||
|
||||
def create_edge(self, src: CanvasNode, dst: CanvasNode) -> CanvasEdge:
|
||||
"""
|
||||
|
|
|
@ -1,16 +1,18 @@
|
|||
import logging
|
||||
import tkinter as tk
|
||||
from tkinter import BooleanVar
|
||||
from typing import Dict, Optional, Set, Tuple
|
||||
from tkinter import BooleanVar, ttk
|
||||
from typing import TYPE_CHECKING, Dict, Optional, Set, Tuple
|
||||
|
||||
from core.gui.app import Application
|
||||
from core.gui.coreclient import CoreClient
|
||||
from core.api.grpc.wrappers import Session
|
||||
from core.gui.graph import tags
|
||||
from core.gui.graph.edges import CanvasEdge
|
||||
from core.gui.graph.enums import GraphMode
|
||||
from core.gui.graph.graph import CanvasGraph
|
||||
from core.gui.graph.node import CanvasNode
|
||||
from core.gui.graph.shape import Shape
|
||||
from core.gui.graph.shapeutils import ShapeType
|
||||
from core.gui.nodeutils import NodeDraw
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from core.gui.app import Application
|
||||
from core.gui.coreclient import CoreClient
|
||||
|
||||
|
||||
class ShowVar(BooleanVar):
|
||||
|
@ -38,18 +40,18 @@ class CanvasManager:
|
|||
# canvas interactions
|
||||
self.mode: GraphMode = GraphMode.SELECT
|
||||
self.annotation_type: Optional[ShapeType] = None
|
||||
self.node_draw: Optional[NodeDraw] = None
|
||||
self.canvases: Dict[int, CanvasGraph] = {}
|
||||
|
||||
# canvas object storage
|
||||
self.nodes: Dict[int, CanvasNode] = {}
|
||||
self.edges: Dict[str, CanvasEdge] = {}
|
||||
self.shapes: Dict[int, Shape] = {}
|
||||
# TODO: validate this
|
||||
self.wireless_network: Dict[int, Set[int]] = {}
|
||||
|
||||
# global canvas settings
|
||||
width = self.app.guiconfig.preferences.width
|
||||
height = self.app.guiconfig.preferences.height
|
||||
self.default_dimensions: Tuple[int, int] = (width, height)
|
||||
self.default_dimensions: Tuple[int, int] = (
|
||||
self.app.guiconfig.preferences.width,
|
||||
self.app.guiconfig.preferences.height,
|
||||
)
|
||||
self.show_node_labels: ShowVar = ShowVar(self, tags.NODE_LABEL, value=True)
|
||||
self.show_link_labels: ShowVar = ShowVar(self, tags.LINK_LABEL, value=True)
|
||||
self.show_links: ShowVar = ShowVar(self, tags.EDGE, value=True)
|
||||
|
@ -65,3 +67,46 @@ class CanvasManager:
|
|||
self.throughput_threshold: float = 250.0
|
||||
self.throughput_width: int = 10
|
||||
self.throughput_color: str = "#FF0000"
|
||||
|
||||
# widget
|
||||
self.notebook: Optional[ttk.Notebook] = None
|
||||
self.draw()
|
||||
|
||||
def draw(self) -> None:
|
||||
self.notebook = ttk.Notebook(self.master)
|
||||
self.notebook.grid(sticky=tk.NSEW)
|
||||
|
||||
def join(self, session: Session) -> None:
|
||||
# clear out all canvas
|
||||
for tab_id in self.notebook.tabs():
|
||||
self.notebook.forget(tab_id)
|
||||
self.canvases.clear()
|
||||
|
||||
# reset settings
|
||||
self.show_node_labels.set(True)
|
||||
self.show_link_labels.set(True)
|
||||
self.show_grid.set(True)
|
||||
self.show_annotations.set(True)
|
||||
self.show_iface_names.set(False)
|
||||
self.show_ip4s.set(True)
|
||||
self.show_ip6s.set(True)
|
||||
self.show_loss_links.set(True)
|
||||
self.mode = GraphMode.SELECT
|
||||
self.annotation_type = None
|
||||
self.node_draw = None
|
||||
|
||||
# draw initial tab(s) and session
|
||||
tab = ttk.Frame(self.notebook, padding=0)
|
||||
tab.grid(sticky=tk.NSEW)
|
||||
tab.columnconfigure(0, weight=1)
|
||||
tab.rowconfigure(0, weight=1)
|
||||
tab_id = len(self.notebook.tabs())
|
||||
self.notebook.add(tab, text=f"Canvas {tab_id}")
|
||||
logging.info("canvas tab id: %s", tab_id)
|
||||
canvas = CanvasGraph(tab, self.app, self, self.core, tab_id)
|
||||
canvas.grid(sticky=tk.NSEW)
|
||||
self.canvases[tab_id] = canvas
|
||||
|
||||
canvas.reset_and_redraw(session)
|
||||
self.core.parse_metadata(canvas)
|
||||
canvas.organize()
|
||||
|
|
|
@ -31,10 +31,16 @@ NODE_TEXT_OFFSET: int = 5
|
|||
|
||||
class CanvasNode:
|
||||
def __init__(
|
||||
self, app: "Application", x: float, y: float, core_node: Node, image: PhotoImage
|
||||
self,
|
||||
app: "Application",
|
||||
canvas: "CanvasGraph",
|
||||
x: float,
|
||||
y: float,
|
||||
core_node: Node,
|
||||
image: PhotoImage,
|
||||
):
|
||||
self.app: "Application" = app
|
||||
self.canvas: "CanvasGraph" = app.canvas
|
||||
self.canvas: "CanvasGraph" = canvas
|
||||
self.image: PhotoImage = image
|
||||
self.core_node: Node = core_node
|
||||
self.id: int = self.canvas.create_image(
|
||||
|
@ -49,7 +55,7 @@ class CanvasNode:
|
|||
tags=tags.NODE_LABEL,
|
||||
font=self.app.icon_text_font,
|
||||
fill="#0000CD",
|
||||
state=self.canvas.show_node_labels.state(),
|
||||
state=self.app.manager.show_node_labels.state(),
|
||||
)
|
||||
self.tooltip: CanvasTooltip = CanvasTooltip(self.canvas)
|
||||
self.edges: Set[CanvasEdge] = set()
|
||||
|
|
|
@ -22,7 +22,7 @@ from core.gui.dialogs.servers import ServersDialog
|
|||
from core.gui.dialogs.sessionoptions import SessionOptionsDialog
|
||||
from core.gui.dialogs.sessions import SessionsDialog
|
||||
from core.gui.dialogs.throughput import ThroughputDialog
|
||||
from core.gui.graph.graph import CanvasGraph
|
||||
from core.gui.graph.manager import CanvasManager
|
||||
from core.gui.nodeutils import ICON_SIZE
|
||||
from core.gui.observers import ObserversMenu
|
||||
from core.gui.task import ProgressTask
|
||||
|
@ -45,7 +45,7 @@ class Menubar(tk.Menu):
|
|||
super().__init__(app)
|
||||
self.app: "Application" = app
|
||||
self.core: CoreClient = app.core
|
||||
self.canvas: CanvasGraph = app.canvas
|
||||
self.canvas_manager: CanvasManager = app.manager
|
||||
self.recent_menu: Optional[tk.Menu] = None
|
||||
self.edit_menu: Optional[tk.Menu] = None
|
||||
self.observers_menu: Optional[ObserversMenu] = None
|
||||
|
@ -145,52 +145,52 @@ class Menubar(tk.Menu):
|
|||
menu.add_checkbutton(
|
||||
label="Interface Names",
|
||||
command=self.click_edge_label_change,
|
||||
variable=self.canvas.show_iface_names,
|
||||
variable=self.canvas_manager.show_iface_names,
|
||||
)
|
||||
menu.add_checkbutton(
|
||||
label="IPv4 Addresses",
|
||||
command=self.click_edge_label_change,
|
||||
variable=self.canvas.show_ip4s,
|
||||
variable=self.canvas_manager.show_ip4s,
|
||||
)
|
||||
menu.add_checkbutton(
|
||||
label="IPv6 Addresses",
|
||||
command=self.click_edge_label_change,
|
||||
variable=self.canvas.show_ip6s,
|
||||
variable=self.canvas_manager.show_ip6s,
|
||||
)
|
||||
menu.add_checkbutton(
|
||||
label="Node Labels",
|
||||
command=self.canvas.show_node_labels.click_handler,
|
||||
variable=self.canvas.show_node_labels,
|
||||
command=self.canvas_manager.show_node_labels.click_handler,
|
||||
variable=self.canvas_manager.show_node_labels,
|
||||
)
|
||||
menu.add_checkbutton(
|
||||
label="Link Labels",
|
||||
command=self.canvas.show_link_labels.click_handler,
|
||||
variable=self.canvas.show_link_labels,
|
||||
command=self.canvas_manager.show_link_labels.click_handler,
|
||||
variable=self.canvas_manager.show_link_labels,
|
||||
)
|
||||
menu.add_checkbutton(
|
||||
label="Links",
|
||||
command=self.canvas.show_links.click_handler,
|
||||
variable=self.canvas.show_links,
|
||||
command=self.canvas_manager.show_links.click_handler,
|
||||
variable=self.canvas_manager.show_links,
|
||||
)
|
||||
menu.add_checkbutton(
|
||||
label="Loss Links",
|
||||
command=self.canvas.show_loss_links.click_handler,
|
||||
variable=self.canvas.show_loss_links,
|
||||
command=self.canvas_manager.show_loss_links.click_handler,
|
||||
variable=self.canvas_manager.show_loss_links,
|
||||
)
|
||||
menu.add_checkbutton(
|
||||
label="Wireless Links",
|
||||
command=self.canvas.show_wireless.click_handler,
|
||||
variable=self.canvas.show_wireless,
|
||||
command=self.canvas_manager.show_wireless.click_handler,
|
||||
variable=self.canvas_manager.show_wireless,
|
||||
)
|
||||
menu.add_checkbutton(
|
||||
label="Annotations",
|
||||
command=self.canvas.show_annotations.click_handler,
|
||||
variable=self.canvas.show_annotations,
|
||||
command=self.canvas_manager.show_annotations.click_handler,
|
||||
variable=self.canvas_manager.show_annotations,
|
||||
)
|
||||
menu.add_checkbutton(
|
||||
label="Canvas Grid",
|
||||
command=self.canvas.show_grid.click_handler,
|
||||
variable=self.canvas.show_grid,
|
||||
command=self.canvas_manager.show_grid.click_handler,
|
||||
variable=self.canvas_manager.show_grid,
|
||||
)
|
||||
self.add_cascade(label="View", menu=menu)
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ class StatusBar(ttk.Frame):
|
|||
|
||||
self.zoom = ttk.Label(self, anchor=tk.CENTER, borderwidth=1, relief=tk.RIDGE)
|
||||
self.zoom.grid(row=0, column=1, sticky=tk.EW)
|
||||
self.set_zoom(self.app.canvas.ratio)
|
||||
# self.set_zoom(self.app.canvas.ratio)
|
||||
|
||||
self.cpu_label = ttk.Label(
|
||||
self, anchor=tk.CENTER, borderwidth=1, relief=tk.RIDGE
|
||||
|
|
|
@ -257,8 +257,8 @@ class Toolbar(ttk.Frame):
|
|||
|
||||
def draw_node_picker(self) -> None:
|
||||
self.hide_marker()
|
||||
self.app.canvas.mode = GraphMode.NODE
|
||||
self.app.canvas.node_draw = self.current_node
|
||||
self.app.manager.mode = GraphMode.NODE
|
||||
self.app.manager.node_draw = self.current_node
|
||||
self.design_frame.select_radio(self.node_button)
|
||||
self.picker = PickerFrame(self.app, self.node_button)
|
||||
# draw default nodes
|
||||
|
@ -278,7 +278,7 @@ class Toolbar(ttk.Frame):
|
|||
|
||||
def click_selection(self) -> None:
|
||||
self.design_frame.select_radio(self.select_button)
|
||||
self.app.canvas.mode = GraphMode.SELECT
|
||||
self.app.manager.mode = GraphMode.SELECT
|
||||
self.hide_marker()
|
||||
|
||||
def click_runtime_selection(self) -> None:
|
||||
|
@ -324,7 +324,7 @@ class Toolbar(ttk.Frame):
|
|||
|
||||
def click_link(self) -> None:
|
||||
self.design_frame.select_radio(self.link_button)
|
||||
self.app.canvas.mode = GraphMode.EDGE
|
||||
self.app.manager.mode = GraphMode.EDGE
|
||||
self.hide_marker()
|
||||
|
||||
def update_button(
|
||||
|
@ -337,7 +337,7 @@ class Toolbar(ttk.Frame):
|
|||
logging.debug("update button(%s): %s", button, node_draw)
|
||||
button.configure(image=image)
|
||||
button.image = image
|
||||
self.app.canvas.node_draw = node_draw
|
||||
self.app.manager.node_draw = node_draw
|
||||
if type_enum == NodeTypeEnum.NODE:
|
||||
self.current_node = node_draw
|
||||
elif type_enum == NodeTypeEnum.NETWORK:
|
||||
|
|
Loading…
Reference in a new issue