renamed python gui to be more similar to other core scripts and specific to it being python, some cleanup to pygui edge drawing and updates to allow for edges to have an arc to support multiple links between the same nodes
This commit is contained in:
parent
8c8024df10
commit
cd8157eff7
6 changed files with 154 additions and 120 deletions
|
@ -5,7 +5,7 @@ verify_ssl = true
|
||||||
|
|
||||||
[scripts]
|
[scripts]
|
||||||
core = "python scripts/core-daemon -f data/core.conf -l data/logging.conf"
|
core = "python scripts/core-daemon -f data/core.conf -l data/logging.conf"
|
||||||
coretk = "python scripts/coretk-gui"
|
core-pygui = "python scripts/core-pygui"
|
||||||
test = "pytest -v tests"
|
test = "pytest -v tests"
|
||||||
test-mock = "pytest -v --mock tests"
|
test-mock = "pytest -v --mock tests"
|
||||||
test-emane = "pytest -v tests/emane"
|
test-emane = "pytest -v tests/emane"
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
import logging
|
import logging
|
||||||
|
import math
|
||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
from typing import TYPE_CHECKING, Any, Tuple
|
from typing import TYPE_CHECKING, Any, Tuple
|
||||||
|
|
||||||
|
from core.api.grpc import core_pb2
|
||||||
from core.gui import themes
|
from core.gui import themes
|
||||||
from core.gui.dialogs.linkconfig import LinkConfigurationDialog
|
from core.gui.dialogs.linkconfig import LinkConfigurationDialog
|
||||||
from core.gui.graph import tags
|
from core.gui.graph import tags
|
||||||
from core.gui.nodeutils import EdgeUtils, NodeUtils
|
from core.gui.nodeutils import NodeUtils
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from core.gui.graph.graph import CanvasGraph
|
from core.gui.graph.graph import CanvasGraph
|
||||||
|
@ -17,80 +19,142 @@ WIRELESS_WIDTH = 1.5
|
||||||
WIRELESS_COLOR = "#009933"
|
WIRELESS_COLOR = "#009933"
|
||||||
|
|
||||||
|
|
||||||
class CanvasWirelessEdge:
|
def interface_label(interface: core_pb2.Interface) -> str:
|
||||||
def __init__(
|
label = ""
|
||||||
self,
|
if interface.ip4:
|
||||||
token: Tuple[Any, ...],
|
label = f"{interface.ip4}/{interface.ip4mask}"
|
||||||
position: Tuple[float, float, float, float],
|
if interface.ip6:
|
||||||
src: int,
|
label = f"{label}\n{interface.ip6}/{interface.ip6mask}"
|
||||||
dst: int,
|
return label
|
||||||
canvas: "CanvasGraph",
|
|
||||||
):
|
|
||||||
logging.debug("Draw wireless link from node %s to node %s", src, dst)
|
def create_edge_token(src: int, dst: int) -> Tuple[int, ...]:
|
||||||
self.token = token
|
return tuple(sorted([src, dst]))
|
||||||
|
|
||||||
|
|
||||||
|
class Edge:
|
||||||
|
tag = tags.EDGE
|
||||||
|
|
||||||
|
def __init__(self, canvas: "CanvasGraph", src: int, dst: int = None) -> None:
|
||||||
|
self.canvas = canvas
|
||||||
|
self.id = None
|
||||||
self.src = src
|
self.src = src
|
||||||
self.dst = dst
|
self.dst = dst
|
||||||
self.canvas = canvas
|
self.arc = 0
|
||||||
|
self.token = None
|
||||||
|
self.color = EDGE_COLOR
|
||||||
|
self.width = EDGE_WIDTH
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create_token(cls, src: int, dst: int) -> Tuple[int, ...]:
|
||||||
|
return tuple(sorted([src, dst]))
|
||||||
|
|
||||||
|
def _get_midpoint(
|
||||||
|
self, src_pos: Tuple[float, float], dst_pos: Tuple[float, float]
|
||||||
|
) -> Tuple[float, float]:
|
||||||
|
src_x, src_y = src_pos
|
||||||
|
dst_x, dst_y = dst_pos
|
||||||
|
t = math.atan2(dst_y - src_y, dst_x - src_y)
|
||||||
|
x_mp = (src_x + dst_x) / 2 + self.arc * math.sin(t)
|
||||||
|
y_mp = (src_y + dst_y) / 2 - self.arc * math.cos(t)
|
||||||
|
return x_mp, y_mp
|
||||||
|
|
||||||
|
def draw(self, src_pos: Tuple[float, float], dst_pos: Tuple[float, float]) -> None:
|
||||||
|
mid_pos = self._get_midpoint(src_pos, dst_pos)
|
||||||
self.id = self.canvas.create_line(
|
self.id = self.canvas.create_line(
|
||||||
*position,
|
*src_pos,
|
||||||
tags=tags.WIRELESS_EDGE,
|
*mid_pos,
|
||||||
width=WIRELESS_WIDTH * self.canvas.app.app_scale,
|
*dst_pos,
|
||||||
fill=WIRELESS_COLOR,
|
smooth=True,
|
||||||
|
tags=self.tag,
|
||||||
|
width=self.width * self.canvas.app.app_scale,
|
||||||
|
fill=self.color,
|
||||||
)
|
)
|
||||||
|
|
||||||
def delete(self):
|
def move_node(self, node_id: int, x: float, y: float) -> None:
|
||||||
|
if self.src == node_id:
|
||||||
|
self.move_src(x, y)
|
||||||
|
else:
|
||||||
|
self.move_dst(x, y)
|
||||||
|
|
||||||
|
def move_dst(self, x: float, y: float) -> None:
|
||||||
|
dst_pos = (x, y)
|
||||||
|
src_x, src_y, _, _, _, _ = self.canvas.coords(self.id)
|
||||||
|
src_pos = (src_x, src_y)
|
||||||
|
mid_pos = self._get_midpoint(src_pos, dst_pos)
|
||||||
|
self.canvas.coords(self.id, *src_pos, *mid_pos, *dst_pos)
|
||||||
|
|
||||||
|
def move_src(self, x: float, y: float) -> None:
|
||||||
|
src_pos = (x, y)
|
||||||
|
_, _, _, _, dst_x, dst_y = self.canvas.coords(self.id)
|
||||||
|
dst_pos = (dst_x, dst_y)
|
||||||
|
mid_pos = self._get_midpoint(src_pos, dst_pos)
|
||||||
|
self.canvas.coords(self.id, *src_pos, *mid_pos, *dst_pos)
|
||||||
|
|
||||||
|
def delete(self) -> None:
|
||||||
self.canvas.delete(self.id)
|
self.canvas.delete(self.id)
|
||||||
|
|
||||||
|
|
||||||
class CanvasEdge:
|
class CanvasWirelessEdge(Edge):
|
||||||
|
tag = tags.WIRELESS_EDGE
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
canvas: "CanvasGraph",
|
||||||
|
src: int,
|
||||||
|
dst: int,
|
||||||
|
src_pos: Tuple[float, float],
|
||||||
|
dst_pos: Tuple[float, float],
|
||||||
|
token: Tuple[Any, ...],
|
||||||
|
) -> None:
|
||||||
|
logging.debug("drawing wireless link from node %s to node %s", src, dst)
|
||||||
|
super().__init__(canvas, src, dst)
|
||||||
|
self.token = token
|
||||||
|
self.width = WIRELESS_WIDTH
|
||||||
|
self.color = WIRELESS_COLOR
|
||||||
|
self.draw(src_pos, dst_pos)
|
||||||
|
|
||||||
|
|
||||||
|
class CanvasEdge(Edge):
|
||||||
"""
|
"""
|
||||||
Canvas edge class
|
Canvas edge class
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
x1: float,
|
|
||||||
y1: float,
|
|
||||||
x2: float,
|
|
||||||
y2: float,
|
|
||||||
src: int,
|
|
||||||
canvas: "CanvasGraph",
|
canvas: "CanvasGraph",
|
||||||
):
|
src: int,
|
||||||
|
src_pos: Tuple[float, float],
|
||||||
|
dst_pos: Tuple[float, float],
|
||||||
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Create an instance of canvas edge object
|
Create an instance of canvas edge object
|
||||||
"""
|
"""
|
||||||
self.src = src
|
super().__init__(canvas, src)
|
||||||
self.dst = None
|
|
||||||
self.src_interface = None
|
self.src_interface = None
|
||||||
self.dst_interface = None
|
self.dst_interface = None
|
||||||
self.canvas = canvas
|
|
||||||
self.id = self.canvas.create_line(
|
|
||||||
x1,
|
|
||||||
y1,
|
|
||||||
x2,
|
|
||||||
y2,
|
|
||||||
tags=tags.EDGE,
|
|
||||||
width=EDGE_WIDTH * self.canvas.app.app_scale,
|
|
||||||
fill=EDGE_COLOR,
|
|
||||||
)
|
|
||||||
self.text_src = None
|
self.text_src = None
|
||||||
self.text_dst = None
|
self.text_dst = None
|
||||||
self.text_middle = None
|
self.text_middle = None
|
||||||
self.token = None
|
|
||||||
self.link = None
|
self.link = None
|
||||||
self.asymmetric_link = None
|
self.asymmetric_link = None
|
||||||
self.throughput = None
|
self.throughput = None
|
||||||
|
self.draw(src_pos, dst_pos)
|
||||||
self.set_binding()
|
self.set_binding()
|
||||||
|
|
||||||
def set_binding(self):
|
def move_node(self, node_id: int, x: float, y: float) -> None:
|
||||||
|
super().move_node(node_id, x, y)
|
||||||
|
self.update_labels()
|
||||||
|
|
||||||
|
def set_binding(self) -> None:
|
||||||
self.canvas.tag_bind(self.id, "<ButtonRelease-3>", self.create_context)
|
self.canvas.tag_bind(self.id, "<ButtonRelease-3>", self.create_context)
|
||||||
|
|
||||||
def set_link(self, link):
|
def set_link(self, link) -> None:
|
||||||
self.link = link
|
self.link = link
|
||||||
self.draw_labels()
|
self.draw_labels()
|
||||||
|
|
||||||
def get_coordinates(self) -> [float, float, float, float]:
|
def get_coordinates(self) -> [float, float, float, float]:
|
||||||
x1, y1, x2, y2 = self.canvas.coords(self.id)
|
x1, y1, _, _, x2, y2 = self.canvas.coords(self.id)
|
||||||
v1 = x2 - x1
|
v1 = x2 - x1
|
||||||
v2 = y2 - y1
|
v2 = y2 - y1
|
||||||
ux = TEXT_DISTANCE * v1
|
ux = TEXT_DISTANCE * v1
|
||||||
|
@ -107,24 +171,16 @@ class CanvasEdge:
|
||||||
y = (y1 + y2) / 2
|
y = (y1 + y2) / 2
|
||||||
return x, y
|
return x, y
|
||||||
|
|
||||||
def create_labels(self):
|
def create_labels(self) -> Tuple[str, str]:
|
||||||
label_one = None
|
label_one = None
|
||||||
if self.link.HasField("interface_one"):
|
if self.link.HasField("interface_one"):
|
||||||
label_one = self.create_label(self.link.interface_one)
|
label_one = interface_label(self.link.interface_one)
|
||||||
label_two = None
|
label_two = None
|
||||||
if self.link.HasField("interface_two"):
|
if self.link.HasField("interface_two"):
|
||||||
label_two = self.create_label(self.link.interface_two)
|
label_two = interface_label(self.link.interface_two)
|
||||||
return label_one, label_two
|
return label_one, label_two
|
||||||
|
|
||||||
def create_label(self, interface):
|
def draw_labels(self) -> None:
|
||||||
label = ""
|
|
||||||
if interface.ip4:
|
|
||||||
label = f"{interface.ip4}/{interface.ip4mask}"
|
|
||||||
if interface.ip6:
|
|
||||||
label = f"{label}\n{interface.ip6}/{interface.ip6mask}"
|
|
||||||
return label
|
|
||||||
|
|
||||||
def draw_labels(self):
|
|
||||||
x1, y1, x2, y2 = self.get_coordinates()
|
x1, y1, x2, y2 = self.get_coordinates()
|
||||||
label_one, label_two = self.create_labels()
|
label_one, label_two = self.create_labels()
|
||||||
self.text_src = self.canvas.create_text(
|
self.text_src = self.canvas.create_text(
|
||||||
|
@ -144,12 +200,12 @@ class CanvasEdge:
|
||||||
tags=tags.LINK_INFO,
|
tags=tags.LINK_INFO,
|
||||||
)
|
)
|
||||||
|
|
||||||
def redraw(self):
|
def redraw(self) -> None:
|
||||||
label_one, label_two = self.create_labels()
|
label_one, label_two = self.create_labels()
|
||||||
self.canvas.itemconfig(self.text_src, text=label_one)
|
self.canvas.itemconfig(self.text_src, text=label_one)
|
||||||
self.canvas.itemconfig(self.text_dst, text=label_two)
|
self.canvas.itemconfig(self.text_dst, text=label_two)
|
||||||
|
|
||||||
def update_labels(self):
|
def update_labels(self) -> None:
|
||||||
"""
|
"""
|
||||||
Move edge labels based on current position.
|
Move edge labels based on current position.
|
||||||
"""
|
"""
|
||||||
|
@ -160,7 +216,7 @@ class CanvasEdge:
|
||||||
x, y = self.get_midpoint()
|
x, y = self.get_midpoint()
|
||||||
self.canvas.coords(self.text_middle, x, y)
|
self.canvas.coords(self.text_middle, x, y)
|
||||||
|
|
||||||
def set_throughput(self, throughput: float):
|
def set_throughput(self, throughput: float) -> None:
|
||||||
throughput = 0.001 * throughput
|
throughput = 0.001 * throughput
|
||||||
value = f"{throughput:.3f} kbps"
|
value = f"{throughput:.3f} kbps"
|
||||||
if self.text_middle is None:
|
if self.text_middle is None:
|
||||||
|
@ -179,18 +235,17 @@ class CanvasEdge:
|
||||||
width = EDGE_WIDTH
|
width = EDGE_WIDTH
|
||||||
self.canvas.itemconfig(self.id, fill=color, width=width)
|
self.canvas.itemconfig(self.id, fill=color, width=width)
|
||||||
|
|
||||||
def complete(self, dst: int):
|
def complete(self, dst: int) -> None:
|
||||||
self.dst = dst
|
self.dst = dst
|
||||||
self.token = EdgeUtils.get_token(self.src, self.dst)
|
self.token = create_edge_token(self.src, self.dst)
|
||||||
x, y = self.canvas.coords(self.dst)
|
x, y = self.canvas.coords(self.dst)
|
||||||
x1, y1, _, _ = self.canvas.coords(self.id)
|
self.move_dst(x, y)
|
||||||
self.canvas.coords(self.id, x1, y1, x, y)
|
|
||||||
self.check_wireless()
|
self.check_wireless()
|
||||||
self.canvas.tag_raise(self.src)
|
self.canvas.tag_raise(self.src)
|
||||||
self.canvas.tag_raise(self.dst)
|
self.canvas.tag_raise(self.dst)
|
||||||
logging.debug("Draw wired link from node %s to node %s", self.src, dst)
|
logging.debug("Draw wired link from node %s to node %s", self.src, dst)
|
||||||
|
|
||||||
def is_wireless(self) -> [bool, bool]:
|
def is_wireless(self) -> bool:
|
||||||
src_node = self.canvas.nodes[self.src]
|
src_node = self.canvas.nodes[self.src]
|
||||||
dst_node = self.canvas.nodes[self.dst]
|
dst_node = self.canvas.nodes[self.dst]
|
||||||
src_node_type = src_node.core_node.type
|
src_node_type = src_node.core_node.type
|
||||||
|
@ -210,12 +265,12 @@ class CanvasEdge:
|
||||||
wlan_network[self.dst].add(self.src)
|
wlan_network[self.dst].add(self.src)
|
||||||
return is_src_wireless or is_dst_wireless
|
return is_src_wireless or is_dst_wireless
|
||||||
|
|
||||||
def check_wireless(self):
|
def check_wireless(self) -> None:
|
||||||
if self.is_wireless():
|
if self.is_wireless():
|
||||||
self.canvas.itemconfig(self.id, state=tk.HIDDEN)
|
self.canvas.itemconfig(self.id, state=tk.HIDDEN)
|
||||||
self._check_antenna()
|
self._check_antenna()
|
||||||
|
|
||||||
def _check_antenna(self):
|
def _check_antenna(self) -> None:
|
||||||
src_node = self.canvas.nodes[self.src]
|
src_node = self.canvas.nodes[self.src]
|
||||||
dst_node = self.canvas.nodes[self.dst]
|
dst_node = self.canvas.nodes[self.dst]
|
||||||
src_node_type = src_node.core_node.type
|
src_node_type = src_node.core_node.type
|
||||||
|
@ -230,20 +285,19 @@ class CanvasEdge:
|
||||||
else:
|
else:
|
||||||
src_node.add_antenna()
|
src_node.add_antenna()
|
||||||
|
|
||||||
def delete(self):
|
def delete(self) -> None:
|
||||||
logging.debug("Delete canvas edge, id: %s", self.id)
|
logging.debug("Delete canvas edge, id: %s", self.id)
|
||||||
self.canvas.delete(self.id)
|
super().delete()
|
||||||
if self.link:
|
|
||||||
self.canvas.delete(self.text_src)
|
self.canvas.delete(self.text_src)
|
||||||
self.canvas.delete(self.text_dst)
|
self.canvas.delete(self.text_dst)
|
||||||
self.canvas.delete(self.text_middle)
|
self.canvas.delete(self.text_middle)
|
||||||
|
|
||||||
def reset(self):
|
def reset(self) -> None:
|
||||||
self.canvas.delete(self.text_middle)
|
self.canvas.delete(self.text_middle)
|
||||||
self.text_middle = None
|
self.text_middle = None
|
||||||
self.canvas.itemconfig(self.id, fill=EDGE_COLOR, width=EDGE_WIDTH)
|
self.canvas.itemconfig(self.id, fill=EDGE_COLOR, width=EDGE_WIDTH)
|
||||||
|
|
||||||
def create_context(self, event: tk.Event):
|
def create_context(self, event: tk.Event) -> None:
|
||||||
context = tk.Menu(self.canvas)
|
context = tk.Menu(self.canvas)
|
||||||
themes.style_menu(context)
|
themes.style_menu(context)
|
||||||
context.add_command(label="Configure", command=self.configure)
|
context.add_command(label="Configure", command=self.configure)
|
||||||
|
@ -256,6 +310,6 @@ class CanvasEdge:
|
||||||
context.entryconfigure(3, state="disabled")
|
context.entryconfigure(3, state="disabled")
|
||||||
context.post(event.x_root, event.y_root)
|
context.post(event.x_root, event.y_root)
|
||||||
|
|
||||||
def configure(self):
|
def configure(self) -> None:
|
||||||
dialog = LinkConfigurationDialog(self.canvas, self.canvas.app, self)
|
dialog = LinkConfigurationDialog(self.canvas, self.canvas.app, self)
|
||||||
dialog.show()
|
dialog.show()
|
||||||
|
|
|
@ -7,13 +7,18 @@ from PIL import Image, ImageTk
|
||||||
from core.api.grpc import core_pb2
|
from core.api.grpc import core_pb2
|
||||||
from core.gui.dialogs.shapemod import ShapeDialog
|
from core.gui.dialogs.shapemod import ShapeDialog
|
||||||
from core.gui.graph import tags
|
from core.gui.graph import tags
|
||||||
from core.gui.graph.edges import EDGE_WIDTH, CanvasEdge, CanvasWirelessEdge
|
from core.gui.graph.edges import (
|
||||||
|
EDGE_WIDTH,
|
||||||
|
CanvasEdge,
|
||||||
|
CanvasWirelessEdge,
|
||||||
|
create_edge_token,
|
||||||
|
)
|
||||||
from core.gui.graph.enums import GraphMode, ScaleOption
|
from core.gui.graph.enums import GraphMode, ScaleOption
|
||||||
from core.gui.graph.node import CanvasNode
|
from core.gui.graph.node import CanvasNode
|
||||||
from core.gui.graph.shape import Shape
|
from core.gui.graph.shape import Shape
|
||||||
from core.gui.graph.shapeutils import ShapeType, is_draw_shape, is_marker
|
from core.gui.graph.shapeutils import ShapeType, is_draw_shape, is_marker
|
||||||
from core.gui.images import ImageEnum, Images, TypeToImage
|
from core.gui.images import ImageEnum, Images, TypeToImage
|
||||||
from core.gui.nodeutils import EdgeUtils, NodeUtils
|
from core.gui.nodeutils import NodeUtils
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from core.gui.app import Application
|
from core.gui.app import Application
|
||||||
|
@ -197,11 +202,10 @@ class CanvasGraph(tk.Canvas):
|
||||||
"""
|
"""
|
||||||
add a wireless edge between 2 canvas nodes
|
add a wireless edge between 2 canvas nodes
|
||||||
"""
|
"""
|
||||||
token = EdgeUtils.get_token(src.id, dst.id)
|
token = create_edge_token(src.id, dst.id)
|
||||||
x1, y1 = self.coords(src.id)
|
src_pos = self.coords(src.id)
|
||||||
x2, y2 = self.coords(dst.id)
|
dst_pos = self.coords(dst.id)
|
||||||
position = (x1, y1, x2, y2)
|
edge = CanvasWirelessEdge(self, src.id, dst.id, src_pos, dst_pos, token)
|
||||||
edge = CanvasWirelessEdge(token, position, src.id, dst.id, self)
|
|
||||||
self.wireless_edges[token] = edge
|
self.wireless_edges[token] = edge
|
||||||
src.wireless_edges.add(edge)
|
src.wireless_edges.add(edge)
|
||||||
dst.wireless_edges.add(edge)
|
dst.wireless_edges.add(edge)
|
||||||
|
@ -209,7 +213,7 @@ class CanvasGraph(tk.Canvas):
|
||||||
self.tag_raise(dst.id)
|
self.tag_raise(dst.id)
|
||||||
|
|
||||||
def delete_wireless_edge(self, src: CanvasNode, dst: CanvasNode):
|
def delete_wireless_edge(self, src: CanvasNode, dst: CanvasNode):
|
||||||
token = EdgeUtils.get_token(src.id, dst.id)
|
token = create_edge_token(src.id, dst.id)
|
||||||
edge = self.wireless_edges.pop(token)
|
edge = self.wireless_edges.pop(token)
|
||||||
edge.delete()
|
edge.delete()
|
||||||
src.wireless_edges.remove(edge)
|
src.wireless_edges.remove(edge)
|
||||||
|
@ -246,20 +250,15 @@ class CanvasGraph(tk.Canvas):
|
||||||
node_one = canvas_node_one.core_node
|
node_one = canvas_node_one.core_node
|
||||||
canvas_node_two = self.core.canvas_nodes[link.node_two_id]
|
canvas_node_two = self.core.canvas_nodes[link.node_two_id]
|
||||||
node_two = canvas_node_two.core_node
|
node_two = canvas_node_two.core_node
|
||||||
token = EdgeUtils.get_token(canvas_node_one.id, canvas_node_two.id)
|
token = create_edge_token(canvas_node_one.id, canvas_node_two.id)
|
||||||
|
|
||||||
if link.type == core_pb2.LinkType.WIRELESS:
|
if link.type == core_pb2.LinkType.WIRELESS:
|
||||||
self.add_wireless_edge(canvas_node_one, canvas_node_two)
|
self.add_wireless_edge(canvas_node_one, canvas_node_two)
|
||||||
else:
|
else:
|
||||||
if token not in self.edges:
|
if token not in self.edges:
|
||||||
edge = CanvasEdge(
|
src_pos = (node_one.position.x, node_one.position.y)
|
||||||
node_one.position.x,
|
dst_pos = (node_two.position.x, node_two.position.y)
|
||||||
node_one.position.y,
|
edge = CanvasEdge(self, canvas_node_one.id, src_pos, dst_pos)
|
||||||
node_two.position.x,
|
|
||||||
node_two.position.y,
|
|
||||||
canvas_node_one.id,
|
|
||||||
self,
|
|
||||||
)
|
|
||||||
edge.token = token
|
edge.token = token
|
||||||
edge.dst = canvas_node_two.id
|
edge.dst = canvas_node_two.id
|
||||||
edge.set_link(link)
|
edge.set_link(link)
|
||||||
|
@ -391,7 +390,7 @@ class CanvasGraph(tk.Canvas):
|
||||||
return
|
return
|
||||||
|
|
||||||
# ignore repeated edges
|
# ignore repeated edges
|
||||||
token = EdgeUtils.get_token(edge.src, self.selected)
|
token = create_edge_token(edge.src, self.selected)
|
||||||
if token in self.edges:
|
if token in self.edges:
|
||||||
edge.delete()
|
edge.delete()
|
||||||
return
|
return
|
||||||
|
@ -520,11 +519,10 @@ class CanvasGraph(tk.Canvas):
|
||||||
logging.debug("click press offset(%s, %s)", x_check, y_check)
|
logging.debug("click press offset(%s, %s)", x_check, y_check)
|
||||||
is_node = selected in self.nodes
|
is_node = selected in self.nodes
|
||||||
if self.mode == GraphMode.EDGE and is_node:
|
if self.mode == GraphMode.EDGE and is_node:
|
||||||
x, y = self.coords(selected)
|
pos = self.coords(selected)
|
||||||
self.drawing_edge = CanvasEdge(x, y, x, y, selected, self)
|
self.drawing_edge = CanvasEdge(self, selected, pos, pos)
|
||||||
|
|
||||||
if self.mode == GraphMode.ANNOTATION:
|
if self.mode == GraphMode.ANNOTATION:
|
||||||
|
|
||||||
if is_marker(self.annotation_type):
|
if is_marker(self.annotation_type):
|
||||||
r = self.app.toolbar.marker_tool.radius
|
r = self.app.toolbar.marker_tool.radius
|
||||||
self.create_oval(
|
self.create_oval(
|
||||||
|
@ -603,8 +601,7 @@ class CanvasGraph(tk.Canvas):
|
||||||
self.cursor = x, y
|
self.cursor = x, y
|
||||||
|
|
||||||
if self.mode == GraphMode.EDGE and self.drawing_edge is not None:
|
if self.mode == GraphMode.EDGE and self.drawing_edge is not None:
|
||||||
x1, y1, _, _ = self.coords(self.drawing_edge.id)
|
self.drawing_edge.move_dst(x, y)
|
||||||
self.coords(self.drawing_edge.id, x1, y1, x, y)
|
|
||||||
if self.mode == GraphMode.ANNOTATION:
|
if self.mode == GraphMode.ANNOTATION:
|
||||||
if is_draw_shape(self.annotation_type) and self.shape_drawing:
|
if is_draw_shape(self.annotation_type) and self.shape_drawing:
|
||||||
shape = self.shapes[self.selected]
|
shape = self.shapes[self.selected]
|
||||||
|
@ -841,11 +838,10 @@ class CanvasGraph(tk.Canvas):
|
||||||
"""
|
"""
|
||||||
create an edge between source node and destination node
|
create an edge between source node and destination node
|
||||||
"""
|
"""
|
||||||
if (source.id, dest.id) not in self.edges:
|
token = create_edge_token(source.id, dest.id)
|
||||||
pos0 = source.core_node.position
|
if token not in self.edges:
|
||||||
x0 = pos0.x
|
pos = (source.core_node.position.x, source.core_node.position.y)
|
||||||
y0 = pos0.y
|
edge = CanvasEdge(self, source.id, pos, pos)
|
||||||
edge = CanvasEdge(x0, y0, x0, y0, source.id, self)
|
|
||||||
edge.complete(dest.id)
|
edge.complete(dest.id)
|
||||||
self.edges[edge.token] = edge
|
self.edges[edge.token] = edge
|
||||||
self.nodes[source.id].edges.add(edge)
|
self.nodes[source.id].edges.add(edge)
|
||||||
|
@ -905,7 +901,7 @@ class CanvasGraph(tk.Canvas):
|
||||||
dest_node_copy = self.nodes[copy_map[edge.token[1]]]
|
dest_node_copy = self.nodes[copy_map[edge.token[1]]]
|
||||||
self.create_edge(source_node_copy, dest_node_copy)
|
self.create_edge(source_node_copy, dest_node_copy)
|
||||||
copy_edge = self.edges[
|
copy_edge = self.edges[
|
||||||
EdgeUtils.get_token(source_node_copy.id, dest_node_copy.id)
|
create_edge_token(source_node_copy.id, dest_node_copy.id)
|
||||||
]
|
]
|
||||||
copy_link = copy_edge.link
|
copy_link = copy_edge.link
|
||||||
options = edge.link.options
|
options = edge.link.options
|
||||||
|
|
|
@ -148,19 +148,9 @@ class CanvasNode:
|
||||||
|
|
||||||
# move edges
|
# move edges
|
||||||
for edge in self.edges:
|
for edge in self.edges:
|
||||||
x1, y1, x2, y2 = self.canvas.coords(edge.id)
|
edge.move_node(self.id, x, y)
|
||||||
if edge.src == self.id:
|
|
||||||
self.canvas.coords(edge.id, x, y, x2, y2)
|
|
||||||
else:
|
|
||||||
self.canvas.coords(edge.id, x1, y1, x, y)
|
|
||||||
edge.update_labels()
|
|
||||||
|
|
||||||
for edge in self.wireless_edges:
|
for edge in self.wireless_edges:
|
||||||
x1, y1, x2, y2 = self.canvas.coords(edge.id)
|
edge.move_node(self.id, x, y)
|
||||||
if edge.src == self.id:
|
|
||||||
self.canvas.coords(edge.id, x, y, x2, y2)
|
|
||||||
else:
|
|
||||||
self.canvas.coords(edge.id, x1, y1, x, y)
|
|
||||||
|
|
||||||
# set actual coords for node and update core is running
|
# set actual coords for node and update core is running
|
||||||
real_x, real_y = self.canvas.get_actual_coords(x, y)
|
real_x, real_y = self.canvas.get_actual_coords(x, y)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import logging
|
import logging
|
||||||
from typing import TYPE_CHECKING, Dict, List, Optional, Set, Tuple, Union
|
from typing import TYPE_CHECKING, Dict, List, Optional, Set, Union
|
||||||
|
|
||||||
from core.api.grpc.core_pb2 import NodeType
|
from core.api.grpc.core_pb2 import NodeType
|
||||||
from core.gui.images import ImageEnum, Images, TypeToImage
|
from core.gui.images import ImageEnum, Images, TypeToImage
|
||||||
|
@ -172,9 +172,3 @@ class NodeUtils:
|
||||||
cls.NETWORK_NODES.append(node_draw)
|
cls.NETWORK_NODES.append(node_draw)
|
||||||
cls.NODE_ICONS[(node_type, None)] = node_draw.image
|
cls.NODE_ICONS[(node_type, None)] = node_draw.image
|
||||||
cls.ANTENNA_ICON = Images.get(ImageEnum.ANTENNA, ANTENNA_SIZE)
|
cls.ANTENNA_ICON = Images.get(ImageEnum.ANTENNA, ANTENNA_SIZE)
|
||||||
|
|
||||||
|
|
||||||
class EdgeUtils:
|
|
||||||
@classmethod
|
|
||||||
def get_token(cls, src: int, dst: int) -> Tuple[int, ...]:
|
|
||||||
return tuple(sorted([src, dst]))
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue