pygui: adjustments to help handle links between shadow nodes with initial desired behaviors

This commit is contained in:
Blake Harnden 2021-01-05 15:42:46 -08:00
parent 685b21924c
commit 3c97f80614
3 changed files with 106 additions and 67 deletions

View file

@ -120,7 +120,7 @@ class ShadowNode:
other_node = edge.src other_node = edge.src
if self.node == edge.src: if self.node == edge.src:
other_node = edge.dst other_node = edge.dst
if other_node.canvas == self.canvas: if not other_node.is_wireless() and other_node.canvas == self.canvas:
return False return False
return True return True
@ -224,13 +224,27 @@ class Edge:
def draw(self, state: str) -> None: def draw(self, state: str) -> None:
if not self.has_shadows(): if not self.has_shadows():
self.id = self.draw_edge(self.src.canvas, self.src, self.src, state) dst = self.dst if self.dst else self.src
self.id = self.draw_edge(self.src.canvas, self.src, dst, state)
elif self.linked_wireless:
if self.src.is_wireless():
self.src_shadow = self.dst.canvas.get_shadow(self.src)
self.id2 = self.draw_edge(
self.dst.canvas, self.src_shadow, self.dst, state
)
if self.dst.is_wireless():
self.dst_shadow = self.src.canvas.get_shadow(self.dst)
self.id = self.draw_edge(
self.src.canvas, self.src, self.dst_shadow, state
)
else: else:
# draw shadow nodes and 2 lines # draw shadow nodes and 2 lines
self.src_shadow = self.dst.canvas.get_shadow(self.src) self.src_shadow = self.dst.canvas.get_shadow(self.src)
self.dst_shadow = self.src.canvas.get_shadow(self.dst) self.dst_shadow = self.src.canvas.get_shadow(self.dst)
self.id = self.draw_edge(self.src.canvas, self.src, self.dst_shadow, state) self.id = self.draw_edge(self.src.canvas, self.src, self.dst_shadow, state)
self.id2 = self.draw_edge(self.dst.canvas, self.src_shadow, self.dst, state) self.id2 = self.draw_edge(self.dst.canvas, self.src_shadow, self.dst, state)
self.src.canvas.organize()
self.dst.canvas.organize()
logging.info( logging.info(
"drawed edge: src shadow(%s) dst shadow(%s)", "drawed edge: src shadow(%s) dst shadow(%s)",
self.src_shadow, self.src_shadow,
@ -261,7 +275,7 @@ class Edge:
def redraw(self) -> None: def redraw(self) -> None:
self.src.canvas.itemconfig(self.id, width=self.scaled_width(), fill=self.color) self.src.canvas.itemconfig(self.id, width=self.scaled_width(), fill=self.color)
self.move_src() self.move_src()
if self.has_shadows(): if self.id2:
self.dst.canvas.itemconfig( self.dst.canvas.itemconfig(
self.id2, width=self.scaled_width(), fill=self.color self.id2, width=self.scaled_width(), fill=self.color
) )
@ -279,7 +293,7 @@ class Edge:
justify=tk.CENTER, justify=tk.CENTER,
state=self.manager.show_link_labels.state(), state=self.manager.show_link_labels.state(),
) )
if self.has_shadows(): if self.id2:
_, _, x, y, _, _ = self.dst.canvas.coords(self.id2) _, _, x, y, _, _ = self.dst.canvas.coords(self.id2)
self.middle_label2 = self.dst.canvas.create_text( self.middle_label2 = self.dst.canvas.create_text(
x, x,
@ -292,29 +306,32 @@ class Edge:
) )
else: else:
self.src.canvas.itemconfig(self.middle_label, text=text) self.src.canvas.itemconfig(self.middle_label, text=text)
if self.has_shadows(): if self.middle_label2:
self.dst.canvas.itemconfig(self.middle_label2, text=text) self.dst.canvas.itemconfig(self.middle_label2, text=text)
def clear_middle_label(self) -> None: def clear_middle_label(self) -> None:
self.src.canvas.delete(self.middle_label) self.src.canvas.delete(self.middle_label)
self.middle_label = None self.middle_label = None
if self.has_shadows(): if self.middle_label2:
self.dst.canvas.delete(self.middle_label2) self.dst.canvas.delete(self.middle_label2)
self.middle_label2 = None self.middle_label2 = None
def src_label_text(self, text: str) -> None: def src_label_text(self, text: str) -> None:
if self.src_label is None: if self.src_label is None and self.src_label2 is None:
src_x, src_y, _, _, dst_x, dst_y = self.src.canvas.coords(self.id) if self.id:
src_pos, _ = node_label_positions(src_x, src_y, dst_x, dst_y) logging.info("src label id")
self.src_label = self.src.canvas.create_text( src_x, src_y, _, _, dst_x, dst_y = self.src.canvas.coords(self.id)
*src_pos, src_pos, _ = node_label_positions(src_x, src_y, dst_x, dst_y)
text=text, self.src_label = self.src.canvas.create_text(
justify=tk.CENTER, *src_pos,
font=self.app.edge_font, text=text,
tags=tags.LINK_LABEL, justify=tk.CENTER,
state=self.manager.show_link_labels.state(), font=self.app.edge_font,
) tags=tags.LINK_LABEL,
if self.has_shadows(): state=self.manager.show_link_labels.state(),
)
if self.id2:
logging.info("src label id2")
src_x, src_y, _, _, dst_x, dst_y = self.dst.canvas.coords(self.id2) src_x, src_y, _, _, dst_x, dst_y = self.dst.canvas.coords(self.id2)
src_pos, _ = node_label_positions(src_x, src_y, dst_x, dst_y) src_pos, _ = node_label_positions(src_x, src_y, dst_x, dst_y)
self.src_label2 = self.dst.canvas.create_text( self.src_label2 = self.dst.canvas.create_text(
@ -326,23 +343,25 @@ class Edge:
state=self.manager.show_link_labels.state(), state=self.manager.show_link_labels.state(),
) )
else: else:
self.src.canvas.itemconfig(self.src_label, text=text) if self.src_label:
if self.has_shadows(): self.src.canvas.itemconfig(self.src_label, text=text)
if self.src_label2:
self.dst.canvas.itemconfig(self.src_label2, text=text) self.dst.canvas.itemconfig(self.src_label2, text=text)
def dst_label_text(self, text: str) -> None: def dst_label_text(self, text: str) -> None:
if self.dst_label is None: if self.dst_label is None and self.dst_label2 is None:
src_x, src_y, _, _, dst_x, dst_y = self.src.canvas.coords(self.id) if self.id:
_, dst_pos = node_label_positions(src_x, src_y, dst_x, dst_y) src_x, src_y, _, _, dst_x, dst_y = self.src.canvas.coords(self.id)
self.dst_label = self.src.canvas.create_text( _, dst_pos = node_label_positions(src_x, src_y, dst_x, dst_y)
*dst_pos, self.dst_label = self.src.canvas.create_text(
text=text, *dst_pos,
justify=tk.CENTER, text=text,
font=self.app.edge_font, justify=tk.CENTER,
tags=tags.LINK_LABEL, font=self.app.edge_font,
state=self.manager.show_link_labels.state(), tags=tags.LINK_LABEL,
) state=self.manager.show_link_labels.state(),
if self.has_shadows(): )
if self.id2:
src_x, src_y, _, _, dst_x, dst_y = self.dst.canvas.coords(self.id2) src_x, src_y, _, _, dst_x, dst_y = self.dst.canvas.coords(self.id2)
_, dst_pos = node_label_positions(src_x, src_y, dst_x, dst_y) _, dst_pos = node_label_positions(src_x, src_y, dst_x, dst_y)
self.dst_label2 = self.dst.canvas.create_text( self.dst_label2 = self.dst.canvas.create_text(
@ -354,8 +373,9 @@ class Edge:
state=self.manager.show_link_labels.state(), state=self.manager.show_link_labels.state(),
) )
else: else:
self.src.canvas.itemconfig(self.dst_label, text=text) if self.dst_label:
if self.has_shadows(): self.src.canvas.itemconfig(self.dst_label, text=text)
if self.dst_label2:
self.dst.canvas.itemconfig(self.dst_label2, text=text) self.dst.canvas.itemconfig(self.dst_label2, text=text)
def drawing(self, pos: Tuple[float, float]) -> None: def drawing(self, pos: Tuple[float, float]) -> None:
@ -372,31 +392,39 @@ class Edge:
def move_shadow(self, node: "ShadowNode") -> None: def move_shadow(self, node: "ShadowNode") -> None:
if self.src_shadow == node: if self.src_shadow == node:
self.move_src_shadow() self.move_src_shadow()
else: elif self.dst_shadow == node:
self.move_dst_shadow() self.move_dst_shadow()
def move_src_shadow(self) -> None: def move_src_shadow(self) -> None:
if not self.id2:
return
_, _, _, _, dst_x, dst_y = self.dst.canvas.coords(self.id2) _, _, _, _, dst_x, dst_y = self.dst.canvas.coords(self.id2)
dst_pos = dst_x, dst_y dst_pos = dst_x, dst_y
self.moved2(self.src_shadow.position(), dst_pos) self.moved2(self.src_shadow.position(), dst_pos)
def move_dst_shadow(self) -> None: def move_dst_shadow(self) -> None:
if not self.id:
return
src_x, src_y, _, _, _, _ = self.src.canvas.coords(self.id) src_x, src_y, _, _, _, _ = self.src.canvas.coords(self.id)
src_pos = src_x, src_y src_pos = src_x, src_y
self.moved(src_pos, self.dst_shadow.position()) self.moved(src_pos, self.dst_shadow.position())
def move_dst(self) -> None: def move_dst(self) -> None:
if self.dst.is_wireless() and self.has_shadows():
return
dst_pos = self.dst.position() dst_pos = self.dst.position()
if not self.has_shadows(): if self.id2:
src_x, src_y, _, _, _, _ = self.dst.canvas.coords(self.id)
src_pos = src_x, src_y
self.moved(src_pos, dst_pos)
else:
src_x, src_y, _, _, _, _ = self.dst.canvas.coords(self.id2) src_x, src_y, _, _, _, _ = self.dst.canvas.coords(self.id2)
src_pos = src_x, src_y src_pos = src_x, src_y
self.moved2(src_pos, dst_pos) self.moved2(src_pos, dst_pos)
elif self.id:
src_x, src_y, _, _, _, _ = self.dst.canvas.coords(self.id)
src_pos = src_x, src_y
self.moved(src_pos, dst_pos)
def move_src(self) -> None: def move_src(self) -> None:
if not self.id:
return
_, _, _, _, dst_x, dst_y = self.src.canvas.coords(self.id) _, _, _, _, dst_x, dst_y = self.src.canvas.coords(self.id)
dst_pos = dst_x, dst_y dst_pos = dst_x, dst_y
self.moved(self.src.position(), dst_pos) self.moved(self.src.position(), dst_pos)
@ -485,6 +513,11 @@ class CanvasWirelessEdge(Edge):
def show_info(self, _event: tk.Event) -> None: def show_info(self, _event: tk.Event) -> None:
self.app.display_info(WirelessEdgeInfoFrame, app=self.app, edge=self) self.app.display_info(WirelessEdgeInfoFrame, app=self.app, edge=self)
def delete(self) -> None:
self.src.wireless_edges.discard(self)
self.dst.wireless_edges.remove(self)
super().delete()
class CanvasEdge(Edge): class CanvasEdge(Edge):
""" """
@ -504,16 +537,16 @@ class CanvasEdge(Edge):
self.asymmetric_link: Optional[Link] = None self.asymmetric_link: Optional[Link] = None
self.throughput: Optional[float] = None self.throughput: Optional[float] = None
self.draw(tk.NORMAL) self.draw(tk.NORMAL)
self.set_binding()
def is_customized(self) -> bool: def is_customized(self) -> bool:
return self.width != EDGE_WIDTH or self.color != EDGE_COLOR return self.width != EDGE_WIDTH or self.color != EDGE_COLOR
def set_binding(self) -> None: def set_bindings(self) -> None:
show_context = functools.partial(self.show_context, self.src.canvas) if self.id:
self.src.canvas.tag_bind(self.id, "<ButtonRelease-3>", show_context) show_context = functools.partial(self.show_context, self.src.canvas)
self.src.canvas.tag_bind(self.id, "<Button-1>", self.show_info) self.src.canvas.tag_bind(self.id, "<ButtonRelease-3>", show_context)
if self.dst and self.has_shadows(): self.src.canvas.tag_bind(self.id, "<Button-1>", self.show_info)
if self.id2:
show_context = functools.partial(self.show_context, self.dst.canvas) show_context = functools.partial(self.show_context, self.dst.canvas)
self.dst.canvas.tag_bind(self.id2, "<ButtonRelease-3>", show_context) self.dst.canvas.tag_bind(self.id2, "<ButtonRelease-3>", show_context)
self.dst.canvas.tag_bind(self.id2, "<Button-1>", self.show_info) self.dst.canvas.tag_bind(self.id2, "<Button-1>", self.show_info)
@ -556,16 +589,16 @@ class CanvasEdge(Edge):
if self.link.options.loss == EDGE_LOSS: if self.link.options.loss == EDGE_LOSS:
state = tk.HIDDEN state = tk.HIDDEN
self.src.canvas.addtag_withtag(tags.LOSS_EDGES, self.id) self.src.canvas.addtag_withtag(tags.LOSS_EDGES, self.id)
if self.has_shadows(): if self.id2:
self.dst.canvas.addtag_withtag(tags.LOSS_EDGES, self.id2) self.dst.canvas.addtag_withtag(tags.LOSS_EDGES, self.id2)
else: else:
state = tk.NORMAL state = tk.NORMAL
self.src.canvas.dtag(self.id, tags.LOSS_EDGES) self.src.canvas.dtag(self.id, tags.LOSS_EDGES)
if self.has_shadows(): if self.id2:
self.dst.canvas.dtag(self.id2, tags.LOSS_EDGES) self.dst.canvas.dtag(self.id2, tags.LOSS_EDGES)
if self.manager.show_loss_links.state() == tk.HIDDEN: if self.manager.show_loss_links.state() == tk.HIDDEN:
self.src.canvas.itemconfigure(self.id, state=state) self.src.canvas.itemconfigure(self.id, state=state)
if self.has_shadows(): if self.id2:
self.dst.canvas.itemconfigure(self.id2, state=state) self.dst.canvas.itemconfigure(self.id2, state=state)
def set_throughput(self, throughput: float) -> None: def set_throughput(self, throughput: float) -> None:
@ -579,7 +612,7 @@ class CanvasEdge(Edge):
color = self.color color = self.color
width = self.scaled_width() width = self.scaled_width()
self.src.canvas.itemconfig(self.id, fill=color, width=width) self.src.canvas.itemconfig(self.id, fill=color, width=width)
if self.has_shadows(): if self.id2:
self.dst.canvas.itemconfig(self.id2, fill=color, width=width) self.dst.canvas.itemconfig(self.id2, fill=color, width=width)
def clear_throughput(self) -> None: def clear_throughput(self) -> None:
@ -590,18 +623,20 @@ class CanvasEdge(Edge):
def complete(self, dst: "CanvasNode") -> None: def complete(self, dst: "CanvasNode") -> None:
self.dst = dst self.dst = dst
self.linked_wireless = self.src.is_wireless() or self.dst.is_wireless() self.linked_wireless = self.src.is_wireless() or self.dst.is_wireless()
self.move_dst() self.set_bindings()
self.check_wireless() self.check_wireless()
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 check_wireless(self) -> None: def check_wireless(self) -> None:
if not self.linked_wireless: if not self.linked_wireless:
return return
self.src.canvas.itemconfig(self.id, state=tk.HIDDEN) if self.id:
self.src.canvas.dtag(self.id, tags.EDGE) # self.src.canvas.itemconfig(self.id, state=tk.HIDDEN)
if self.has_shadows(): self.src.canvas.dtag(self.id, tags.EDGE)
self.dst.canvas.itemconfig(self.id2, state=tk.HIDDEN) if self.id2:
# self.dst.canvas.itemconfig(self.id2, state=tk.HIDDEN)
self.dst.canvas.dtag(self.id2, tags.EDGE) self.dst.canvas.dtag(self.id2, tags.EDGE)
# add antenna to node
if self.src.is_wireless() and not self.dst.is_wireless(): if self.src.is_wireless() and not self.dst.is_wireless():
self.dst.add_antenna() self.dst.add_antenna()
elif not self.src.is_wireless() and self.dst.is_wireless(): elif not self.src.is_wireless() and self.dst.is_wireless():
@ -610,12 +645,17 @@ class CanvasEdge(Edge):
self.src.add_antenna() self.src.add_antenna()
def reset(self) -> None: def reset(self) -> None:
self.src.canvas.delete(self.middle_label) if self.middle_label:
self.middle_label = None self.src.canvas.delete(self.middle_label)
self.src.canvas.itemconfig(self.id, fill=self.color, width=self.scaled_width()) self.middle_label = None
if self.has_shadows(): if self.middle_label2:
self.dst.canvas.delete(self.middle_label2) self.dst.canvas.delete(self.middle_label2)
self.middle_label2 = None self.middle_label2 = None
if self.id:
self.src.canvas.itemconfig(
self.id, fill=self.color, width=self.scaled_width()
)
if self.id2:
self.dst.canvas.itemconfig( self.dst.canvas.itemconfig(
self.id2, fill=self.color, width=self.scaled_width() self.id2, fill=self.color, width=self.scaled_width()
) )
@ -690,4 +730,5 @@ class CanvasEdge(Edge):
self.src.delete_antenna() self.src.delete_antenna()
self.app.core.deleted_canvas_edges([self]) self.app.core.deleted_canvas_edges([self])
super().delete() super().delete()
self.arc_common_edges() if self.dst:
self.arc_common_edges()

View file

@ -287,8 +287,6 @@ class CanvasGraph(tk.Canvas):
# delete node and related edges # delete node and related edges
if object_id in self.nodes: if object_id in self.nodes:
canvas_node = self.nodes.pop(object_id) canvas_node = self.nodes.pop(object_id)
canvas_node.delete()
nodes.append(canvas_node)
# delete related edges # delete related edges
while canvas_node.edges: while canvas_node.edges:
edge = canvas_node.edges.pop() edge = canvas_node.edges.pop()
@ -296,6 +294,9 @@ class CanvasGraph(tk.Canvas):
continue continue
edges.add(edge) edges.add(edge)
edge.delete() edge.delete()
# delete node
canvas_node.delete()
nodes.append(canvas_node)
# delete shape # delete shape
if object_id in self.shapes: if object_id in self.shapes:

View file

@ -325,7 +325,6 @@ class CanvasManager:
dst.wireless_edges.add(edge) dst.wireless_edges.add(edge)
src.canvas.tag_raise(src.id) src.canvas.tag_raise(src.id)
dst.canvas.tag_raise(dst.id) dst.canvas.tag_raise(dst.id)
edge.arc_common_edges()
def delete_wireless_edge( def delete_wireless_edge(
self, src: CanvasNode, dst: CanvasNode, link: Link self, src: CanvasNode, dst: CanvasNode, link: Link
@ -336,9 +335,6 @@ class CanvasManager:
return return
edge = self.wireless_edges.pop(token) edge = self.wireless_edges.pop(token)
edge.delete() edge.delete()
src.wireless_edges.remove(edge)
dst.wireless_edges.remove(edge)
edge.arc_common_edges()
def update_wireless_edge( def update_wireless_edge(
self, src: CanvasNode, dst: CanvasNode, link: Link self, src: CanvasNode, dst: CanvasNode, link: Link
@ -372,7 +368,8 @@ class CanvasManager:
src.edges.add(edge) src.edges.add(edge)
dst.edges.add(edge) dst.edges.add(edge)
edge.token = create_edge_token(edge.link) edge.token = create_edge_token(edge.link)
edge.arc_common_edges() if not edge.linked_wireless:
edge.arc_common_edges()
edge.draw_labels() edge.draw_labels()
edge.check_options() edge.check_options()
self.edges[edge.token] = edge self.edges[edge.token] = edge