pygui: further refactoring to work towards multiple canvas support

This commit is contained in:
Blake Harnden 2020-12-11 18:39:58 -08:00
parent e34c00a431
commit 886bfc093b
8 changed files with 161 additions and 134 deletions

View file

@ -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)

View file

@ -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)

View file

@ -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:
"""

View file

@ -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()

View file

@ -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()

View file

@ -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)

View file

@ -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

View file

@ -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: