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 logging
import tkinter as tk import tkinter as tk
import coretk.images as images
from coretk.coregrpc import CoreGrpc
from coretk.coremenubar import CoreMenubar from coretk.coremenubar import CoreMenubar
from coretk.coretoolbar import CoreToolbar from coretk.coretoolbar import CoreToolbar
from coretk.graph import CanvasGraph from coretk.graph import CanvasGraph
@ -13,11 +15,16 @@ class Application(tk.Frame):
self.load_images() self.load_images()
self.setup_app() self.setup_app()
self.menubar = None self.menubar = None
self.canvas = None
self.core_grpc = CoreGrpc()
self.create_menu() self.create_menu()
self.create_widgets() self.create_widgets()
def load_images(self): 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): def setup_app(self):
self.master.title("CORE") self.master.title("CORE")
@ -40,11 +47,14 @@ class Application(tk.Frame):
core_editbar.create_toolbar() core_editbar.create_toolbar()
self.canvas = CanvasGraph( 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.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( scroll_x = tk.Scrollbar(
self.canvas, orient=tk.HORIZONTAL, command=self.canvas.xview self.canvas, orient=tk.HORIZONTAL, command=self.canvas.xview
@ -69,3 +79,4 @@ if __name__ == "__main__":
logging.basicConfig(level=logging.DEBUG) logging.basicConfig(level=logging.DEBUG)
app = Application() app = Application()
app.mainloop() 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 self.network_layer_option_menu = None
# variables used by canvas graph # 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 :return: nothing
""" """
Images.load("core", "core-icon.png") self.canvas = canvas
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
def destroy_previous_frame(self): def destroy_previous_frame(self):
""" """
@ -189,47 +149,67 @@ class CoreToolbar(object):
def click_selection_tool(self): def click_selection_tool(self):
logging.debug("Click SELECTION TOOL") logging.debug("Click SELECTION TOOL")
self.set_graph_mode(GraphMode.SELECT) self.canvas.mode = GraphMode.SELECT
def click_start_stop_session_tool(self): def click_start_stop_session_tool(self):
logging.debug("Click START STOP SESSION button") logging.debug("Click START STOP SESSION button")
self.destroy_children_widgets(self.edit_frame) self.destroy_children_widgets(self.edit_frame)
self.canvas.set_canvas_mode(GraphMode.SELECT)
self.create_runtime_toolbar() self.create_runtime_toolbar()
def click_link_tool(self): def click_link_tool(self):
logging.debug("Click LINK button") logging.debug("Click LINK button")
self.set_graph_mode(GraphMode.EDGE) self.canvas.set_canvas_mode(GraphMode.EDGE)
def pick_router(self, main_button): def pick_router(self, main_button):
logging.debug("Pick router option")
self.network_layer_option_menu.destroy() self.network_layer_option_menu.destroy()
main_button.configure(image=Images.get("router")) 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): def pick_host(self, main_button):
logging.debug("Pick host option")
self.network_layer_option_menu.destroy() self.network_layer_option_menu.destroy()
main_button.configure(image=Images.get("host")) 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): def pick_pc(self, main_button):
logging.debug("Pick PC option")
self.network_layer_option_menu.destroy() self.network_layer_option_menu.destroy()
main_button.configure(image=Images.get("pc")) 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): def pick_mdr(self, main_button):
logging.debug("Pick MDR option")
self.network_layer_option_menu.destroy() self.network_layer_option_menu.destroy()
main_button.configure(image=Images.get("mdr")) 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): def pick_prouter(self, main_button):
logging.debug("Pick prouter option")
self.network_layer_option_menu.destroy() self.network_layer_option_menu.destroy()
main_button.configure(image=Images.get("prouter")) 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): def pick_ovs(self, main_button):
logging.debug("Pick OVS option")
self.network_layer_option_menu.destroy() self.network_layer_option_menu.destroy()
main_button.configure(image=Images.get("ovs")) 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): def pick_editnode(self, main_button):
self.network_layer_option_menu.destroy() self.network_layer_option_menu.destroy()
main_button.configure(image=Images.get("editnode")) main_button.configure(image=Images.get("editnode"))
@ -311,29 +291,43 @@ class CoreToolbar(object):
CreateToolTip(network_layer_button, "Network-layer virtual nodes") CreateToolTip(network_layer_button, "Network-layer virtual nodes")
def pick_hub(self, main_button): def pick_hub(self, main_button):
logging.debug("Pick link-layer node HUB")
self.link_layer_option_menu.destroy() self.link_layer_option_menu.destroy()
main_button.configure(image=Images.get("hub")) 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): def pick_switch(self, main_button):
logging.debug("Pick link-layer node SWITCH")
self.link_layer_option_menu.destroy() self.link_layer_option_menu.destroy()
main_button.configure(image=Images.get("switch")) 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): def pick_wlan(self, main_button):
logging.debug("Pick link-layer node WLAN")
self.link_layer_option_menu.destroy() self.link_layer_option_menu.destroy()
main_button.configure(image=Images.get("wlan")) 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): def pick_rj45(self, main_button):
logging.debug("Pick link-layer node RJ45")
self.link_layer_option_menu.destroy() self.link_layer_option_menu.destroy()
main_button.configure(image=Images.get("rj45")) 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): def pick_tunnel(self, main_button):
logging.debug("Pick link-layer node TUNNEL")
self.link_layer_option_menu.destroy() self.link_layer_option_menu.destroy()
main_button.configure(image=Images.get("tunnel")) 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): def draw_link_layer_options(self, link_layer_button):
""" """
@ -482,7 +476,7 @@ class CoreToolbar(object):
CreateToolTip(marker_main_button, "background annotation tools") CreateToolTip(marker_main_button, "background annotation tools")
def create_toolbar(self): def create_toolbar(self):
self.load_toolbar_images() # self.load_toolbar_images()
self.create_regular_button( self.create_regular_button(
self.edit_frame, self.edit_frame,
Images.get("start"), Images.get("start"),
@ -508,6 +502,7 @@ class CoreToolbar(object):
self.create_network_layer_button() self.create_network_layer_button()
self.create_link_layer_button() self.create_link_layer_button()
self.create_marker_button() self.create_marker_button()
self.radio_value.set(1)
def create_observe_button(self): def create_observe_button(self):
menu_button = tk.Menubutton( menu_button = tk.Menubutton(
@ -599,3 +594,4 @@ class CoreToolbar(object):
self.create_regular_button( self.create_regular_button(
self.edit_frame, Images.get("run"), self.click_run_button, "run" 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 logging
import tkinter as tk import tkinter as tk
from coretk.images import Images
class GraphMode(enum.Enum): class GraphMode(enum.Enum):
SELECT = 0 SELECT = 0
EDGE = 1 EDGE = 1
NODE = 2 PICKNODE = 2
NODE = 3
OTHER = 4
class CanvasGraph(tk.Canvas): 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: if cnf is None:
cnf = {} cnf = {}
kwargs["highlightthickness"] = 0 kwargs["highlightthickness"] = 0
super().__init__(master, cnf, **kwargs) super().__init__(master, cnf, **kwargs)
self.core_grpc = grpc
self.mode = GraphMode.SELECT self.mode = GraphMode.SELECT
self.draw_node_image = None
self.draw_node_name = None
self.selected = None self.selected = None
self.node_context = None self.node_context = None
self.nodes = {} self.nodes = {}
@ -29,6 +31,15 @@ class CanvasGraph(tk.Canvas):
self.setup_bindings() self.setup_bindings()
self.draw_grid() 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): def draw_grid(self, width=1000, height=750):
""" """
Create grid Create grid
@ -70,9 +81,9 @@ class CanvasGraph(tk.Canvas):
self.bind("<ButtonRelease-1>", self.click_release) self.bind("<ButtonRelease-1>", self.click_release)
self.bind("<B1-Motion>", self.click_motion) self.bind("<B1-Motion>", self.click_motion)
self.bind("<Button-3>", self.context) self.bind("<Button-3>", self.context)
self.bind("e", self.set_mode) # self.bind("e", self.set_mode)
self.bind("s", self.set_mode) # self.bind("s", self.set_mode)
self.bind("n", self.set_mode) # self.bind("n", self.set_mode)
def canvas_xy(self, event): def canvas_xy(self, event):
""" """
@ -124,7 +135,9 @@ class CanvasGraph(tk.Canvas):
self.handle_edge_release(event) self.handle_edge_release(event)
elif self.mode == GraphMode.NODE: elif self.mode == GraphMode.NODE:
x, y = self.canvas_xy(event) 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): def handle_edge_release(self, event):
edge = self.drawing_edge edge = self.drawing_edge
@ -194,25 +207,39 @@ class CanvasGraph(tk.Canvas):
logging.debug(f"node context: {selected}") logging.debug(f"node context: {selected}")
self.node_context.post(event.x_root, event.y_root) self.node_context.post(event.x_root, event.y_root)
def set_mode(self, event): # def set_mode(self, event):
""" # """
Set canvas mode according to the hot key that has been pressed # 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 # def add_node(self, x, y, image_name):
:return: nothing # image = Images.get(image_name)
""" # node = CanvasNode(x, y, image, self)
logging.debug(f"mode event: {event}") # self.nodes[node.id] = node
if event.char == "e": # return node
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): def add_node(self, x, y, image, node_name):
image = Images.get(image_name) core_session_id = self.core_grpc.get_session_id()
node = CanvasNode(x, y, image, self) 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 self.nodes[node.id] = node
return node return node
@ -250,22 +277,23 @@ class CanvasEdge:
self.canvas.coords(self.id, x1, y1, x, y) self.canvas.coords(self.id, x1, y1, x, y)
self.canvas.lift(self.src) self.canvas.lift(self.src)
self.canvas.lift(self.dst) 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): def delete(self):
self.canvas.delete(self.id) self.canvas.delete(self.id)
class CanvasNode: 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.image = image
self.canvas = canvas self.canvas = canvas
self.id = self.canvas.create_image( self.id = self.canvas.create_image(
x, y, anchor=tk.CENTER, image=self.image, tags="node" 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.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, "<ButtonPress-1>", self.click_press)
self.canvas.tag_bind(self.id, "<ButtonRelease-1>", self.click_release) self.canvas.tag_bind(self.id, "<ButtonRelease-1>", self.click_release)
@ -274,16 +302,29 @@ class CanvasNode:
self.edges = set() self.edges = set()
self.moving = None 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): def click_press(self, event):
logging.debug(f"click press {self.name}: {event}") logging.debug(f"click press {self.name}: {event}")
self.moving = self.canvas.canvas_xy(event) self.moving = self.canvas.canvas_xy(event)
def click_release(self, event): def click_release(self, event):
logging.debug(f"click release {self.name}: {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 self.moving = None
def motion(self, event): def motion(self, event):
if self.canvas.mode == GraphMode.EDGE: if self.canvas.mode == GraphMode.EDGE or self.canvas.mode == GraphMode.NODE:
return return
x, y = self.canvas.canvas_xy(event) x, y = self.canvas.canvas_xy(event)
moving_x, moving_y = self.moving moving_x, moving_y = self.moving

View file

@ -18,3 +18,31 @@ class Images:
@classmethod @classmethod
def get(cls, name): def get(cls, name):
return cls.images[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")