pygui: initial canvas manager with a single tab by default, updates to how throughputs are handled related to canvases
This commit is contained in:
parent
2f9c169e66
commit
f9a4fe3331
8 changed files with 59 additions and 61 deletions
|
@ -259,7 +259,7 @@ class CoreClient:
|
|||
if self.handling_throughputs:
|
||||
self.handling_throughputs.cancel()
|
||||
self.handling_throughputs = None
|
||||
self.app.canvas.clear_throughputs()
|
||||
self.app.manager.clear_throughputs()
|
||||
|
||||
def cancel_events(self) -> None:
|
||||
if self.handling_events:
|
||||
|
@ -290,7 +290,7 @@ class CoreClient:
|
|||
)
|
||||
return
|
||||
logging.debug("handling throughputs event: %s", event)
|
||||
self.app.after(0, self.app.canvas.set_throughputs, event)
|
||||
self.app.after(0, self.app.manager.set_throughputs, event)
|
||||
|
||||
def handle_cpu_event(self, event: core_pb2.CpuUsageEvent) -> None:
|
||||
self.app.after(0, self.app.statusbar.set_cpu, event.usage)
|
||||
|
|
|
@ -134,7 +134,8 @@ class PreferencesDialog(Dialog):
|
|||
|
||||
# scale toolbar and canvas items
|
||||
self.app.toolbar.scale()
|
||||
self.app.canvas.scale_graph()
|
||||
for canvas in self.app.manager.all():
|
||||
canvas.scale_graph()
|
||||
|
||||
def adjust_scale(self, arg1: str, arg2: str, arg3: str) -> None:
|
||||
scale_value = self.gui_scale.get()
|
||||
|
|
|
@ -7,7 +7,7 @@ from typing import TYPE_CHECKING, Optional
|
|||
|
||||
from core.gui.dialogs.colorpicker import ColorPickerDialog
|
||||
from core.gui.dialogs.dialog import Dialog
|
||||
from core.gui.graph.graph import CanvasGraph
|
||||
from core.gui.graph.manager import CanvasManager
|
||||
from core.gui.themes import FRAME_PAD, PADX, PADY
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
@ -17,16 +17,16 @@ if TYPE_CHECKING:
|
|||
class ThroughputDialog(Dialog):
|
||||
def __init__(self, app: "Application") -> None:
|
||||
super().__init__(app, "Throughput Config")
|
||||
self.canvas: CanvasGraph = app.canvas
|
||||
self.manager: CanvasManager = app.manager
|
||||
self.show_throughput: tk.IntVar = tk.IntVar(value=1)
|
||||
self.exponential_weight: tk.IntVar = tk.IntVar(value=1)
|
||||
self.transmission: tk.IntVar = tk.IntVar(value=1)
|
||||
self.reception: tk.IntVar = tk.IntVar(value=1)
|
||||
self.threshold: tk.DoubleVar = tk.DoubleVar(
|
||||
value=self.canvas.throughput_threshold
|
||||
value=self.manager.throughput_threshold
|
||||
)
|
||||
self.width: tk.IntVar = tk.IntVar(value=self.canvas.throughput_width)
|
||||
self.color: str = self.canvas.throughput_color
|
||||
self.width: tk.IntVar = tk.IntVar(value=self.manager.throughput_width)
|
||||
self.color: str = self.manager.throughput_color
|
||||
self.color_button: Optional[tk.Button] = None
|
||||
self.top.columnconfigure(0, weight=1)
|
||||
self.draw()
|
||||
|
@ -106,7 +106,7 @@ class ThroughputDialog(Dialog):
|
|||
self.color_button.config(bg=self.color, text=self.color, bd=0)
|
||||
|
||||
def click_save(self) -> None:
|
||||
self.canvas.throughput_threshold = self.threshold.get()
|
||||
self.canvas.throughput_width = self.width.get()
|
||||
self.canvas.throughput_color = self.color
|
||||
self.manager.throughput_threshold = self.threshold.get()
|
||||
self.manager.throughput_width = self.width.get()
|
||||
self.manager.throughput_color = self.color
|
||||
self.destroy()
|
||||
|
|
|
@ -21,7 +21,7 @@ RANGE_WIDTH: int = 3
|
|||
class WlanConfigDialog(Dialog):
|
||||
def __init__(self, app: "Application", canvas_node: "CanvasNode") -> None:
|
||||
super().__init__(app, f"{canvas_node.core_node.name} WLAN Configuration")
|
||||
self.canvas: "CanvasGraph" = app.canvas
|
||||
self.canvas: "CanvasGraph" = app.manager.current()
|
||||
self.canvas_node: "CanvasNode" = canvas_node
|
||||
self.node: Node = canvas_node.core_node
|
||||
self.config_frame: Optional[ConfigFrame] = None
|
||||
|
|
|
@ -357,9 +357,9 @@ class CanvasEdge(Edge):
|
|||
throughput = 0.001 * throughput
|
||||
text = f"{throughput:.3f} kbps"
|
||||
self.middle_label_text(text)
|
||||
if throughput > self.canvas.throughput_threshold:
|
||||
color = self.canvas.throughput_color
|
||||
width = self.canvas.throughput_width
|
||||
if throughput > self.canvas.manager.throughput_threshold:
|
||||
color = self.canvas.manager.throughput_color
|
||||
width = self.canvas.manager.throughput_width
|
||||
else:
|
||||
color = self.color
|
||||
width = self.scaled_width()
|
||||
|
|
|
@ -7,14 +7,7 @@ from typing import TYPE_CHECKING, Any, Dict, List, Optional, Set, Tuple
|
|||
from PIL import Image
|
||||
from PIL.ImageTk import PhotoImage
|
||||
|
||||
from core.api.grpc.wrappers import (
|
||||
Interface,
|
||||
Link,
|
||||
LinkType,
|
||||
Node,
|
||||
Session,
|
||||
ThroughputsEvent,
|
||||
)
|
||||
from core.api.grpc.wrappers import Interface, Link, LinkType, Node, Session
|
||||
from core.gui import appconfig
|
||||
from core.gui.dialogs.shapemod import ShapeDialog
|
||||
from core.gui.graph import tags
|
||||
|
@ -90,11 +83,6 @@ class CanvasGraph(tk.Canvas):
|
|||
self.scale_option: tk.IntVar = tk.IntVar(value=1)
|
||||
self.adjust_to_dim: tk.BooleanVar = tk.BooleanVar(value=False)
|
||||
|
||||
# throughput related
|
||||
self.throughput_threshold: float = 250.0
|
||||
self.throughput_width: int = 10
|
||||
self.throughput_color: str = "#FF0000"
|
||||
|
||||
# bindings
|
||||
self.setup_bindings()
|
||||
|
||||
|
@ -171,16 +159,6 @@ class CanvasGraph(tk.Canvas):
|
|||
valid_bottomright = self.inside_canvas(x2, y2)
|
||||
return valid_topleft and valid_bottomright
|
||||
|
||||
def set_throughputs(self, throughputs_event: ThroughputsEvent) -> None:
|
||||
for iface_throughput in throughputs_event.iface_throughputs:
|
||||
node_id = iface_throughput.node_id
|
||||
iface_id = iface_throughput.iface_id
|
||||
throughput = iface_throughput.throughput
|
||||
iface_to_edge_id = (node_id, iface_id)
|
||||
edge = self.core.iface_to_edge.get(iface_to_edge_id)
|
||||
if edge:
|
||||
edge.set_throughput(throughput)
|
||||
|
||||
def draw_grid(self) -> None:
|
||||
"""
|
||||
Create grid.
|
||||
|
|
|
@ -3,7 +3,7 @@ import tkinter as tk
|
|||
from tkinter import BooleanVar, messagebox, ttk
|
||||
from typing import TYPE_CHECKING, Any, Dict, Optional, Set, Tuple, ValuesView
|
||||
|
||||
from core.api.grpc.wrappers import LinkType, Session
|
||||
from core.api.grpc.wrappers import LinkType, Session, ThroughputsEvent
|
||||
from core.gui.graph import tags
|
||||
from core.gui.graph.enums import GraphMode
|
||||
from core.gui.graph.graph import CanvasGraph
|
||||
|
@ -74,6 +74,9 @@ class CanvasManager:
|
|||
self.unique_ids: Dict[str, int] = {}
|
||||
self.draw()
|
||||
|
||||
# start with a single tab by default
|
||||
self.add_canvas()
|
||||
|
||||
def draw(self) -> None:
|
||||
self.notebook = ttk.Notebook(self.master)
|
||||
self.notebook.grid(sticky=tk.NSEW, pady=1)
|
||||
|
@ -225,3 +228,18 @@ class CanvasManager:
|
|||
continue
|
||||
canvas = self.get(canvas_id)
|
||||
canvas.parse_metadata(canvas_config)
|
||||
|
||||
def set_throughputs(self, throughputs_event: ThroughputsEvent):
|
||||
for iface_throughput in throughputs_event.iface_throughputs:
|
||||
node_id = iface_throughput.node_id
|
||||
iface_id = iface_throughput.iface_id
|
||||
throughput = iface_throughput.throughput
|
||||
iface_to_edge_id = (node_id, iface_id)
|
||||
edge = self.core.iface_to_edge.get(iface_to_edge_id)
|
||||
if edge:
|
||||
edge.set_throughput(throughput)
|
||||
|
||||
def clear_throughputs(self) -> None:
|
||||
for canvas in self.all():
|
||||
for edge in canvas.edges.values():
|
||||
edge.clear_throughput()
|
||||
|
|
|
@ -45,7 +45,7 @@ class Menubar(tk.Menu):
|
|||
super().__init__(app)
|
||||
self.app: "Application" = app
|
||||
self.core: CoreClient = app.core
|
||||
self.canvas_manager: CanvasManager = app.manager
|
||||
self.manager: CanvasManager = app.manager
|
||||
self.recent_menu: Optional[tk.Menu] = None
|
||||
self.edit_menu: Optional[tk.Menu] = None
|
||||
self.observers_menu: Optional[ObserversMenu] = None
|
||||
|
@ -148,52 +148,52 @@ class Menubar(tk.Menu):
|
|||
menu.add_checkbutton(
|
||||
label="Interface Names",
|
||||
command=self.click_edge_label_change,
|
||||
variable=self.canvas_manager.show_iface_names,
|
||||
variable=self.manager.show_iface_names,
|
||||
)
|
||||
menu.add_checkbutton(
|
||||
label="IPv4 Addresses",
|
||||
command=self.click_edge_label_change,
|
||||
variable=self.canvas_manager.show_ip4s,
|
||||
variable=self.manager.show_ip4s,
|
||||
)
|
||||
menu.add_checkbutton(
|
||||
label="IPv6 Addresses",
|
||||
command=self.click_edge_label_change,
|
||||
variable=self.canvas_manager.show_ip6s,
|
||||
variable=self.manager.show_ip6s,
|
||||
)
|
||||
menu.add_checkbutton(
|
||||
label="Node Labels",
|
||||
command=self.canvas_manager.show_node_labels.click_handler,
|
||||
variable=self.canvas_manager.show_node_labels,
|
||||
command=self.manager.show_node_labels.click_handler,
|
||||
variable=self.manager.show_node_labels,
|
||||
)
|
||||
menu.add_checkbutton(
|
||||
label="Link Labels",
|
||||
command=self.canvas_manager.show_link_labels.click_handler,
|
||||
variable=self.canvas_manager.show_link_labels,
|
||||
command=self.manager.show_link_labels.click_handler,
|
||||
variable=self.manager.show_link_labels,
|
||||
)
|
||||
menu.add_checkbutton(
|
||||
label="Links",
|
||||
command=self.canvas_manager.show_links.click_handler,
|
||||
variable=self.canvas_manager.show_links,
|
||||
command=self.manager.show_links.click_handler,
|
||||
variable=self.manager.show_links,
|
||||
)
|
||||
menu.add_checkbutton(
|
||||
label="Loss Links",
|
||||
command=self.canvas_manager.show_loss_links.click_handler,
|
||||
variable=self.canvas_manager.show_loss_links,
|
||||
command=self.manager.show_loss_links.click_handler,
|
||||
variable=self.manager.show_loss_links,
|
||||
)
|
||||
menu.add_checkbutton(
|
||||
label="Wireless Links",
|
||||
command=self.canvas_manager.show_wireless.click_handler,
|
||||
variable=self.canvas_manager.show_wireless,
|
||||
command=self.manager.show_wireless.click_handler,
|
||||
variable=self.manager.show_wireless,
|
||||
)
|
||||
menu.add_checkbutton(
|
||||
label="Annotations",
|
||||
command=self.canvas_manager.show_annotations.click_handler,
|
||||
variable=self.canvas_manager.show_annotations,
|
||||
command=self.manager.show_annotations.click_handler,
|
||||
variable=self.manager.show_annotations,
|
||||
)
|
||||
menu.add_checkbutton(
|
||||
label="Canvas Grid",
|
||||
command=self.canvas_manager.show_grid.click_handler,
|
||||
variable=self.canvas_manager.show_grid,
|
||||
command=self.manager.show_grid.click_handler,
|
||||
variable=self.manager.show_grid,
|
||||
)
|
||||
self.add_cascade(label="View", menu=menu)
|
||||
|
||||
|
@ -376,10 +376,10 @@ class Menubar(tk.Menu):
|
|||
dialog.show()
|
||||
|
||||
def click_canvas_add(self) -> None:
|
||||
self.canvas_manager.add_canvas()
|
||||
self.manager.add_canvas()
|
||||
|
||||
def click_canvas_delete(self) -> None:
|
||||
self.canvas_manager.delete_canvas()
|
||||
self.manager.delete_canvas()
|
||||
|
||||
def click_canvas_size_and_scale(self) -> None:
|
||||
dialog = SizeAndScaleDialog(self.app)
|
||||
|
@ -448,14 +448,15 @@ class Menubar(tk.Menu):
|
|||
dialog.show()
|
||||
|
||||
def click_autogrid(self) -> None:
|
||||
width, height = self.canvas.current_dimensions
|
||||
width, height = self.manager.current_dimensions
|
||||
padding = (ICON_SIZE / 2) + 10
|
||||
layout_size = padding + ICON_SIZE
|
||||
col_count = width // layout_size
|
||||
logging.info(
|
||||
"auto grid layout: dimension(%s, %s) col(%s)", width, height, col_count
|
||||
)
|
||||
for i, node in enumerate(self.canvas.nodes.values()):
|
||||
canvas = self.manager.current()
|
||||
for i, node in enumerate(canvas.nodes.values()):
|
||||
col = i % col_count
|
||||
row = i // col_count
|
||||
x = (col * layout_size) + padding
|
||||
|
|
Loading…
Reference in a new issue