finish the basics of toolbar and start working on simple grpc

This commit is contained in:
Huy Pham 2019-10-01 16:25:26 -07:00
parent 269d7f8f92
commit cbd593eed6
5 changed files with 254 additions and 95 deletions

View file

@ -1,6 +1,8 @@
import logging
import tkinter as tk
import coretk.images as images
from coretk.coregrpc import CoreGrpc
from coretk.coremenubar import CoreMenubar
from coretk.coretoolbar import CoreToolbar
from coretk.graph import CanvasGraph
@ -13,11 +15,16 @@ class Application(tk.Frame):
self.load_images()
self.setup_app()
self.menubar = None
self.canvas = None
self.core_grpc = CoreGrpc()
self.create_menu()
self.create_widgets()
def load_images(self):
Images.load("core", "core-icon.png")
images.load_core_images(Images)
def close_grpc(self):
self.core_grpc.close()
def setup_app(self):
self.master.title("CORE")
@ -40,11 +47,14 @@ class Application(tk.Frame):
core_editbar.create_toolbar()
self.canvas = CanvasGraph(
master=self, background="#cccccc", scrollregion=(0, 0, 1000, 1000)
grpc=self.core_grpc,
master=self,
background="#cccccc",
scrollregion=(0, 0, 1000, 1000),
)
self.canvas.pack(fill=tk.BOTH, expand=True)
# self.canvas.create_rectangle(0, 0, 1000, 750, outline="#000000", fill="#ffffff", width=1)
core_editbar.update_canvas(self.canvas)
scroll_x = tk.Scrollbar(
self.canvas, orient=tk.HORIZONTAL, command=self.canvas.xview
@ -69,3 +79,4 @@ if __name__ == "__main__":
logging.basicConfig(level=logging.DEBUG)
app = Application()
app.mainloop()
app.close_grpc()

83
coretk/coretk/coregrpc.py Normal file
View file

@ -0,0 +1,83 @@
"""
Incorporate grpc into python tkinter GUI
"""
import logging
from core.api.grpc import client, core_pb2
class CoreGrpc:
def __init__(self):
"""
Create a CoreGrpc instance
"""
self.core = client.CoreGrpcClient()
self.session_id = None
self.set_up()
def log_event(self, event):
logging.info("event: %s", event)
def set_up(self):
"""
Create session, handle events session may broadcast, change session state
:return: nothing
"""
self.core.connect()
# create session
response = self.core.create_session()
logging.info("created session: %s", response)
# handle events session may broadcast
self.session_id = response.session_id
self.core.events(self.session_id, self.log_event)
# change session state
response = self.core.set_session_state(
self.session_id, core_pb2.SessionState.CONFIGURATION
)
logging.info("set session state: %s", response)
def get_session_id(self):
return self.session_id
# TODO add checkings to the function
def add_node(self, x, y, node_name):
link_layer_nodes = ["switch", "hub", "wlan", "rj45", "tunnel"]
network_layer_nodes = ["default"]
node = None
if node_name in link_layer_nodes:
if node_name == "switch":
node = core_pb2.Node(type=core_pb2.NodeType.SWITCH)
elif node_name == "hub":
node = core_pb2.Node(type=core_pb2.NodeType.HUB)
elif node_name == "wlan":
node = core_pb2.Node(type=core_pb2.NodeType.WIRELESS_LAN)
elif node_name == "rj45":
node = core_pb2.Node(type=core_pb2.NodeType.RJ45)
elif node_name == "tunnel":
node = core_pb2.Node(type=core_pb2.NodeType.TUNNEL)
elif node_name in network_layer_nodes:
position = core_pb2.Position(x=x, y=y)
node = core_pb2.Node(position=position)
else:
return
response = self.core.add_node(self.session_id, node)
logging.info("created %s: %s", node_name, response)
return response.node_id
def edit_node(self, session_id, node_id, x, y):
position = core_pb2.Position(x=x, y=y)
response = self.core.edit_node(session_id, node_id, position)
logging.info("updated node id %s: %s", node_id, response)
def close(self):
"""
Clean ups when done using grpc
:return: nothing
"""
logging.debug("Close grpc")
self.core.close()

View file

@ -36,57 +36,17 @@ class CoreToolbar(object):
self.network_layer_option_menu = None
# variables used by canvas graph
self.mode = GraphMode.SELECT
self.image_to_draw = None
self.canvas = None
def load_toolbar_images(self):
def update_canvas(self, canvas):
"""
Load the images that appear in core toolbar
Update canvas variable in CoreToolbar class
:param tkinter.Canvas canvas: core canvas
:return: nothing
"""
Images.load("core", "core-icon.png")
Images.load("start", "start.gif")
Images.load("switch", "lanswitch.gif")
Images.load("marker", "marker.gif")
Images.load("router", "router.gif")
Images.load("select", "select.gif")
Images.load("link", "link.gif")
Images.load("hub", "hub.gif")
Images.load("wlan", "wlan.gif")
Images.load("rj45", "rj45.gif")
Images.load("tunnel", "tunnel.gif")
Images.load("oval", "oval.gif")
Images.load("rectangle", "rectangle.gif")
Images.load("text", "text.gif")
Images.load("host", "host.gif")
Images.load("pc", "pc.gif")
Images.load("mdr", "mdr.gif")
Images.load("prouter", "router_green.gif")
Images.load("ovs", "OVS.gif")
Images.load("editnode", "document-properties.gif")
Images.load("run", "run.gif")
Images.load("plot", "plot.gif")
Images.load("twonode", "twonode.gif")
Images.load("stop", "stop.gif")
Images.load("observe", "observe.gif")
def get_graph_mode(self):
"""
Retrieve current graph mode
:rtype: int
:return: current graph mode
"""
return self.mode
def set_graph_mode(self, mode):
"""
Set graph mode
:param int mode: graph mode
:return: nothing
"""
self.mode = mode
self.canvas = canvas
def destroy_previous_frame(self):
"""
@ -189,47 +149,67 @@ class CoreToolbar(object):
def click_selection_tool(self):
logging.debug("Click SELECTION TOOL")
self.set_graph_mode(GraphMode.SELECT)
self.canvas.mode = GraphMode.SELECT
def click_start_stop_session_tool(self):
logging.debug("Click START STOP SESSION button")
self.destroy_children_widgets(self.edit_frame)
self.canvas.set_canvas_mode(GraphMode.SELECT)
self.create_runtime_toolbar()
def click_link_tool(self):
logging.debug("Click LINK button")
self.set_graph_mode(GraphMode.EDGE)
self.canvas.set_canvas_mode(GraphMode.EDGE)
def pick_router(self, main_button):
logging.debug("Pick router option")
self.network_layer_option_menu.destroy()
main_button.configure(image=Images.get("router"))
logging.debug("Pick router option")
self.canvas.set_canvas_mode(GraphMode.PICKNODE)
self.canvas.set_drawing_image(Images.get("router"))
self.canvas.set_drawing_name("default")
def pick_host(self, main_button):
logging.debug("Pick host option")
self.network_layer_option_menu.destroy()
main_button.configure(image=Images.get("host"))
logging.debug("Pick host option")
self.canvas.set_canvas_mode(GraphMode.PICKNODE)
self.canvas.set_drawing_image(Images.get("host"))
self.canvas.set_drawing_name("default")
def pick_pc(self, main_button):
logging.debug("Pick PC option")
self.network_layer_option_menu.destroy()
main_button.configure(image=Images.get("pc"))
logging.debug("Pick PC option")
self.canvas.set_canvas_mode(GraphMode.PICKNODE)
self.canvas.set_drawing_image(Images.get("pc"))
self.canvas.set_drawing_name("default")
def pick_mdr(self, main_button):
logging.debug("Pick MDR option")
self.network_layer_option_menu.destroy()
main_button.configure(image=Images.get("mdr"))
logging.debug("Pick MDR option")
self.canvas.set_canvas_mode(GraphMode.PICKNODE)
self.canvas.set_drawing_image(Images.get("mdr"))
self.canvas.set_drawing_name("default")
def pick_prouter(self, main_button):
logging.debug("Pick prouter option")
self.network_layer_option_menu.destroy()
main_button.configure(image=Images.get("prouter"))
logging.debug("Pick prouter option")
self.canvas.set_canvas_mode(GraphMode.PICKNODE)
self.canvas.set_drawing_image(Images.get("prouter"))
self.canvas.set_drawing_name("default")
def pick_ovs(self, main_button):
logging.debug("Pick OVS option")
self.network_layer_option_menu.destroy()
main_button.configure(image=Images.get("ovs"))
logging.debug("Pick OVS option")
self.canvas.set_canvas_mode(GraphMode.PICKNODE)
self.canvas.set_drawing_image(Images.get("ovs"))
self.canvas.set_drawing_name("default")
# TODO what graph node is this
def pick_editnode(self, main_button):
self.network_layer_option_menu.destroy()
main_button.configure(image=Images.get("editnode"))
@ -311,29 +291,43 @@ class CoreToolbar(object):
CreateToolTip(network_layer_button, "Network-layer virtual nodes")
def pick_hub(self, main_button):
logging.debug("Pick link-layer node HUB")
self.link_layer_option_menu.destroy()
main_button.configure(image=Images.get("hub"))
logging.debug("Pick link-layer node HUB")
self.canvas.set_canvas_mode(GraphMode.PICKNODE)
self.canvas.set_drawing_image(Images.get("hub"))
self.canvas.set_drawing_name("hub")
def pick_switch(self, main_button):
logging.debug("Pick link-layer node SWITCH")
self.link_layer_option_menu.destroy()
main_button.configure(image=Images.get("switch"))
logging.debug("Pick link-layer node SWITCH")
self.canvas.set_canvas_mode(GraphMode.PICKNODE)
self.canvas.set_drawing_image(Images.get("switch"))
self.canvas.set_drawing_name("switch")
def pick_wlan(self, main_button):
logging.debug("Pick link-layer node WLAN")
self.link_layer_option_menu.destroy()
main_button.configure(image=Images.get("wlan"))
logging.debug("Pick link-layer node WLAN")
self.canvas.set_canvas_mode(GraphMode.PICKNODE)
self.canvas.set_drawing_image(Images.get("wlan"))
self.canvas.set_drawing_name("wlan")
def pick_rj45(self, main_button):
logging.debug("Pick link-layer node RJ45")
self.link_layer_option_menu.destroy()
main_button.configure(image=Images.get("rj45"))
logging.debug("Pick link-layer node RJ45")
self.canvas.set_canvas_mode(GraphMode.PICKNODE)
self.canvas.set_drawing_image(Images.get("rj45"))
def pick_tunnel(self, main_button):
logging.debug("Pick link-layer node TUNNEL")
self.link_layer_option_menu.destroy()
main_button.configure(image=Images.get("tunnel"))
logging.debug("Pick link-layer node TUNNEL")
self.canvas.set_canvas_mode(GraphMode.PICKNODE)
self.canvas.set_drawing_image(Images.get("tunnel"))
self.canvas.set_drawing_image(Images.get("tunnel"))
def draw_link_layer_options(self, link_layer_button):
"""
@ -482,7 +476,7 @@ class CoreToolbar(object):
CreateToolTip(marker_main_button, "background annotation tools")
def create_toolbar(self):
self.load_toolbar_images()
# self.load_toolbar_images()
self.create_regular_button(
self.edit_frame,
Images.get("start"),
@ -508,6 +502,7 @@ class CoreToolbar(object):
self.create_network_layer_button()
self.create_link_layer_button()
self.create_marker_button()
self.radio_value.set(1)
def create_observe_button(self):
menu_button = tk.Menubutton(
@ -599,3 +594,4 @@ class CoreToolbar(object):
self.create_regular_button(
self.edit_frame, Images.get("run"), self.click_run_button, "run"
)
self.exec_radio_value.set(1)

View file

@ -2,23 +2,25 @@ import enum
import logging
import tkinter as tk
from coretk.images import Images
class GraphMode(enum.Enum):
SELECT = 0
EDGE = 1
NODE = 2
PICKNODE = 2
NODE = 3
OTHER = 4
class CanvasGraph(tk.Canvas):
def __init__(self, master=None, cnf=None, **kwargs):
def __init__(self, grpc=None, master=None, cnf=None, **kwargs):
if cnf is None:
cnf = {}
kwargs["highlightthickness"] = 0
super().__init__(master, cnf, **kwargs)
self.core_grpc = grpc
self.mode = GraphMode.SELECT
self.draw_node_image = None
self.draw_node_name = None
self.selected = None
self.node_context = None
self.nodes = {}
@ -29,6 +31,15 @@ class CanvasGraph(tk.Canvas):
self.setup_bindings()
self.draw_grid()
def set_canvas_mode(self, mode):
self.mode = mode
def set_drawing_image(self, img):
self.draw_node_image = img
def set_drawing_name(self, name):
self.draw_node_name = name
def draw_grid(self, width=1000, height=750):
"""
Create grid
@ -70,9 +81,9 @@ class CanvasGraph(tk.Canvas):
self.bind("<ButtonRelease-1>", self.click_release)
self.bind("<B1-Motion>", self.click_motion)
self.bind("<Button-3>", self.context)
self.bind("e", self.set_mode)
self.bind("s", self.set_mode)
self.bind("n", self.set_mode)
# self.bind("e", self.set_mode)
# self.bind("s", self.set_mode)
# self.bind("n", self.set_mode)
def canvas_xy(self, event):
"""
@ -124,7 +135,9 @@ class CanvasGraph(tk.Canvas):
self.handle_edge_release(event)
elif self.mode == GraphMode.NODE:
x, y = self.canvas_xy(event)
self.add_node(x, y, "switch")
self.add_node(x, y, self.draw_node_image, self.draw_node_name)
elif self.mode == GraphMode.PICKNODE:
self.mode = GraphMode.NODE
def handle_edge_release(self, event):
edge = self.drawing_edge
@ -194,25 +207,39 @@ class CanvasGraph(tk.Canvas):
logging.debug(f"node context: {selected}")
self.node_context.post(event.x_root, event.y_root)
def set_mode(self, event):
"""
Set canvas mode according to the hot key that has been pressed
# def set_mode(self, event):
# """
# Set canvas mode according to the hot key that has been pressed
#
# :param event: key event
# :return: nothing
# """
# logging.debug(f"mode event: {event}")
# if event.char == "e":
# self.mode = GraphMode.EDGE
# elif event.char == "s":
# self.mode = GraphMode.SELECT
# elif event.char == "n":
# self.mode = GraphMode.NODE
# logging.debug(f"graph mode: {self.mode}")
:param event: key event
:return: nothing
"""
logging.debug(f"mode event: {event}")
if event.char == "e":
self.mode = GraphMode.EDGE
elif event.char == "s":
self.mode = GraphMode.SELECT
elif event.char == "n":
self.mode = GraphMode.NODE
logging.debug(f"graph mode: {self.mode}")
# def add_node(self, x, y, image_name):
# image = Images.get(image_name)
# node = CanvasNode(x, y, image, self)
# self.nodes[node.id] = node
# return node
def add_node(self, x, y, image_name):
image = Images.get(image_name)
node = CanvasNode(x, y, image, self)
def add_node(self, x, y, image, node_name):
core_session_id = self.core_grpc.get_session_id()
core_node_id = self.core_grpc.add_node(int(x), int(y), node_name)
node = CanvasNode(
core_session_id=core_session_id,
core_node_id=core_node_id,
x=x,
y=y,
image=image,
canvas=self,
)
self.nodes[node.id] = node
return node
@ -250,22 +277,23 @@ class CanvasEdge:
self.canvas.coords(self.id, x1, y1, x, y)
self.canvas.lift(self.src)
self.canvas.lift(self.dst)
# self.canvas.create_line(0,0,10,10)
# print(x1,y1,x,y)
# self.canvas.create_line(x1+1, y1+1, x+1, y+1)
def delete(self):
self.canvas.delete(self.id)
class CanvasNode:
def __init__(self, x, y, image, canvas):
def __init__(self, core_session_id, core_node_id, x, y, image, canvas):
self.image = image
self.canvas = canvas
self.id = self.canvas.create_image(
x, y, anchor=tk.CENTER, image=self.image, tags="node"
)
self.name = f"Node {self.id}"
self.x_coord = x
self.y_coord = y
self.core_session_id = core_session_id
self.core_node_id = core_node_id
self.name = f"Node {self.core_node_id}"
self.text_id = self.canvas.create_text(x, y + 20, text=self.name)
self.canvas.tag_bind(self.id, "<ButtonPress-1>", self.click_press)
self.canvas.tag_bind(self.id, "<ButtonRelease-1>", self.click_release)
@ -274,16 +302,29 @@ class CanvasNode:
self.edges = set()
self.moving = None
def get_coords(self):
return self.x_coord, self.y_coord
def update_coords(self):
self.x_coord, self.y_coord = self.canvas.coords(self.id)
def click_press(self, event):
logging.debug(f"click press {self.name}: {event}")
self.moving = self.canvas.canvas_xy(event)
def click_release(self, event):
logging.debug(f"click release {self.name}: {event}")
self.update_coords()
self.canvas.core_grpc.edit_node(
self.core_session_id,
self.core_node_id,
int(self.x_coord),
int(self.y_coord),
)
self.moving = None
def motion(self, event):
if self.canvas.mode == GraphMode.EDGE:
if self.canvas.mode == GraphMode.EDGE or self.canvas.mode == GraphMode.NODE:
return
x, y = self.canvas.canvas_xy(event)
moving_x, moving_y = self.moving

View file

@ -18,3 +18,31 @@ class Images:
@classmethod
def get(cls, name):
return cls.images[name]
def load_core_images(images):
images.load("core", "core-icon.png")
images.load("start", "start.gif")
images.load("switch", "lanswitch.gif")
images.load("marker", "marker.gif")
images.load("router", "router.gif")
images.load("select", "select.gif")
images.load("link", "link.gif")
images.load("hub", "hub.gif")
images.load("wlan", "wlan.gif")
images.load("rj45", "rj45.gif")
images.load("tunnel", "tunnel.gif")
images.load("oval", "oval.gif")
images.load("rectangle", "rectangle.gif")
images.load("text", "text.gif")
images.load("host", "host.gif")
images.load("pc", "pc.gif")
images.load("mdr", "mdr.gif")
images.load("prouter", "router_green.gif")
images.load("ovs", "OVS.gif")
images.load("editnode", "document-properties.gif")
images.load("run", "run.gif")
images.load("plot", "plot.gif")
images.load("twonode", "twonode.gif")
images.load("stop", "stop.gif")
images.load("observe", "observe.gif")