merged drawing antenna code to graph node class
This commit is contained in:
parent
7e2ebb4a2c
commit
81eeac9ec6
5 changed files with 120 additions and 194 deletions
|
@ -1,5 +1,7 @@
|
|||
import tkinter as tk
|
||||
|
||||
from coretk.nodeutils import NodeUtils
|
||||
|
||||
|
||||
class CanvasWirelessEdge:
|
||||
def __init__(self, token, position, src, dst, canvas):
|
||||
|
@ -22,7 +24,7 @@ class CanvasEdge:
|
|||
|
||||
width = 1.4
|
||||
|
||||
def __init__(self, x1, y1, x2, y2, src, canvas, is_wired=None):
|
||||
def __init__(self, x1, y1, x2, y2, src, canvas):
|
||||
"""
|
||||
Create an instance of canvas edge object
|
||||
:param int x1: source x-coord
|
||||
|
@ -30,41 +32,56 @@ class CanvasEdge:
|
|||
:param int x2: destination x-coord
|
||||
:param int y2: destination y-coord
|
||||
:param int src: source id
|
||||
:param tkinter.Canvas canvas: canvas object
|
||||
:param coretk.graph.graph.GraphCanvas canvas: canvas object
|
||||
"""
|
||||
self.src = src
|
||||
self.dst = None
|
||||
self.src_interface = None
|
||||
self.dst_interface = None
|
||||
self.canvas = canvas
|
||||
if is_wired is None or is_wired is True:
|
||||
self.id = self.canvas.create_line(
|
||||
x1, y1, x2, y2, tags="edge", width=self.width, fill="#ff0000"
|
||||
)
|
||||
else:
|
||||
self.id = self.canvas.create_line(
|
||||
x1,
|
||||
y1,
|
||||
x2,
|
||||
y2,
|
||||
tags="edge",
|
||||
width=self.width,
|
||||
fill="#ff0000",
|
||||
state=tk.HIDDEN,
|
||||
)
|
||||
self.id = self.canvas.create_line(
|
||||
x1, y1, x2, y2, tags="edge", width=self.width, fill="#ff0000"
|
||||
)
|
||||
self.token = None
|
||||
self.link_info = None
|
||||
self.throughput = None
|
||||
self.wired = is_wired
|
||||
|
||||
def complete(self, dst, x, y):
|
||||
def complete(self, dst):
|
||||
self.dst = dst
|
||||
self.token = tuple(sorted((self.src, self.dst)))
|
||||
x, y = self.canvas.coords(self.dst)
|
||||
x1, y1, _, _ = self.canvas.coords(self.id)
|
||||
self.canvas.coords(self.id, x1, y1, x, y)
|
||||
self.canvas.helper.draw_wireless_case(self.src, self.dst, self)
|
||||
self.check_wireless()
|
||||
self.canvas.tag_raise(self.src)
|
||||
self.canvas.tag_raise(self.dst)
|
||||
|
||||
def check_wireless(self):
|
||||
src_node = self.canvas.nodes[self.src]
|
||||
dst_node = self.canvas.nodes[self.dst]
|
||||
src_node_type = src_node.core_node.type
|
||||
dst_node_type = dst_node.core_node.type
|
||||
is_src_wireless = NodeUtils.is_wireless_node(src_node_type)
|
||||
is_dst_wireless = NodeUtils.is_wireless_node(dst_node_type)
|
||||
if is_src_wireless or is_dst_wireless:
|
||||
self.canvas.itemconfig(self.id, state=tk.HIDDEN)
|
||||
self._check_antenna()
|
||||
|
||||
def _check_antenna(self):
|
||||
src_node = self.canvas.nodes[self.src]
|
||||
dst_node = self.canvas.nodes[self.dst]
|
||||
src_node_type = src_node.core_node.type
|
||||
dst_node_type = dst_node.core_node.type
|
||||
is_src_wireless = NodeUtils.is_wireless_node(src_node_type)
|
||||
is_dst_wireless = NodeUtils.is_wireless_node(dst_node_type)
|
||||
if is_src_wireless or is_dst_wireless:
|
||||
if is_src_wireless and not is_dst_wireless:
|
||||
dst_node.add_antenna()
|
||||
elif not is_src_wireless and is_dst_wireless:
|
||||
src_node.add_antenna()
|
||||
# TODO: remove this? dont allow linking wireless nodes?
|
||||
else:
|
||||
src_node.add_antenna()
|
||||
|
||||
def delete(self):
|
||||
self.canvas.delete(self.id)
|
||||
|
|
|
@ -8,7 +8,6 @@ from core.api.grpc.core_pb2 import NodeType
|
|||
from coretk.dialogs.shapemod import ShapeDialog
|
||||
from coretk.graph.edges import CanvasEdge, CanvasWirelessEdge
|
||||
from coretk.graph.enums import GraphMode, ScaleOption
|
||||
from coretk.graph.graph_helper import GraphHelper
|
||||
from coretk.graph.linkinfo import LinkInfo, Throughput
|
||||
from coretk.graph.node import CanvasNode
|
||||
from coretk.graph.shape import Shape
|
||||
|
@ -16,6 +15,18 @@ from coretk.images import ImageEnum, Images
|
|||
from coretk.nodeutils import NodeUtils
|
||||
|
||||
ABOVE_WALLPAPER = ["edge", "linkinfo", "wireless", "antenna", "nodename", "node"]
|
||||
CANVAS_COMPONENT_TAGS = [
|
||||
"edge",
|
||||
"node",
|
||||
"nodename",
|
||||
"wallpaper",
|
||||
"linkinfo",
|
||||
"antenna",
|
||||
"wireless",
|
||||
"selectednodes",
|
||||
"shape",
|
||||
"shapetext",
|
||||
]
|
||||
|
||||
|
||||
class CanvasGraph(tk.Canvas):
|
||||
|
@ -40,7 +51,6 @@ class CanvasGraph(tk.Canvas):
|
|||
self.setup_bindings()
|
||||
self.draw_grid(width, height)
|
||||
self.core = core
|
||||
self.helper = GraphHelper(self, core)
|
||||
self.throughput_draw = Throughput(self, core)
|
||||
self.shape_drawing = False
|
||||
|
||||
|
@ -96,7 +106,8 @@ class CanvasGraph(tk.Canvas):
|
|||
:return: nothing
|
||||
"""
|
||||
# delete any existing drawn items
|
||||
self.helper.delete_canvas_components()
|
||||
for tag in CANVAS_COMPONENT_TAGS:
|
||||
self.delete(tag)
|
||||
|
||||
# set the private variables to default value
|
||||
self.mode = GraphMode.SELECT
|
||||
|
@ -195,9 +206,6 @@ class CanvasGraph(tk.Canvas):
|
|||
if link.type == core_pb2.LinkType.WIRELESS:
|
||||
self.add_wireless_edge(canvas_node_one, canvas_node_two)
|
||||
else:
|
||||
is_node_one_wireless = NodeUtils.is_wireless_node(node_one.type)
|
||||
is_node_two_wireless = NodeUtils.is_wireless_node(node_two.type)
|
||||
has_no_wireless = not (is_node_one_wireless or is_node_two_wireless)
|
||||
edge = CanvasEdge(
|
||||
node_one.position.x,
|
||||
node_one.position.y,
|
||||
|
@ -205,15 +213,14 @@ class CanvasGraph(tk.Canvas):
|
|||
node_two.position.y,
|
||||
canvas_node_one.id,
|
||||
self,
|
||||
is_wired=has_no_wireless,
|
||||
)
|
||||
edge.token = tuple(sorted((canvas_node_one.id, canvas_node_two.id)))
|
||||
edge.dst = canvas_node_two.id
|
||||
edge.check_wireless()
|
||||
canvas_node_one.edges.add(edge)
|
||||
canvas_node_two.edges.add(edge)
|
||||
self.edges[edge.token] = edge
|
||||
self.core.links[edge.token] = link
|
||||
self.helper.redraw_antenna(canvas_node_one, canvas_node_two)
|
||||
edge.link_info = LinkInfo(self, edge, link)
|
||||
if link.HasField("interface_one"):
|
||||
canvas_node_one.interfaces.append(link.interface_one)
|
||||
|
@ -311,21 +318,23 @@ class CanvasGraph(tk.Canvas):
|
|||
edge.delete()
|
||||
return
|
||||
|
||||
# set dst node and snap edge to center
|
||||
x, y = self.coords(self.selected)
|
||||
edge.complete(self.selected, x, y)
|
||||
logging.debug(f"drawing edge token: {edge.token}")
|
||||
if edge.token in self.edges:
|
||||
# ignore repeated edges
|
||||
token = tuple(sorted((edge.src, self.selected)))
|
||||
if token in self.edges:
|
||||
edge.delete()
|
||||
else:
|
||||
self.edges[edge.token] = edge
|
||||
node_src = self.nodes[edge.src]
|
||||
node_src.edges.add(edge)
|
||||
node_dst = self.nodes[edge.dst]
|
||||
node_dst.edges.add(edge)
|
||||
link = self.core.create_link(edge, node_src, node_dst)
|
||||
edge.link_info = LinkInfo(self, edge, link)
|
||||
logging.debug(f"edges: {self.find_withtag('edge')}")
|
||||
return
|
||||
|
||||
# set dst node and snap edge to center
|
||||
edge.complete(self.selected)
|
||||
logging.debug("drawing edge token: %s", edge.token)
|
||||
|
||||
self.edges[edge.token] = edge
|
||||
node_src = self.nodes[edge.src]
|
||||
node_src.edges.add(edge)
|
||||
node_dst = self.nodes[edge.dst]
|
||||
node_dst.edges.add(edge)
|
||||
link = self.core.create_link(edge, node_src, node_dst)
|
||||
edge.link_info = LinkInfo(self, edge, link)
|
||||
|
||||
def select_object(self, object_id, choose_multiple=False):
|
||||
"""
|
||||
|
@ -374,11 +383,8 @@ class CanvasGraph(tk.Canvas):
|
|||
self.delete(object_id)
|
||||
self.delete(selection_id)
|
||||
self.delete(canvas_node.text_id)
|
||||
|
||||
# delete antennas
|
||||
canvas_node.delete_antennae()
|
||||
is_wireless = NodeUtils.is_wireless_node(canvas_node.core_node.type)
|
||||
if is_wireless:
|
||||
canvas_node.antenna_draw.delete_antennas()
|
||||
|
||||
# delete related edges
|
||||
for edge in canvas_node.edges:
|
||||
|
@ -401,7 +407,7 @@ class CanvasGraph(tk.Canvas):
|
|||
except ValueError:
|
||||
pass
|
||||
if is_wireless:
|
||||
other_node.antenna_draw.delete_antenna()
|
||||
other_node.delete_antenna()
|
||||
if object_id in self.shapes:
|
||||
selection_id = self.selection[object_id]
|
||||
self.shapes[object_id].delete()
|
||||
|
@ -424,6 +430,7 @@ class CanvasGraph(tk.Canvas):
|
|||
if self.mode == GraphMode.EDGE and is_node:
|
||||
x, y = self.coords(selected)
|
||||
self.drawing_edge = CanvasEdge(x, y, x, y, selected, self)
|
||||
self.tag_raise(selected)
|
||||
if (
|
||||
self.mode == GraphMode.ANNOTATION
|
||||
and self.annotation_type in [ImageEnum.OVAL, ImageEnum.RECTANGLE]
|
||||
|
|
|
@ -1,144 +0,0 @@
|
|||
"""
|
||||
Some graph helper functions
|
||||
"""
|
||||
import logging
|
||||
import tkinter as tk
|
||||
|
||||
from coretk.images import ImageEnum, Images
|
||||
from coretk.nodeutils import NodeUtils
|
||||
|
||||
CANVAS_COMPONENT_TAGS = [
|
||||
"edge",
|
||||
"node",
|
||||
"nodename",
|
||||
"wallpaper",
|
||||
"linkinfo",
|
||||
"antenna",
|
||||
"wireless",
|
||||
"selectednodes",
|
||||
"shape",
|
||||
"shapetext",
|
||||
]
|
||||
|
||||
|
||||
class GraphHelper:
|
||||
def __init__(self, canvas, core):
|
||||
"""
|
||||
create an instance of GraphHelper object
|
||||
"""
|
||||
self.canvas = canvas
|
||||
self.core = core
|
||||
|
||||
def delete_canvas_components(self):
|
||||
"""
|
||||
delete the components of the graph leaving only the blank canvas
|
||||
|
||||
:return: nothing
|
||||
"""
|
||||
for tag in CANVAS_COMPONENT_TAGS:
|
||||
for i in self.canvas.find_withtag(tag):
|
||||
self.canvas.delete(i)
|
||||
|
||||
def draw_wireless_case(self, src_id, dst_id, edge):
|
||||
src_node_type = self.canvas.nodes[src_id].core_node.type
|
||||
dst_node_type = self.canvas.nodes[dst_id].core_node.type
|
||||
is_src_wireless = NodeUtils.is_wireless_node(src_node_type)
|
||||
is_dst_wireless = NodeUtils.is_wireless_node(dst_node_type)
|
||||
if is_src_wireless or is_dst_wireless:
|
||||
self.canvas.itemconfig(edge.id, state=tk.HIDDEN)
|
||||
edge.wired = False
|
||||
if edge.token not in self.canvas.edges:
|
||||
if is_src_wireless and is_dst_wireless:
|
||||
self.canvas.nodes[src_id].antenna_draw.add_antenna()
|
||||
elif is_src_wireless:
|
||||
self.canvas.nodes[dst_id].antenna_draw.add_antenna()
|
||||
else:
|
||||
self.canvas.nodes[src_id].antenna_draw.add_antenna()
|
||||
edge.wired = True
|
||||
|
||||
def redraw_antenna(self, node_one, node_two):
|
||||
is_node_one_wireless = NodeUtils.is_wireless_node(node_one.core_node.type)
|
||||
is_node_two_wireless = NodeUtils.is_wireless_node(node_two.core_node.type)
|
||||
if is_node_one_wireless or is_node_two_wireless:
|
||||
if is_node_one_wireless and not is_node_two_wireless:
|
||||
node_two.antenna_draw.add_antenna()
|
||||
elif not is_node_one_wireless and is_node_two_wireless:
|
||||
node_one.antenna_draw.add_antenna()
|
||||
else:
|
||||
logging.error("bad link between two wireless nodes")
|
||||
|
||||
def update_wlan_connection(self, old_x, old_y, new_x, new_y, edge_ids):
|
||||
for eid in edge_ids:
|
||||
x1, y1, x2, y2 = self.canvas.coords(eid)
|
||||
if x1 == old_x and y1 == old_y:
|
||||
self.canvas.coords(eid, new_x, new_y, x2, y2)
|
||||
else:
|
||||
self.canvas.coords(eid, x1, y1, new_x, new_y)
|
||||
|
||||
|
||||
class WlanAntennaManager:
|
||||
def __init__(self, canvas, node_id):
|
||||
"""
|
||||
crate an instance for AntennaManager
|
||||
"""
|
||||
self.canvas = canvas
|
||||
self.node_id = node_id
|
||||
self.quantity = 0
|
||||
self._max = 5
|
||||
self.antennas = []
|
||||
self.image = Images.get(ImageEnum.ANTENNA, 32)
|
||||
|
||||
# distance between each antenna
|
||||
self.offset = 0
|
||||
|
||||
def add_antenna(self):
|
||||
"""
|
||||
add an antenna to a node
|
||||
|
||||
:return: nothing
|
||||
"""
|
||||
if self.quantity < 5:
|
||||
x, y = self.canvas.coords(self.node_id)
|
||||
aid = self.canvas.create_image(
|
||||
x - 16 + self.offset,
|
||||
y - 23,
|
||||
anchor=tk.CENTER,
|
||||
image=self.image,
|
||||
tags="antenna",
|
||||
)
|
||||
# self.canvas.tag_raise("antenna")
|
||||
self.antennas.append(aid)
|
||||
self.quantity = self.quantity + 1
|
||||
self.offset = self.offset + 8
|
||||
|
||||
def delete_antenna(self):
|
||||
"""
|
||||
delete one antenna
|
||||
|
||||
:return: nothing
|
||||
"""
|
||||
if len(self.antennas) > 0:
|
||||
self.canvas.delete(self.antennas.pop())
|
||||
self.quantity -= 1
|
||||
self.offset -= 8
|
||||
|
||||
def delete_antennas(self):
|
||||
"""
|
||||
delete all antennas
|
||||
|
||||
:return: nothing
|
||||
"""
|
||||
for aid in self.antennas:
|
||||
self.canvas.delete(aid)
|
||||
self.antennas.clear()
|
||||
self.quantity = 0
|
||||
self.offset = 0
|
||||
|
||||
def update_antennas_position(self, offset_x, offset_y):
|
||||
"""
|
||||
redraw antennas of a node according to the new node position
|
||||
|
||||
:return: nothing
|
||||
"""
|
||||
for i in self.antennas:
|
||||
self.canvas.move(i, offset_x, offset_y)
|
|
@ -7,8 +7,8 @@ from coretk.dialogs.mobilityconfig import MobilityConfigDialog
|
|||
from coretk.dialogs.nodeconfig import NodeConfigDialog
|
||||
from coretk.dialogs.wlanconfig import WlanConfigDialog
|
||||
from coretk.graph.enums import GraphMode
|
||||
from coretk.graph.graph_helper import WlanAntennaManager
|
||||
from coretk.graph.tooltip import CanvasTooltip
|
||||
from coretk.nodeutils import NodeUtils
|
||||
|
||||
NODE_TEXT_OFFSET = 5
|
||||
|
||||
|
@ -35,7 +35,6 @@ class CanvasNode:
|
|||
font=text_font,
|
||||
fill="#0000CD",
|
||||
)
|
||||
self.antenna_draw = WlanAntennaManager(self.canvas, self.id)
|
||||
self.tooltip = CanvasTooltip(self.canvas)
|
||||
self.canvas.tag_bind(self.id, "<ButtonPress-1>", self.click_press)
|
||||
self.canvas.tag_bind(self.id, "<ButtonRelease-1>", self.click_release)
|
||||
|
@ -48,6 +47,50 @@ class CanvasNode:
|
|||
self.interfaces = []
|
||||
self.wireless_edges = set()
|
||||
self.moving = None
|
||||
self.antennae = []
|
||||
|
||||
def add_antenna(self):
|
||||
x, y = self.canvas.coords(self.id)
|
||||
offset = len(self.antennae) * 8
|
||||
|
||||
antenna_id = self.canvas.create_image(
|
||||
x - 16 + offset,
|
||||
y - 23,
|
||||
anchor=tk.CENTER,
|
||||
image=NodeUtils.ANTENNA_ICON,
|
||||
tags="antenna",
|
||||
)
|
||||
self.antennae.append(antenna_id)
|
||||
|
||||
def delete_antenna(self):
|
||||
"""
|
||||
delete one antenna
|
||||
|
||||
:return: nothing
|
||||
"""
|
||||
if self.antennae:
|
||||
antenna_id = self.antennae.pop()
|
||||
self.canvas.delete(antenna_id)
|
||||
|
||||
def delete_antennae(self):
|
||||
"""
|
||||
delete all antennas
|
||||
|
||||
:return: nothing
|
||||
"""
|
||||
logging.info("deleting antennae: %s", self.antennae)
|
||||
for antenna_id in self.antennae:
|
||||
self.canvas.delete(antenna_id)
|
||||
self.antennae.clear()
|
||||
|
||||
def move_antennae(self, x_offset, y_offset):
|
||||
"""
|
||||
redraw antennas of a node according to the new node position
|
||||
|
||||
:return: nothing
|
||||
"""
|
||||
for antenna_id in self.antennae:
|
||||
self.canvas.move(antenna_id, x_offset, y_offset)
|
||||
|
||||
def redraw(self):
|
||||
self.canvas.itemconfig(self.id, image=self.image)
|
||||
|
@ -62,7 +105,7 @@ class CanvasNode:
|
|||
self.core_node.position.y = int(y)
|
||||
self.canvas.move(self.id, x_offset, y_offset)
|
||||
self.canvas.move(self.text_id, x_offset, y_offset)
|
||||
self.antenna_draw.update_antennas_position(x_offset, y_offset)
|
||||
self.move_antennae(x_offset, y_offset)
|
||||
self.canvas.object_drag(self.id, x_offset, y_offset)
|
||||
for edge in self.edges:
|
||||
x1, y1, x2, y2 = self.canvas.coords(edge.id)
|
||||
|
|
|
@ -2,6 +2,7 @@ from core.api.grpc.core_pb2 import NodeType
|
|||
from coretk.images import ImageEnum, Images
|
||||
|
||||
ICON_SIZE = 48
|
||||
ANTENNA_SIZE = 32
|
||||
|
||||
|
||||
class NodeDraw:
|
||||
|
@ -49,6 +50,7 @@ class NodeUtils:
|
|||
WIRELESS_NODES = {NodeType.WIRELESS_LAN, NodeType.EMANE}
|
||||
IGNORE_NODES = {NodeType.CONTROL_NET, NodeType.PEER_TO_PEER}
|
||||
NODE_MODELS = {"router", "host", "PC", "mdr", "prouter"}
|
||||
ANTENNA_ICON = None
|
||||
|
||||
@classmethod
|
||||
def is_ignore_node(cls, node_type):
|
||||
|
@ -104,3 +106,4 @@ class NodeUtils:
|
|||
node_draw = NodeDraw.from_setup(image_enum, node_type, tooltip=tooltip)
|
||||
cls.NETWORK_NODES.append(node_draw)
|
||||
cls.NODE_ICONS[(node_type, None)] = node_draw.image
|
||||
cls.ANTENNA_ICON = Images.get(ImageEnum.ANTENNA, ANTENNA_SIZE)
|
||||
|
|
Loading…
Add table
Reference in a new issue