updates to handling movement for nodes/shapes on canvas, added initial canvas zoom/panning, fixed some issues with mobility player event handling when dialog is closed

This commit is contained in:
Blake Harnden 2019-12-10 14:33:52 -08:00
parent 17c78d59cd
commit 51163a30d3
6 changed files with 128 additions and 148 deletions

View file

@ -1,4 +1,3 @@
import logging
import tkinter as tk
from tkinter import font
@ -11,7 +10,6 @@ from coretk.dialogs.nodeconfig import NodeConfigDialog
from coretk.dialogs.wlanconfig import WlanConfigDialog
from coretk.errors import show_grpc_error
from coretk.graph import tags
from coretk.graph.enums import GraphMode
from coretk.graph.tooltip import CanvasTooltip
from coretk.nodeutils import NodeUtils
@ -29,12 +27,11 @@ class CanvasNode:
self.id = self.canvas.create_image(
x, y, anchor=tk.CENTER, image=self.image, tags=tags.NODE
)
image_box = self.canvas.bbox(self.id)
y = image_box[3] + NODE_TEXT_OFFSET
text_font = font.Font(family="TkIconFont", size=12)
label_y = self._get_label_y()
self.text_id = self.canvas.create_text(
x,
y,
label_y,
text=self.core_node.name,
tags=tags.NODE_NAME,
font=text_font,
@ -44,17 +41,11 @@ class CanvasNode:
self.edges = set()
self.interfaces = []
self.wireless_edges = set()
self.moving = None
self.antennae = []
self.setup_bindings()
def setup_bindings(self):
# self.canvas.bind("<Button-3>", self.click_context)
self.canvas.tag_bind(self.id, "<ButtonPress-1>", self.click_press)
self.canvas.tag_bind(self.id, "<ButtonRelease-1>", self.click_release)
self.canvas.tag_bind(self.id, "<B1-Motion>", self.motion)
self.canvas.tag_bind(self.id, "<Double-Button-1>", self.double_click)
self.canvas.tag_bind(self.id, "<Control-1>", self.select_multiple)
self.canvas.tag_bind(self.id, "<Enter>", self.on_enter)
self.canvas.tag_bind(self.id, "<Leave>", self.on_leave)
@ -95,30 +86,32 @@ class CanvasNode:
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)
self.canvas.itemconfig(self.text_id, text=self.core_node.name)
def move(self, x, y, update=True):
old_x = self.core_node.position.x
old_y = self.core_node.position.y
x_offset = x - old_x
y_offset = y - old_y
self.core_node.position.x = int(x)
self.core_node.position.y = int(y)
def _get_label_y(self):
image_box = self.canvas.bbox(self.id)
return image_box[3] + NODE_TEXT_OFFSET
def move(self, x, y):
x_offset = x - self.core_node.position.x
y_offset = y - self.core_node.position.y
self.motion(x_offset, y_offset, update=False)
def motion(self, x_offset, y_offset, update=True):
self.canvas.move(self.id, x_offset, y_offset)
self.canvas.move(self.text_id, x_offset, y_offset)
self.move_antennae(x_offset, y_offset)
self.canvas.object_drag(self.id, x_offset, y_offset)
self.canvas.move_selection(self.id, x_offset, y_offset)
x, y = self.canvas.coords(self.id)
self.core_node.position.x = int(x)
self.core_node.position.y = int(y)
# move antennae
for antenna_id in self.antennae:
self.canvas.move(antenna_id, x_offset, y_offset)
# move edges
for edge in self.edges:
x1, y1, x2, y2 = self.canvas.coords(edge.id)
if edge.src == self.id:
@ -126,16 +119,18 @@ class CanvasNode:
else:
self.canvas.coords(edge.id, x1, y1, x, y)
self.canvas.throughput_draw.move(edge)
edge.link_info.recalculate_info()
for edge in self.wireless_edges:
x1, y1, x2, y2 = self.canvas.coords(edge.id)
if edge.src == self.id:
self.canvas.coords(edge.id, x, y, x2, y2)
else:
self.canvas.coords(edge.id, x1, y1, x, y)
# update core with new location
if self.app.core.is_runtime() and update:
self.app.core.edit_node(self.core_node.id, int(x), int(y))
self.app.core.edit_node(self.core_node)
def on_enter(self, event):
if self.app.core.is_runtime() and self.app.core.observer:
@ -164,39 +159,6 @@ class CanvasNode:
self.core_node.position.x = int(x)
self.core_node.position.y = int(y)
def click_press(self, event):
logging.debug(f"node click press {self.core_node.name}: {event}")
self.moving = self.canvas.canvas_xy(event)
if self.id not in self.canvas.selection:
self.canvas.select_object(self.id)
self.canvas.selected = self.id
def click_release(self, event):
logging.debug(f"node click release {self.core_node.name}: {event}")
self.update_coords()
self.moving = None
def motion(self, event):
if self.canvas.mode == GraphMode.EDGE:
return
x, y = self.canvas.canvas_xy(event)
my_x = self.core_node.position.x
my_y = self.core_node.position.y
self.move(x, y)
# move other selected components
for object_id, selection_id in self.canvas.selection.items():
if object_id != self.id and object_id in self.canvas.nodes:
canvas_node = self.canvas.nodes[object_id]
other_old_x = canvas_node.core_node.position.x
other_old_y = canvas_node.core_node.position.y
other_new_x = x + other_old_x - my_x
other_new_y = y + other_old_y - my_y
self.canvas.nodes[object_id].move(other_new_x, other_new_y)
elif object_id in self.canvas.shapes:
shape = self.canvas.shapes[object_id]
shape.motion(None, x - my_x, y - my_y)
def create_context(self):
is_wlan = self.core_node.type == NodeType.WIRELESS_LAN
is_emane = self.core_node.type == NodeType.EMANE
@ -244,9 +206,6 @@ class CanvasNode:
context.add_command(label="Hide", state=tk.DISABLED)
return context
def select_multiple(self, event):
self.canvas.select_object(self.id, choose_multiple=True)
def show_config(self):
self.canvas.context = None
dialog = NodeConfigDialog(self.app, self.app, self)