pygui: able to start session with multiple canvases, just using 1 canvas for now
This commit is contained in:
parent
6f43d0e88f
commit
9621df6bc4
5 changed files with 34 additions and 24 deletions
|
@ -13,7 +13,6 @@ from core.gui.coreclient import CoreClient
|
||||||
from core.gui.dialogs.error import ErrorDialog
|
from core.gui.dialogs.error import ErrorDialog
|
||||||
from core.gui.frames.base import InfoFrameBase
|
from core.gui.frames.base import InfoFrameBase
|
||||||
from core.gui.frames.default import DefaultInfoFrame
|
from core.gui.frames.default import DefaultInfoFrame
|
||||||
from core.gui.graph.graph import CanvasGraph
|
|
||||||
from core.gui.graph.manager import CanvasManager
|
from core.gui.graph.manager import CanvasManager
|
||||||
from core.gui.images import ImageEnum, Images
|
from core.gui.images import ImageEnum, Images
|
||||||
from core.gui.menubar import Menubar
|
from core.gui.menubar import Menubar
|
||||||
|
@ -37,7 +36,6 @@ class Application(ttk.Frame):
|
||||||
self.toolbar: Optional[Toolbar] = None
|
self.toolbar: Optional[Toolbar] = None
|
||||||
self.right_frame: Optional[ttk.Frame] = None
|
self.right_frame: Optional[ttk.Frame] = None
|
||||||
self.manager: Optional[CanvasManager] = None
|
self.manager: Optional[CanvasManager] = None
|
||||||
self.canvas: Optional[CanvasGraph] = None
|
|
||||||
self.statusbar: Optional[StatusBar] = None
|
self.statusbar: Optional[StatusBar] = None
|
||||||
self.progress: Optional[Progressbar] = None
|
self.progress: Optional[Progressbar] = None
|
||||||
self.infobar: Optional[ttk.Frame] = None
|
self.infobar: Optional[ttk.Frame] = None
|
||||||
|
|
|
@ -555,6 +555,8 @@ class CoreClient:
|
||||||
mobility_player.show()
|
mobility_player.show()
|
||||||
|
|
||||||
def set_metadata(self) -> None:
|
def set_metadata(self) -> None:
|
||||||
|
# TODO: handle metadata for multiple canvases
|
||||||
|
return
|
||||||
# create canvas data
|
# create canvas data
|
||||||
wallpaper_path = None
|
wallpaper_path = None
|
||||||
if self.app.canvas.wallpaper_file:
|
if self.app.canvas.wallpaper_file:
|
||||||
|
|
|
@ -145,7 +145,7 @@ class Edge:
|
||||||
text=text,
|
text=text,
|
||||||
tags=tags.LINK_LABEL,
|
tags=tags.LINK_LABEL,
|
||||||
justify=tk.CENTER,
|
justify=tk.CENTER,
|
||||||
state=self.canvas.show_link_labels.state(),
|
state=self.canvas.manager.show_link_labels.state(),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
self.canvas.itemconfig(self.middle_label, text=text)
|
self.canvas.itemconfig(self.middle_label, text=text)
|
||||||
|
@ -177,7 +177,7 @@ class Edge:
|
||||||
justify=tk.CENTER,
|
justify=tk.CENTER,
|
||||||
font=self.canvas.app.edge_font,
|
font=self.canvas.app.edge_font,
|
||||||
tags=tags.LINK_LABEL,
|
tags=tags.LINK_LABEL,
|
||||||
state=self.canvas.show_link_labels.state(),
|
state=self.canvas.manager.show_link_labels.state(),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
self.canvas.itemconfig(self.src_label, text=text)
|
self.canvas.itemconfig(self.src_label, text=text)
|
||||||
|
@ -191,7 +191,7 @@ class Edge:
|
||||||
justify=tk.CENTER,
|
justify=tk.CENTER,
|
||||||
font=self.canvas.app.edge_font,
|
font=self.canvas.app.edge_font,
|
||||||
tags=tags.LINK_LABEL,
|
tags=tags.LINK_LABEL,
|
||||||
state=self.canvas.show_link_labels.state(),
|
state=self.canvas.manager.show_link_labels.state(),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
self.canvas.itemconfig(self.dst_label, text=text)
|
self.canvas.itemconfig(self.dst_label, text=text)
|
||||||
|
@ -256,7 +256,7 @@ class CanvasWirelessEdge(Edge):
|
||||||
self.width: float = WIRELESS_WIDTH
|
self.width: float = WIRELESS_WIDTH
|
||||||
color = link.color if link.color else WIRELESS_COLOR
|
color = link.color if link.color else WIRELESS_COLOR
|
||||||
self.color: str = color
|
self.color: str = color
|
||||||
self.draw(src_pos, dst_pos, self.canvas.show_wireless.state())
|
self.draw(src_pos, dst_pos, self.canvas.manager.show_wireless.state())
|
||||||
if link.label:
|
if link.label:
|
||||||
self.middle_label_text(link.label)
|
self.middle_label_text(link.label)
|
||||||
self.set_binding()
|
self.set_binding()
|
||||||
|
@ -311,12 +311,12 @@ class CanvasEdge(Edge):
|
||||||
|
|
||||||
def iface_label(self, iface: Interface) -> str:
|
def iface_label(self, iface: Interface) -> str:
|
||||||
label = ""
|
label = ""
|
||||||
if iface.name and self.canvas.show_iface_names.get():
|
if iface.name and self.canvas.manager.show_iface_names.get():
|
||||||
label = f"{iface.name}"
|
label = f"{iface.name}"
|
||||||
if iface.ip4 and self.canvas.show_ip4s.get():
|
if iface.ip4 and self.canvas.manager.show_ip4s.get():
|
||||||
label = f"{label}\n" if label else ""
|
label = f"{label}\n" if label else ""
|
||||||
label += f"{iface.ip4}/{iface.ip4_mask}"
|
label += f"{iface.ip4}/{iface.ip4_mask}"
|
||||||
if iface.ip6 and self.canvas.show_ip6s.get():
|
if iface.ip6 and self.canvas.manager.show_ip6s.get():
|
||||||
label = f"{label}\n" if label else ""
|
label = f"{label}\n" if label else ""
|
||||||
label += f"{iface.ip6}/{iface.ip6_mask}"
|
label += f"{iface.ip6}/{iface.ip6_mask}"
|
||||||
return label
|
return label
|
||||||
|
@ -350,7 +350,7 @@ class CanvasEdge(Edge):
|
||||||
else:
|
else:
|
||||||
state = tk.NORMAL
|
state = tk.NORMAL
|
||||||
self.canvas.dtag(self.id, tags.LOSS_EDGES)
|
self.canvas.dtag(self.id, tags.LOSS_EDGES)
|
||||||
if self.canvas.show_loss_links.state() == tk.HIDDEN:
|
if self.canvas.manager.show_loss_links.state() == tk.HIDDEN:
|
||||||
self.canvas.itemconfigure(self.id, state=state)
|
self.canvas.itemconfigure(self.id, state=state)
|
||||||
|
|
||||||
def set_throughput(self, throughput: float) -> None:
|
def set_throughput(self, throughput: float) -> None:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import logging
|
import logging
|
||||||
import tkinter as tk
|
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
|
from typing import TYPE_CHECKING, Dict, Optional, Set, Tuple, ValuesView
|
||||||
|
|
||||||
from core.api.grpc.wrappers import Session
|
from core.api.grpc.wrappers import Session
|
||||||
from core.gui.graph import tags
|
from core.gui.graph import tags
|
||||||
|
@ -77,20 +77,28 @@ class CanvasManager:
|
||||||
self.notebook = ttk.Notebook(self.master)
|
self.notebook = ttk.Notebook(self.master)
|
||||||
self.notebook.grid(sticky=tk.NSEW, pady=1)
|
self.notebook.grid(sticky=tk.NSEW, pady=1)
|
||||||
|
|
||||||
def next_id(self) -> int:
|
def _next_id(self) -> int:
|
||||||
_id = 1
|
_id = 1
|
||||||
tab_ids = set(self.unique_ids.values())
|
tab_ids = set(self.unique_ids.values())
|
||||||
while _id in tab_ids:
|
while _id in tab_ids:
|
||||||
_id += 1
|
_id += 1
|
||||||
return _id
|
return _id
|
||||||
|
|
||||||
|
def current(self) -> CanvasGraph:
|
||||||
|
unique_id = self.notebook.select()
|
||||||
|
tab_id = self.unique_ids[unique_id]
|
||||||
|
return self.canvases[tab_id]
|
||||||
|
|
||||||
|
def all(self) -> ValuesView[CanvasGraph]:
|
||||||
|
return self.canvases.values()
|
||||||
|
|
||||||
def add_canvas(self) -> CanvasGraph:
|
def add_canvas(self) -> 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()
|
tab_id = self._next_id()
|
||||||
self.notebook.add(tab, text=f"Canvas {tab_id}")
|
self.notebook.add(tab, text=f"Canvas {tab_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, tab_id)
|
||||||
|
|
|
@ -144,7 +144,8 @@ class MarkerFrame(ttk.Frame):
|
||||||
Tooltip(self.color_frame, "Marker Color")
|
Tooltip(self.color_frame, "Marker Color")
|
||||||
|
|
||||||
def click_clear(self) -> None:
|
def click_clear(self) -> None:
|
||||||
self.app.canvas.delete(tags.MARKER)
|
canvas = self.app.manager.current()
|
||||||
|
canvas.delete(tags.MARKER)
|
||||||
|
|
||||||
def click_color(self, _event: tk.Event) -> None:
|
def click_color(self, _event: tk.Event) -> None:
|
||||||
dialog = ColorPickerDialog(self.app, self.app, self.color)
|
dialog = ColorPickerDialog(self.app, self.app, self.color)
|
||||||
|
@ -283,7 +284,7 @@ class Toolbar(ttk.Frame):
|
||||||
|
|
||||||
def click_runtime_selection(self) -> None:
|
def click_runtime_selection(self) -> None:
|
||||||
self.runtime_frame.select_radio(self.runtime_select_button)
|
self.runtime_frame.select_radio(self.runtime_select_button)
|
||||||
self.app.canvas.mode = GraphMode.SELECT
|
self.app.manager.mode = GraphMode.SELECT
|
||||||
self.hide_marker()
|
self.hide_marker()
|
||||||
|
|
||||||
def click_start(self) -> None:
|
def click_start(self) -> None:
|
||||||
|
@ -292,7 +293,7 @@ class Toolbar(ttk.Frame):
|
||||||
server.
|
server.
|
||||||
"""
|
"""
|
||||||
self.app.menubar.change_menubar_item_state(is_runtime=True)
|
self.app.menubar.change_menubar_item_state(is_runtime=True)
|
||||||
self.app.canvas.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(
|
||||||
self.app, "Start", self.app.core.start_session, self.start_callback
|
self.app, "Start", self.app.core.start_session, self.start_callback
|
||||||
|
@ -348,8 +349,8 @@ class Toolbar(ttk.Frame):
|
||||||
Draw the options for link-layer button.
|
Draw the options for link-layer button.
|
||||||
"""
|
"""
|
||||||
self.hide_marker()
|
self.hide_marker()
|
||||||
self.app.canvas.mode = GraphMode.NODE
|
self.app.manager.mode = GraphMode.NODE
|
||||||
self.app.canvas.node_draw = self.current_network
|
self.app.manager.node_draw = self.current_network
|
||||||
self.design_frame.select_radio(self.network_button)
|
self.design_frame.select_radio(self.network_button)
|
||||||
self.picker = PickerFrame(self.app, self.network_button)
|
self.picker = PickerFrame(self.app, self.network_button)
|
||||||
for node_draw in NodeUtils.NETWORK_NODES:
|
for node_draw in NodeUtils.NETWORK_NODES:
|
||||||
|
@ -364,8 +365,8 @@ class Toolbar(ttk.Frame):
|
||||||
Draw the options for marker button.
|
Draw the options for marker button.
|
||||||
"""
|
"""
|
||||||
self.design_frame.select_radio(self.annotation_button)
|
self.design_frame.select_radio(self.annotation_button)
|
||||||
self.app.canvas.mode = GraphMode.ANNOTATION
|
self.app.manager.mode = GraphMode.ANNOTATION
|
||||||
self.app.canvas.annotation_type = self.current_annotation
|
self.app.manager.annotation_type = self.current_annotation
|
||||||
if is_marker(self.current_annotation):
|
if is_marker(self.current_annotation):
|
||||||
self.show_marker()
|
self.show_marker()
|
||||||
self.picker = PickerFrame(self.app, self.annotation_button)
|
self.picker = PickerFrame(self.app, self.annotation_button)
|
||||||
|
@ -406,7 +407,8 @@ class Toolbar(ttk.Frame):
|
||||||
|
|
||||||
def stop_callback(self, result: bool) -> None:
|
def stop_callback(self, result: bool) -> None:
|
||||||
self.set_design()
|
self.set_design()
|
||||||
self.app.canvas.stopped_session()
|
for canvas in self.app.manager.all():
|
||||||
|
canvas.stopped_session()
|
||||||
|
|
||||||
def update_annotation(
|
def update_annotation(
|
||||||
self, shape_type: ShapeType, image_enum: ImageEnum, image: PhotoImage
|
self, shape_type: ShapeType, image_enum: ImageEnum, image: PhotoImage
|
||||||
|
@ -414,7 +416,7 @@ class Toolbar(ttk.Frame):
|
||||||
logging.debug("clicked annotation")
|
logging.debug("clicked annotation")
|
||||||
self.annotation_button.configure(image=image)
|
self.annotation_button.configure(image=image)
|
||||||
self.annotation_button.image = image
|
self.annotation_button.image = image
|
||||||
self.app.canvas.annotation_type = shape_type
|
self.app.manager.annotation_type = shape_type
|
||||||
self.current_annotation = shape_type
|
self.current_annotation = shape_type
|
||||||
self.annotation_enum = image_enum
|
self.annotation_enum = image_enum
|
||||||
if is_marker(shape_type):
|
if is_marker(shape_type):
|
||||||
|
@ -435,8 +437,8 @@ class Toolbar(ttk.Frame):
|
||||||
|
|
||||||
def click_marker_button(self) -> None:
|
def click_marker_button(self) -> None:
|
||||||
self.runtime_frame.select_radio(self.runtime_marker_button)
|
self.runtime_frame.select_radio(self.runtime_marker_button)
|
||||||
self.app.canvas.mode = GraphMode.ANNOTATION
|
self.app.manager.mode = GraphMode.ANNOTATION
|
||||||
self.app.canvas.annotation_type = ShapeType.MARKER
|
self.app.manager.annotation_type = ShapeType.MARKER
|
||||||
self.show_marker()
|
self.show_marker()
|
||||||
|
|
||||||
def scale_button(
|
def scale_button(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue