From dcfd7f879535a331a795c58c7b8fc76ea5c8eded Mon Sep 17 00:00:00 2001 From: Huy Pham <42948410+hpham@users.noreply.github.com> Date: Thu, 7 Nov 2019 13:23:02 -0800 Subject: [PATCH] working on delete node --- coretk/coretk/coreclient.py | 49 ++++++++++++++++------- coretk/coretk/coretoolbarhelp.py | 3 ++ coretk/coretk/graph.py | 36 ++++++++++++++++- coretk/coretk/mobilitynodeconfig.py | 4 ++ coretk/coretk/nodedelete.py | 61 +++++++++++++++++++++++++++++ 5 files changed, 138 insertions(+), 15 deletions(-) create mode 100644 coretk/coretk/nodedelete.py diff --git a/coretk/coretk/coreclient.py b/coretk/coretk/coreclient.py index 2f6e0b88..ae03922b 100644 --- a/coretk/coretk/coreclient.py +++ b/coretk/coretk/coreclient.py @@ -500,6 +500,41 @@ class CoreClient: name, ) + def delete_wanted_graph_nodes(self, canvas_ids, tokens): + """ + remove the nodes selected by the user and anything related to that node + such as link, configurations, interfaces + + :param list(int) canvas_ids: list of canvas node ids + :return: nothing + """ + # keep reference to the core ids + core_node_ids = [self.nodes[x].node_id for x in canvas_ids] + + # delete the nodes + for i in canvas_ids: + try: + self.nodes.pop(i) + self.reusable.append(i) + except KeyError: + logging.error("coreclient.py INVALID NODE CANVAS ID") + + self.reusable.sort() + + # delete the edges and interfaces + for i in tokens: + try: + self.edges.pop(i) + except KeyError: + logging.error("coreclient.py invalid edge token ") + + # delete any configurations + for i in core_node_ids: + if i in self.mobilityconfig_management.configurations: + self.mobilityconfig_management.pop(i) + if i in self.wlanconfig_management.configurations: + self.wlanconfig_management.pop(i) + def add_preexisting_node(self, canvas_node, session_id, core_node, name): """ Add preexisting nodes to grpc manager @@ -553,20 +588,6 @@ class CoreClient: self.preexisting.clear() logging.debug("Next id: %s, Reusable: %s", self.id, self.reusable) - def delete_node(self, canvas_id): - """ - Delete a node from the session - - :param int canvas_id: node's id in the canvas - :return: thing - """ - try: - self.nodes.pop(canvas_id) - self.reusable.append(canvas_id) - self.reusable.sort() - except KeyError: - logging.error("grpcmanagement.py INVALID NODE CANVAS ID") - def create_interface(self, node_type, gui_interface): """ create a protobuf interface given the interface object stored by the programmer diff --git a/coretk/coretk/coretoolbarhelp.py b/coretk/coretk/coretoolbarhelp.py index c650a5bc..5192f2c5 100644 --- a/coretk/coretk/coretoolbarhelp.py +++ b/coretk/coretk/coretoolbarhelp.py @@ -110,3 +110,6 @@ class CoreToolbarHelp: emane_config=emane_config, emane_model_configs=emane_model_configs, ) + + response = self.app.core.client.get_session(self.app.core.session_id) + print(response) diff --git a/coretk/coretk/graph.py b/coretk/coretk/graph.py index 448a6f1d..9ab6b956 100644 --- a/coretk/coretk/graph.py +++ b/coretk/coretk/graph.py @@ -8,6 +8,7 @@ from coretk.graph_helper import GraphHelper, WlanAntennaManager from coretk.images import Images from coretk.interface import Interface from coretk.linkinfo import LinkInfo, Throughput +from coretk.nodedelete import CanvasComponentManagement from coretk.wirelessconnection import WirelessConnection @@ -41,7 +42,11 @@ class CanvasGraph(tk.Canvas): self.drawing_edge = None self.grid = None self.meters_per_pixel = 1.5 + + self.canvas_management = CanvasComponentManagement(self, core) + self.canvas_action = CanvasAction(master, self) + self.setup_menus() self.setup_bindings() self.draw_grid() @@ -101,6 +106,7 @@ class CanvasGraph(tk.Canvas): self.bind("", self.click_release) self.bind("", self.click_motion) self.bind("", self.context) + self.bind("", self.press_delete) def draw_grid(self, width=1000, height=800): """ @@ -377,6 +383,25 @@ class CanvasGraph(tk.Canvas): self.node_context.unpost() self.is_node_context_opened = False + def press_delete(self, event): + # hide nodes, links, link information that shows on the GUI + to_delete_nodes, to_delete_edge_tokens = ( + self.canvas_management.delete_selected_nodes() + ) + + # delete nodes and link info stored in CanvasGraph object + for nid in to_delete_nodes: + self.nodes.pop(nid) + for token in to_delete_edge_tokens: + self.edges.pop(token) + + self.core.delete_wanted_graph_nodes(to_delete_nodes, to_delete_edge_tokens) + # delete any configuration related to the links and nodes + + # delete selected node + + # delete links connected to the selected nodes + def add_node(self, x, y, image, node_name): plot_id = self.find_all()[0] if self.selected == plot_id: @@ -473,11 +498,15 @@ class CanvasNode: self.canvas.tag_bind(self.id, "", self.motion) self.canvas.tag_bind(self.id, "", self.context) self.canvas.tag_bind(self.id, "", self.double_click) + self.canvas.tag_bind(self.id, "", self.select_multiple) self.edges = set() self.wlans = [] self.moving = None + def click(self, event): + print("click") + def double_click(self, event): node_id = self.canvas.core.nodes[self.id].node_id state = self.canvas.core.get_session_state() @@ -500,7 +529,8 @@ class CanvasNode: def click_press(self, event): logging.debug(f"click press {self.name}: {event}") self.moving = self.canvas.canvas_xy(event) - # return "break" + + self.canvas.canvas_management.node_select(self) def click_release(self, event): logging.debug(f"click release {self.name}: {event}") @@ -520,6 +550,7 @@ class CanvasNode: self.canvas.move(self.id, offset_x, offset_y) self.canvas.move(self.text_id, offset_x, offset_y) self.antenna_draw.update_antennas_position(offset_x, offset_y) + self.canvas.canvas_management.node_drag(self, offset_x, offset_y) new_x, new_y = self.canvas.coords(self.id) @@ -539,5 +570,8 @@ class CanvasNode: old_x, old_y, new_x, new_y, self.wlans ) + def select_multiple(self, event): + self.canvas.canvas_management.node_select(self, True) + def context(self, event): logging.debug(f"context click {self.name}: {event}") diff --git a/coretk/coretk/mobilitynodeconfig.py b/coretk/coretk/mobilitynodeconfig.py index e79e58ac..4a94f573 100644 --- a/coretk/coretk/mobilitynodeconfig.py +++ b/coretk/coretk/mobilitynodeconfig.py @@ -10,6 +10,10 @@ from core.api.grpc import core_pb2 class MobilityNodeConfig: def __init__(self): + """ + create an instance of MobilityConfig object + """ + # dict that maps node id to mobility configuration self.configurations = {} def set_default_configuration(self, node_type, node_id): diff --git a/coretk/coretk/nodedelete.py b/coretk/coretk/nodedelete.py new file mode 100644 index 00000000..6ce3a6f9 --- /dev/null +++ b/coretk/coretk/nodedelete.py @@ -0,0 +1,61 @@ +""" +manage deletion +""" + + +class CanvasComponentManagement: + def __init__(self, canvas, core): + self.app = core + self.canvas = canvas + + # dictionary that maps node to box + self.selected = {} + + def node_select(self, canvas_node, choose_multiple=False): + """ + create a bounding box when a node is selected + + :param coretk.graph.CanvasNode canvas_node: canvas node object + :return: nothing + """ + + if not choose_multiple: + self.delete_current_bbox() + + # draw a bounding box if node hasn't been selected yet + if canvas_node.id not in self.selected: + x0, y0, x1, y1 = self.canvas.bbox(canvas_node.id) + bbox_id = self.canvas.create_rectangle( + (x0 - 6, y0 - 6, x1 + 6, y1 + 6), activedash=True, dash="-" + ) + self.selected[canvas_node.id] = bbox_id + + def node_drag(self, canvas_node, offset_x, offset_y): + self.canvas.move(self.selected[canvas_node.id], offset_x, offset_y) + + def delete_current_bbox(self): + for bbid in self.selected.values(): + self.canvas.delete(bbid) + self.selected.clear() + + def delete_selected_nodes(self): + selected_nodes = list(self.selected.keys()) + edges = set() + for n in selected_nodes: + edges = edges.union(self.canvas.nodes[n].edges) + edge_canvas_ids = [x.id for x in edges] + edge_tokens = [x.token for x in edges] + link_infos = [x.link_info.id1 for x in edges] + [x.link_info.id2 for x in edges] + + for i in edge_canvas_ids: + self.canvas.itemconfig(i, state="hidden") + + for i in link_infos: + self.canvas.itemconfig(i, state="hidden") + + for cnid, bbid in self.selected.items(): + self.canvas.itemconfig(cnid, state="hidden") + self.canvas.itemconfig(bbid, state="hidden") + self.canvas.itemconfig(self.canvas.nodes[cnid].text_id, state="hidden") + self.selected.clear() + return selected_nodes, edge_tokens