pygui: initial changes to allow multiple wired links between nodes, updated to commonize logic for creating edges and adjustments in the UI for several edge related cases
This commit is contained in:
parent
96dddb687d
commit
29bd6ef7f8
5 changed files with 119 additions and 114 deletions
|
@ -21,8 +21,10 @@ from core.gui.graph.edges import (
|
|||
EDGE_WIDTH,
|
||||
CanvasEdge,
|
||||
CanvasWirelessEdge,
|
||||
Edge,
|
||||
arc_edges,
|
||||
create_edge_token,
|
||||
create_wireless_token,
|
||||
)
|
||||
from core.gui.graph.enums import GraphMode, ScaleOption
|
||||
from core.gui.graph.node import CanvasNode
|
||||
|
@ -69,9 +71,9 @@ class CanvasGraph(tk.Canvas):
|
|||
self.selected: Optional[int] = None
|
||||
self.node_draw: Optional[NodeDraw] = None
|
||||
self.nodes: Dict[int, CanvasNode] = {}
|
||||
self.edges: Dict[int, CanvasEdge] = {}
|
||||
self.edges: Dict[str, CanvasEdge] = {}
|
||||
self.shapes: Dict[int, Shape] = {}
|
||||
self.wireless_edges: Dict[Tuple[int, ...], CanvasWirelessEdge] = {}
|
||||
self.wireless_edges: Dict[str, CanvasWirelessEdge] = {}
|
||||
|
||||
# map wireless/EMANE node to the set of MDRs connected to that node
|
||||
self.wireless_network: Dict[int, Set[int]] = {}
|
||||
|
@ -206,14 +208,9 @@ class CanvasGraph(tk.Canvas):
|
|||
iface_id = iface_throughput.iface_id
|
||||
throughput = iface_throughput.throughput
|
||||
iface_to_edge_id = (node_id, iface_id)
|
||||
token = self.core.iface_to_edge.get(iface_to_edge_id)
|
||||
if not token:
|
||||
continue
|
||||
edge = self.edges.get(token)
|
||||
edge = self.core.iface_to_edge.get(iface_to_edge_id)
|
||||
if edge:
|
||||
edge.set_throughput(throughput)
|
||||
else:
|
||||
del self.core.iface_to_edge[iface_to_edge_id]
|
||||
|
||||
def draw_grid(self) -> None:
|
||||
"""
|
||||
|
@ -230,7 +227,7 @@ class CanvasGraph(tk.Canvas):
|
|||
self.tag_lower(self.rect)
|
||||
|
||||
def add_wired_edge(self, src: CanvasNode, dst: CanvasNode, link: Link) -> None:
|
||||
token = create_edge_token(src.id, dst.id)
|
||||
token = create_edge_token(src.id, dst.id, link)
|
||||
if token in self.edges and link.options.unidirectional:
|
||||
edge = self.edges[token]
|
||||
edge.asymmetric_link = link
|
||||
|
@ -240,72 +237,50 @@ class CanvasGraph(tk.Canvas):
|
|||
src_pos = (node1.position.x, node1.position.y)
|
||||
dst_pos = (node2.position.x, node2.position.y)
|
||||
edge = CanvasEdge(self, src.id, src_pos, dst_pos)
|
||||
edge.linked_wireless = self.is_linked_wireless(src.id, dst.id)
|
||||
edge.token = token
|
||||
edge.dst = dst.id
|
||||
edge.set_link(link)
|
||||
edge.check_wireless()
|
||||
src.edges.add(edge)
|
||||
dst.edges.add(edge)
|
||||
self.edges[edge.token] = edge
|
||||
self.core.links[edge.token] = edge
|
||||
if link.iface1:
|
||||
iface1 = link.iface1
|
||||
self.core.iface_to_edge[(node1.id, iface1.id)] = token
|
||||
src.ifaces[iface1.id] = iface1
|
||||
edge.src_iface = iface1
|
||||
if link.iface2:
|
||||
iface2 = link.iface2
|
||||
self.core.iface_to_edge[(node2.id, iface2.id)] = edge.token
|
||||
dst.ifaces[iface2.id] = iface2
|
||||
edge.dst_iface = iface2
|
||||
self.complete_edge(src, dst, edge)
|
||||
|
||||
def delete_wired_edge(self, src: CanvasNode, dst: CanvasNode) -> None:
|
||||
token = create_edge_token(src.id, dst.id)
|
||||
def delete_wired_edge(self, src: CanvasNode, dst: CanvasNode, link: Link) -> None:
|
||||
token = create_edge_token(src.id, dst.id, link)
|
||||
edge = self.edges.get(token)
|
||||
if not edge:
|
||||
return
|
||||
self.delete_edge(edge)
|
||||
if edge:
|
||||
self.delete_edge(edge)
|
||||
|
||||
def update_wired_edge(self, src: CanvasNode, dst: CanvasNode, link: Link) -> None:
|
||||
token = create_edge_token(src.id, dst.id)
|
||||
token = create_edge_token(src.id, dst.id, link)
|
||||
edge = self.edges.get(token)
|
||||
if not edge:
|
||||
return
|
||||
edge.link.options = deepcopy(link.options)
|
||||
if edge:
|
||||
edge.link.options = deepcopy(link.options)
|
||||
|
||||
def add_wireless_edge(self, src: CanvasNode, dst: CanvasNode, link: Link) -> None:
|
||||
network_id = link.network_id if link.network_id else None
|
||||
token = create_edge_token(src.id, dst.id, network_id)
|
||||
token = create_wireless_token(src.id, dst.id, network_id)
|
||||
if token in self.wireless_edges:
|
||||
logging.warning("ignoring link that already exists: %s", link)
|
||||
return
|
||||
src_pos = self.coords(src.id)
|
||||
dst_pos = self.coords(dst.id)
|
||||
edge = CanvasWirelessEdge(self, src.id, dst.id, src_pos, dst_pos, token, link)
|
||||
edge = CanvasWirelessEdge(
|
||||
self, src.id, dst.id, network_id, token, src_pos, dst_pos, link
|
||||
)
|
||||
self.wireless_edges[token] = edge
|
||||
src.wireless_edges.add(edge)
|
||||
dst.wireless_edges.add(edge)
|
||||
self.tag_raise(src.id)
|
||||
self.tag_raise(dst.id)
|
||||
# update arcs when there are multiple links
|
||||
common_edges = list(src.wireless_edges & dst.wireless_edges)
|
||||
arc_edges(common_edges)
|
||||
self.arc_common_edges(edge)
|
||||
|
||||
def delete_wireless_edge(
|
||||
self, src: CanvasNode, dst: CanvasNode, link: Link
|
||||
) -> None:
|
||||
network_id = link.network_id if link.network_id else None
|
||||
token = create_edge_token(src.id, dst.id, network_id)
|
||||
token = create_wireless_token(src.id, dst.id, network_id)
|
||||
if token not in self.wireless_edges:
|
||||
return
|
||||
edge = self.wireless_edges.pop(token)
|
||||
edge.delete()
|
||||
src.wireless_edges.remove(edge)
|
||||
dst.wireless_edges.remove(edge)
|
||||
# update arcs when there are multiple links
|
||||
common_edges = list(src.wireless_edges & dst.wireless_edges)
|
||||
arc_edges(common_edges)
|
||||
self.arc_common_edges(edge)
|
||||
|
||||
def update_wireless_edge(
|
||||
self, src: CanvasNode, dst: CanvasNode, link: Link
|
||||
|
@ -313,7 +288,7 @@ class CanvasGraph(tk.Canvas):
|
|||
if not link.label:
|
||||
return
|
||||
network_id = link.network_id if link.network_id else None
|
||||
token = create_edge_token(src.id, dst.id, network_id)
|
||||
token = create_wireless_token(src.id, dst.id, network_id)
|
||||
if token not in self.wireless_edges:
|
||||
self.add_wireless_edge(src, dst, link)
|
||||
else:
|
||||
|
@ -454,12 +429,6 @@ class CanvasGraph(tk.Canvas):
|
|||
edge.delete()
|
||||
return
|
||||
|
||||
# ignore repeated edges
|
||||
token = create_edge_token(edge.src, self.selected)
|
||||
if token in self.edges:
|
||||
edge.delete()
|
||||
return
|
||||
|
||||
# rj45 nodes can only support one link
|
||||
if NodeUtils.is_rj45_node(src_node.core_node.type) and src_node.edges:
|
||||
edge.delete()
|
||||
|
@ -468,14 +437,15 @@ class CanvasGraph(tk.Canvas):
|
|||
edge.delete()
|
||||
return
|
||||
|
||||
# set dst node and snap edge to center
|
||||
linked_wireless = self.is_linked_wireless(src_node.id, self.selected)
|
||||
edge.complete(self.selected, linked_wireless)
|
||||
# finalize edge creation
|
||||
self.complete_edge(src_node, dst_node, edge)
|
||||
|
||||
self.edges[edge.token] = edge
|
||||
src_node.edges.add(edge)
|
||||
dst_node.edges.add(edge)
|
||||
self.core.create_link(edge, src_node, dst_node)
|
||||
def arc_common_edges(self, edge: Edge) -> None:
|
||||
src_node = self.nodes[edge.src]
|
||||
dst_node = self.nodes[edge.dst]
|
||||
common_edges = list(src_node.edges & dst_node.edges)
|
||||
common_edges += list(src_node.wireless_edges & dst_node.wireless_edges)
|
||||
arc_edges(common_edges)
|
||||
|
||||
def select_object(self, object_id: int, choose_multiple: bool = False) -> None:
|
||||
"""
|
||||
|
@ -572,6 +542,7 @@ class CanvasGraph(tk.Canvas):
|
|||
if dst_wireless:
|
||||
src_node.delete_antenna()
|
||||
self.core.deleted_canvas_edges([edge])
|
||||
self.arc_common_edges(edge)
|
||||
|
||||
def zoom(self, event: tk.Event, factor: float = None) -> None:
|
||||
if not factor:
|
||||
|
@ -903,20 +874,41 @@ class CanvasGraph(tk.Canvas):
|
|||
def is_selection_mode(self) -> bool:
|
||||
return self.mode == GraphMode.SELECT
|
||||
|
||||
def create_edge(self, source: CanvasNode, dest: CanvasNode) -> None:
|
||||
def create_edge(self, src: CanvasNode, dst: CanvasNode) -> CanvasEdge:
|
||||
"""
|
||||
create an edge between source node and destination node
|
||||
"""
|
||||
token = create_edge_token(source.id, dest.id)
|
||||
if token not in self.edges:
|
||||
pos = (source.core_node.position.x, source.core_node.position.y)
|
||||
edge = CanvasEdge(self, source.id, pos, pos)
|
||||
linked_wireless = self.is_linked_wireless(source.id, dest.id)
|
||||
edge.complete(dest.id, linked_wireless)
|
||||
self.edges[edge.token] = edge
|
||||
self.nodes[source.id].edges.add(edge)
|
||||
self.nodes[dest.id].edges.add(edge)
|
||||
self.core.create_link(edge, source, dest)
|
||||
pos = (src.core_node.position.x, src.core_node.position.y)
|
||||
edge = CanvasEdge(self, src.id, pos, pos)
|
||||
self.complete_edge(src, dst, edge)
|
||||
return edge
|
||||
|
||||
def complete_edge(
|
||||
self,
|
||||
src: CanvasNode,
|
||||
dst: CanvasNode,
|
||||
edge: CanvasEdge,
|
||||
link: Optional[Link] = None,
|
||||
) -> None:
|
||||
linked_wireless = self.is_linked_wireless(src.id, dst.id)
|
||||
edge.complete(dst.id, linked_wireless)
|
||||
src.edges.add(edge)
|
||||
dst.edges.add(edge)
|
||||
if link is None:
|
||||
link = self.core.create_link(edge, src, dst)
|
||||
if link.iface1:
|
||||
iface1 = link.iface1
|
||||
src.ifaces[iface1.id] = iface1
|
||||
edge.src_iface = iface1
|
||||
if link.iface2:
|
||||
iface2 = link.iface2
|
||||
dst.ifaces[iface2.id] = iface2
|
||||
edge.dst_iface = iface2
|
||||
edge.set_link(link)
|
||||
edge.token = create_edge_token(src.id, dst.id, edge.link)
|
||||
self.arc_common_edges(edge)
|
||||
self.edges[edge.token] = edge
|
||||
self.core.save_edge(edge, src, dst)
|
||||
|
||||
def copy(self) -> None:
|
||||
if self.core.is_runtime():
|
||||
|
@ -970,13 +962,12 @@ class CanvasGraph(tk.Canvas):
|
|||
if edge.src not in to_copy_ids or edge.dst not in to_copy_ids:
|
||||
if canvas_node.id == edge.src:
|
||||
dst_node = self.nodes[edge.dst]
|
||||
self.create_edge(node, dst_node)
|
||||
token = create_edge_token(node.id, dst_node.id)
|
||||
copy_edge = self.create_edge(node, dst_node)
|
||||
elif canvas_node.id == edge.dst:
|
||||
src_node = self.nodes[edge.src]
|
||||
self.create_edge(src_node, node)
|
||||
token = create_edge_token(src_node.id, node.id)
|
||||
copy_edge = self.edges[token]
|
||||
copy_edge = self.create_edge(src_node, node)
|
||||
else:
|
||||
continue
|
||||
copy_link = copy_edge.link
|
||||
iface1_id = copy_link.iface1.id if copy_link.iface1 else None
|
||||
iface2_id = copy_link.iface2.id if copy_link.iface2 else None
|
||||
|
@ -1003,13 +994,11 @@ class CanvasGraph(tk.Canvas):
|
|||
|
||||
# copy link and link config
|
||||
for edge in to_copy_edges:
|
||||
src_node_id = copy_map[edge.token[0]]
|
||||
dst_node_id = copy_map[edge.token[1]]
|
||||
src_node_id = copy_map[edge.src]
|
||||
dst_node_id = copy_map[edge.dst]
|
||||
src_node_copy = self.nodes[src_node_id]
|
||||
dst_node_copy = self.nodes[dst_node_id]
|
||||
self.create_edge(src_node_copy, dst_node_copy)
|
||||
token = create_edge_token(src_node_copy.id, dst_node_copy.id)
|
||||
copy_edge = self.edges[token]
|
||||
copy_edge = self.create_edge(src_node_copy, dst_node_copy)
|
||||
copy_link = copy_edge.link
|
||||
iface1_id = copy_link.iface1.id if copy_link.iface1 else None
|
||||
iface2_id = copy_link.iface2.id if copy_link.iface2 else None
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue