updates for working label drawing on wireless links in pygui, will display sinr values on emane links
This commit is contained in:
parent
86b0c07764
commit
23562cd294
6 changed files with 64 additions and 42 deletions
|
@ -85,6 +85,7 @@ def handle_link_event(event: LinkData) -> core_pb2.LinkEvent:
|
||||||
interface_two=interface_two,
|
interface_two=interface_two,
|
||||||
options=options,
|
options=options,
|
||||||
network_id=event.network_id,
|
network_id=event.network_id,
|
||||||
|
label=event.label,
|
||||||
)
|
)
|
||||||
return core_pb2.LinkEvent(message_type=event.message_type.value, link=link)
|
return core_pb2.LinkEvent(message_type=event.message_type.value, link=link)
|
||||||
|
|
||||||
|
|
|
@ -371,6 +371,7 @@ def convert_link(session: Session, link_data: LinkData) -> core_pb2.Link:
|
||||||
interface_two=interface_two,
|
interface_two=interface_two,
|
||||||
options=options,
|
options=options,
|
||||||
network_id=link_data.network_id,
|
network_id=link_data.network_id,
|
||||||
|
label=link_data.label,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -207,22 +207,25 @@ class CoreClient:
|
||||||
logging.debug("Link event: %s", event)
|
logging.debug("Link event: %s", event)
|
||||||
node_one_id = event.link.node_one_id
|
node_one_id = event.link.node_one_id
|
||||||
node_two_id = event.link.node_two_id
|
node_two_id = event.link.node_two_id
|
||||||
network_id = event.link.network_id
|
|
||||||
if node_one_id == node_two_id:
|
if node_one_id == node_two_id:
|
||||||
logging.warning("ignoring invalid link: %s", event)
|
logging.warning("ignoring links with loops: %s", event)
|
||||||
return
|
return
|
||||||
canvas_node_one = self.canvas_nodes[node_one_id]
|
canvas_node_one = self.canvas_nodes[node_one_id]
|
||||||
canvas_node_two = self.canvas_nodes[node_two_id]
|
canvas_node_two = self.canvas_nodes[node_two_id]
|
||||||
if event.message_type == core_pb2.MessageType.ADD:
|
if event.message_type == core_pb2.MessageType.ADD:
|
||||||
self.app.canvas.add_wireless_edge(
|
self.app.canvas.add_wireless_edge(
|
||||||
canvas_node_one, canvas_node_two, network_id
|
canvas_node_one, canvas_node_two, event.link
|
||||||
)
|
)
|
||||||
elif event.message_type == core_pb2.MessageType.DELETE:
|
elif event.message_type == core_pb2.MessageType.DELETE:
|
||||||
self.app.canvas.delete_wireless_edge(
|
self.app.canvas.delete_wireless_edge(
|
||||||
canvas_node_one, canvas_node_two, network_id
|
canvas_node_one, canvas_node_two, event.link
|
||||||
|
)
|
||||||
|
elif event.message_type == core_pb2.MessageType.NONE:
|
||||||
|
self.app.canvas.update_wireless_edge(
|
||||||
|
canvas_node_one, canvas_node_two, event.link
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
logging.warning("unknown link event: %s", event.message_type)
|
logging.warning("unknown link event: %s", event)
|
||||||
|
|
||||||
def handle_node_event(self, event: core_pb2.NodeEvent):
|
def handle_node_event(self, event: core_pb2.NodeEvent):
|
||||||
logging.debug("node event: %s", event)
|
logging.debug("node event: %s", event)
|
||||||
|
|
|
@ -75,6 +75,7 @@ class Edge:
|
||||||
self.dst = dst
|
self.dst = dst
|
||||||
self.arc = 0
|
self.arc = 0
|
||||||
self.token = None
|
self.token = None
|
||||||
|
self.middle_label = None
|
||||||
self.color = EDGE_COLOR
|
self.color = EDGE_COLOR
|
||||||
self.width = EDGE_WIDTH
|
self.width = EDGE_WIDTH
|
||||||
|
|
||||||
|
@ -82,6 +83,9 @@ class Edge:
|
||||||
def create_token(cls, src: int, dst: int) -> Tuple[int, ...]:
|
def create_token(cls, src: int, dst: int) -> Tuple[int, ...]:
|
||||||
return tuple(sorted([src, dst]))
|
return tuple(sorted([src, dst]))
|
||||||
|
|
||||||
|
def scaled_width(self) -> float:
|
||||||
|
return self.width * self.canvas.app.app_scale
|
||||||
|
|
||||||
def _get_arcpoint(
|
def _get_arcpoint(
|
||||||
self, src_pos: Tuple[float, float], dst_pos: Tuple[float, float]
|
self, src_pos: Tuple[float, float], dst_pos: Tuple[float, float]
|
||||||
) -> Tuple[float, float]:
|
) -> Tuple[float, float]:
|
||||||
|
@ -119,16 +123,28 @@ class Edge:
|
||||||
*dst_pos,
|
*dst_pos,
|
||||||
smooth=True,
|
smooth=True,
|
||||||
tags=self.tag,
|
tags=self.tag,
|
||||||
width=self.width * self.canvas.app.app_scale,
|
width=self.scaled_width(),
|
||||||
fill=self.color,
|
fill=self.color,
|
||||||
)
|
)
|
||||||
|
|
||||||
def redraw(self):
|
def redraw(self):
|
||||||
width = self.width * self.canvas.app.app_scale
|
self.canvas.itemconfig(self.id, width=self.scaled_width(), fill=self.color)
|
||||||
self.canvas.itemconfig(self.id, width=width, fill=self.color)
|
|
||||||
src_x, src_y, _, _, _, _ = self.canvas.coords(self.id)
|
src_x, src_y, _, _, _, _ = self.canvas.coords(self.id)
|
||||||
self.move_src(src_x, src_y)
|
self.move_src(src_x, src_y)
|
||||||
|
|
||||||
|
def middle_label_pos(self) -> Tuple[float, float]:
|
||||||
|
_, _, x, y, _, _ = self.canvas.coords(self.id)
|
||||||
|
return x, y
|
||||||
|
|
||||||
|
def middle_label_text(self, text: str) -> None:
|
||||||
|
if self.middle_label is None:
|
||||||
|
x, y = self.middle_label_pos()
|
||||||
|
self.middle_label = self.canvas.create_text(
|
||||||
|
x, y, font=self.canvas.app.edge_font, text=text
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.canvas.itemconfig(self.middle_label, text=text)
|
||||||
|
|
||||||
def move_node(self, node_id: int, x: float, y: float) -> None:
|
def move_node(self, node_id: int, x: float, y: float) -> None:
|
||||||
if self.src == node_id:
|
if self.src == node_id:
|
||||||
self.move_src(x, y)
|
self.move_src(x, y)
|
||||||
|
@ -139,18 +155,23 @@ class Edge:
|
||||||
dst_pos = (x, y)
|
dst_pos = (x, y)
|
||||||
src_x, src_y, _, _, _, _ = self.canvas.coords(self.id)
|
src_x, src_y, _, _, _, _ = self.canvas.coords(self.id)
|
||||||
src_pos = (src_x, src_y)
|
src_pos = (src_x, src_y)
|
||||||
arc_pos = self._get_arcpoint(src_pos, dst_pos)
|
self.moved(src_pos, dst_pos)
|
||||||
self.canvas.coords(self.id, *src_pos, *arc_pos, *dst_pos)
|
|
||||||
|
|
||||||
def move_src(self, x: float, y: float) -> None:
|
def move_src(self, x: float, y: float) -> None:
|
||||||
src_pos = (x, y)
|
src_pos = (x, y)
|
||||||
_, _, _, _, dst_x, dst_y = self.canvas.coords(self.id)
|
_, _, _, _, dst_x, dst_y = self.canvas.coords(self.id)
|
||||||
dst_pos = (dst_x, dst_y)
|
dst_pos = (dst_x, dst_y)
|
||||||
|
self.moved(src_pos, dst_pos)
|
||||||
|
|
||||||
|
def moved(self, src_pos: Tuple[float, float], dst_pos: Tuple[float, float]) -> None:
|
||||||
arc_pos = self._get_arcpoint(src_pos, dst_pos)
|
arc_pos = self._get_arcpoint(src_pos, dst_pos)
|
||||||
self.canvas.coords(self.id, *src_pos, *arc_pos, *dst_pos)
|
self.canvas.coords(self.id, *src_pos, *arc_pos, *dst_pos)
|
||||||
|
if self.middle_label:
|
||||||
|
self.canvas.coords(self.middle_label, *arc_pos)
|
||||||
|
|
||||||
def delete(self) -> None:
|
def delete(self) -> None:
|
||||||
self.canvas.delete(self.id)
|
self.canvas.delete(self.id)
|
||||||
|
self.canvas.delete(self.middle_label)
|
||||||
|
|
||||||
|
|
||||||
class CanvasWirelessEdge(Edge):
|
class CanvasWirelessEdge(Edge):
|
||||||
|
@ -193,7 +214,6 @@ class CanvasEdge(Edge):
|
||||||
self.dst_interface = None
|
self.dst_interface = None
|
||||||
self.text_src = None
|
self.text_src = None
|
||||||
self.text_dst = None
|
self.text_dst = None
|
||||||
self.text_middle = None
|
|
||||||
self.link = None
|
self.link = None
|
||||||
self.asymmetric_link = None
|
self.asymmetric_link = None
|
||||||
self.throughput = None
|
self.throughput = None
|
||||||
|
@ -223,12 +243,6 @@ class CanvasEdge(Edge):
|
||||||
y2 = y2 - uy
|
y2 = y2 - uy
|
||||||
return x1, y1, x2, y2
|
return x1, y1, x2, y2
|
||||||
|
|
||||||
def get_midpoint(self) -> [float, float]:
|
|
||||||
x1, y1, x2, y2 = self.canvas.coords(self.id)
|
|
||||||
x = (x1 + x2) / 2
|
|
||||||
y = (y1 + y2) / 2
|
|
||||||
return x, y
|
|
||||||
|
|
||||||
def create_labels(self) -> Tuple[str, str]:
|
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"):
|
||||||
|
@ -271,27 +285,18 @@ class CanvasEdge(Edge):
|
||||||
x1, y1, x2, y2 = self.get_coordinates()
|
x1, y1, x2, y2 = self.get_coordinates()
|
||||||
self.canvas.coords(self.text_src, x1, y1)
|
self.canvas.coords(self.text_src, x1, y1)
|
||||||
self.canvas.coords(self.text_dst, x2, y2)
|
self.canvas.coords(self.text_dst, x2, y2)
|
||||||
if self.text_middle is not None:
|
|
||||||
x, y = self.get_midpoint()
|
|
||||||
self.canvas.coords(self.text_middle, x, y)
|
|
||||||
|
|
||||||
def set_throughput(self, throughput: float) -> None:
|
def set_throughput(self, throughput: float) -> None:
|
||||||
throughput = 0.001 * throughput
|
throughput = 0.001 * throughput
|
||||||
value = f"{throughput:.3f} kbps"
|
text = f"{throughput:.3f} kbps"
|
||||||
if self.text_middle is None:
|
self.middle_label_text(text)
|
||||||
x, y = self.get_midpoint()
|
self.canvas.addtag(self.middle_label, tags.THROUGHPUT)
|
||||||
self.text_middle = self.canvas.create_text(
|
|
||||||
x, y, tags=tags.THROUGHPUT, font=self.canvas.app.edge_font, text=value
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
self.canvas.itemconfig(self.text_middle, text=value)
|
|
||||||
|
|
||||||
if throughput > self.canvas.throughput_threshold:
|
if throughput > self.canvas.throughput_threshold:
|
||||||
color = self.canvas.throughput_color
|
color = self.canvas.throughput_color
|
||||||
width = self.canvas.throughput_width
|
width = self.canvas.throughput_width
|
||||||
else:
|
else:
|
||||||
color = EDGE_COLOR
|
color = self.color
|
||||||
width = EDGE_WIDTH
|
width = self.scaled_width()
|
||||||
self.canvas.itemconfig(self.id, fill=color, width=width)
|
self.canvas.itemconfig(self.id, fill=color, width=width)
|
||||||
|
|
||||||
def complete(self, dst: int) -> None:
|
def complete(self, dst: int) -> None:
|
||||||
|
@ -349,12 +354,11 @@ class CanvasEdge(Edge):
|
||||||
super().delete()
|
super().delete()
|
||||||
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)
|
|
||||||
|
|
||||||
def reset(self) -> None:
|
def reset(self) -> None:
|
||||||
self.canvas.delete(self.text_middle)
|
self.canvas.delete(self.middle_label)
|
||||||
self.text_middle = None
|
self.middle_label = None
|
||||||
self.canvas.itemconfig(self.id, fill=EDGE_COLOR, width=EDGE_WIDTH)
|
self.canvas.itemconfig(self.id, fill=self.color, width=self.scaled_width())
|
||||||
|
|
||||||
def create_context(self, event: tk.Event) -> None:
|
def create_context(self, event: tk.Event) -> None:
|
||||||
context = tk.Menu(self.canvas)
|
context = tk.Menu(self.canvas)
|
||||||
|
|
|
@ -200,17 +200,18 @@ class CanvasGraph(tk.Canvas):
|
||||||
self.tag_lower(self.grid)
|
self.tag_lower(self.grid)
|
||||||
|
|
||||||
def add_wireless_edge(
|
def add_wireless_edge(
|
||||||
self, src: CanvasNode, dst: CanvasNode, network_id: int = None
|
self, src: CanvasNode, dst: CanvasNode, link: core_pb2.Link
|
||||||
):
|
) -> None:
|
||||||
"""
|
network_id = link.network_id if link.network_id else None
|
||||||
add a wireless edge between 2 canvas nodes
|
|
||||||
"""
|
|
||||||
token = create_edge_token(src.id, dst.id, network_id)
|
token = create_edge_token(src.id, dst.id, network_id)
|
||||||
if token in self.wireless_edges:
|
if token in self.wireless_edges:
|
||||||
|
logging.warning("ignoring link that already exists: %s", link)
|
||||||
return
|
return
|
||||||
src_pos = self.coords(src.id)
|
src_pos = self.coords(src.id)
|
||||||
dst_pos = self.coords(dst.id)
|
dst_pos = self.coords(dst.id)
|
||||||
edge = CanvasWirelessEdge(self, src.id, dst.id, src_pos, dst_pos, token)
|
edge = CanvasWirelessEdge(self, src.id, dst.id, src_pos, dst_pos, token)
|
||||||
|
if link.label:
|
||||||
|
edge.middle_label_text(link.label)
|
||||||
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)
|
||||||
|
@ -221,8 +222,9 @@ class CanvasGraph(tk.Canvas):
|
||||||
arc_edges(common_edges)
|
arc_edges(common_edges)
|
||||||
|
|
||||||
def delete_wireless_edge(
|
def delete_wireless_edge(
|
||||||
self, src: CanvasNode, dst: CanvasNode, network_id: int = None
|
self, src: CanvasNode, dst: CanvasNode, link: core_pb2.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_edge_token(src.id, dst.id, network_id)
|
||||||
if token not in self.wireless_edges:
|
if token not in self.wireless_edges:
|
||||||
return
|
return
|
||||||
|
@ -234,6 +236,16 @@ class CanvasGraph(tk.Canvas):
|
||||||
common_edges = list(src.wireless_edges & dst.wireless_edges)
|
common_edges = list(src.wireless_edges & dst.wireless_edges)
|
||||||
arc_edges(common_edges)
|
arc_edges(common_edges)
|
||||||
|
|
||||||
|
def update_wireless_edge(
|
||||||
|
self, src: CanvasNode, dst: CanvasNode, link: core_pb2.Link
|
||||||
|
) -> None:
|
||||||
|
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)
|
||||||
|
edge = self.wireless_edges[token]
|
||||||
|
edge.middle_label_text(link.label)
|
||||||
|
|
||||||
def draw_session(self, session: core_pb2.Session):
|
def draw_session(self, session: core_pb2.Session):
|
||||||
"""
|
"""
|
||||||
Draw existing session.
|
Draw existing session.
|
||||||
|
|
|
@ -687,6 +687,7 @@ message Link {
|
||||||
Interface interface_two = 5;
|
Interface interface_two = 5;
|
||||||
LinkOptions options = 6;
|
LinkOptions options = 6;
|
||||||
int32 network_id = 7;
|
int32 network_id = 7;
|
||||||
|
string label = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
message LinkOptions {
|
message LinkOptions {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue