create grids
This commit is contained in:
parent
130c2a9b8d
commit
269d7f8f92
3 changed files with 162 additions and 13 deletions
|
@ -21,7 +21,7 @@ class Application(tk.Frame):
|
|||
|
||||
def setup_app(self):
|
||||
self.master.title("CORE")
|
||||
self.master.geometry("800x600")
|
||||
self.master.geometry("1000x800")
|
||||
image = Images.get("core")
|
||||
self.master.tk.call("wm", "iconphoto", self.master._w, image)
|
||||
self.pack(fill=tk.BOTH, expand=True)
|
||||
|
@ -40,11 +40,11 @@ class Application(tk.Frame):
|
|||
core_editbar.create_toolbar()
|
||||
|
||||
self.canvas = CanvasGraph(
|
||||
self, background="#cccccc", scrollregion=(0, 0, 1000, 1000)
|
||||
master=self, background="#cccccc", scrollregion=(0, 0, 1000, 1000)
|
||||
)
|
||||
self.canvas.pack(fill=tk.BOTH, expand=True)
|
||||
|
||||
# self.canvas.create_line(0, 0, 10, 10)
|
||||
# self.canvas.create_rectangle(0, 0, 1000, 750, outline="#000000", fill="#ffffff", width=1)
|
||||
|
||||
scroll_x = tk.Scrollbar(
|
||||
self.canvas, orient=tk.HORIZONTAL, command=self.canvas.xview
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import logging
|
||||
import tkinter as tk
|
||||
|
||||
from coretk.graph import GraphMode
|
||||
from coretk.images import Images
|
||||
from coretk.tooltip import CreateToolTip
|
||||
|
||||
|
@ -34,6 +35,9 @@ class CoreToolbar(object):
|
|||
self.marker_option_menu = None
|
||||
self.network_layer_option_menu = None
|
||||
|
||||
# variables used by canvas graph
|
||||
self.mode = GraphMode.SELECT
|
||||
|
||||
def load_toolbar_images(self):
|
||||
"""
|
||||
Load the images that appear in core toolbar
|
||||
|
@ -66,6 +70,24 @@ class CoreToolbar(object):
|
|||
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):
|
||||
"""
|
||||
Destroy any extra frame from previous before drawing a new one
|
||||
|
@ -94,7 +116,7 @@ class CoreToolbar(object):
|
|||
if i.winfo_name() != "!frame":
|
||||
i.destroy()
|
||||
|
||||
def create_button(self, img, func, frame, main_button):
|
||||
def create_button(self, img, func, frame, main_button, btt_message):
|
||||
"""
|
||||
Create button and put it on the frame
|
||||
|
||||
|
@ -106,6 +128,7 @@ class CoreToolbar(object):
|
|||
"""
|
||||
button = tk.Button(frame, width=self.width, height=self.height, image=img)
|
||||
button.pack(side=tk.LEFT, pady=1)
|
||||
CreateToolTip(button, btt_message)
|
||||
button.bind("<Button-1>", lambda mb: func(main_button))
|
||||
|
||||
def create_radio_button(self, frame, image, func, variable, value, tooltip_msg):
|
||||
|
@ -122,11 +145,12 @@ class CoreToolbar(object):
|
|||
button.pack(side=tk.TOP, pady=1)
|
||||
CreateToolTip(button, tooltip_msg)
|
||||
|
||||
def create_regular_button(self, frame, image, func):
|
||||
def create_regular_button(self, frame, image, func, btt_message):
|
||||
button = tk.Button(
|
||||
frame, width=self.width, height=self.height, image=image, command=func
|
||||
)
|
||||
button.pack(side=tk.TOP, pady=1)
|
||||
CreateToolTip(button, btt_message)
|
||||
|
||||
def draw_button_menu_frame(self, edit_frame, option_frame, main_button):
|
||||
"""
|
||||
|
@ -165,6 +189,7 @@ class CoreToolbar(object):
|
|||
|
||||
def click_selection_tool(self):
|
||||
logging.debug("Click SELECTION TOOL")
|
||||
self.set_graph_mode(GraphMode.SELECT)
|
||||
|
||||
def click_start_stop_session_tool(self):
|
||||
logging.debug("Click START STOP SESSION button")
|
||||
|
@ -173,6 +198,7 @@ class CoreToolbar(object):
|
|||
|
||||
def click_link_tool(self):
|
||||
logging.debug("Click LINK button")
|
||||
self.set_graph_mode(GraphMode.EDGE)
|
||||
|
||||
def pick_router(self, main_button):
|
||||
self.network_layer_option_menu.destroy()
|
||||
|
@ -237,9 +263,22 @@ class CoreToolbar(object):
|
|||
self.pick_ovs,
|
||||
self.pick_editnode,
|
||||
]
|
||||
tooltip_list = [
|
||||
"router",
|
||||
"host",
|
||||
"PC",
|
||||
"mdr",
|
||||
"prouter",
|
||||
"OVS",
|
||||
"edit node types",
|
||||
]
|
||||
for i in range(len(img_list)):
|
||||
self.create_button(
|
||||
img_list[i], func_list[i], option_frame, network_layer_button
|
||||
img_list[i],
|
||||
func_list[i],
|
||||
option_frame,
|
||||
network_layer_button,
|
||||
tooltip_list[i],
|
||||
)
|
||||
|
||||
# place frame at a calculated position as well as keep a reference of that frame
|
||||
|
@ -320,9 +359,20 @@ class CoreToolbar(object):
|
|||
self.pick_rj45,
|
||||
self.pick_tunnel,
|
||||
]
|
||||
tooltip_list = [
|
||||
"ethernet hub",
|
||||
"ethernet switch",
|
||||
"wireless LAN",
|
||||
"rj45 physical interface tool",
|
||||
"tunnel tool",
|
||||
]
|
||||
for i in range(len(img_list)):
|
||||
self.create_button(
|
||||
img_list[i], func_list[i], option_frame, link_layer_button
|
||||
img_list[i],
|
||||
func_list[i],
|
||||
option_frame,
|
||||
link_layer_button,
|
||||
tooltip_list[i],
|
||||
)
|
||||
|
||||
# place frame at a calculated position as well as keep a reference of the frame
|
||||
|
@ -358,7 +408,6 @@ class CoreToolbar(object):
|
|||
self.marker_option_menu.destroy()
|
||||
main_button.configure(image=Images.get("marker"))
|
||||
logging.debug("Pick MARKER")
|
||||
return "break"
|
||||
|
||||
def pick_oval(self, main_button):
|
||||
self.marker_option_menu.destroy()
|
||||
|
@ -397,8 +446,11 @@ class CoreToolbar(object):
|
|||
self.pick_rectangle,
|
||||
self.pick_text,
|
||||
]
|
||||
tooltip_list = ["marker", "oval", "rectangle", "text"]
|
||||
for i in range(len(img_list)):
|
||||
self.create_button(img_list[i], func_list[i], option_frame, main_button)
|
||||
self.create_button(
|
||||
img_list[i], func_list[i], option_frame, main_button, tooltip_list[i]
|
||||
)
|
||||
|
||||
# place the frame at a calculated position as well as keep a reference of that frame
|
||||
self.draw_button_menu_frame(self.edit_frame, option_frame, main_button)
|
||||
|
@ -432,7 +484,10 @@ class CoreToolbar(object):
|
|||
def create_toolbar(self):
|
||||
self.load_toolbar_images()
|
||||
self.create_regular_button(
|
||||
self.edit_frame, Images.get("start"), self.click_start_stop_session_tool
|
||||
self.edit_frame,
|
||||
Images.get("start"),
|
||||
self.click_start_stop_session_tool,
|
||||
"start the session",
|
||||
)
|
||||
self.create_radio_button(
|
||||
self.edit_frame,
|
||||
|
@ -503,7 +558,10 @@ class CoreToolbar(object):
|
|||
|
||||
def create_runtime_toolbar(self):
|
||||
self.create_regular_button(
|
||||
self.edit_frame, Images.get("stop"), self.click_stop_button
|
||||
self.edit_frame,
|
||||
Images.get("stop"),
|
||||
self.click_stop_button,
|
||||
"stop the session",
|
||||
)
|
||||
self.create_radio_button(
|
||||
self.edit_frame,
|
||||
|
@ -539,5 +597,5 @@ class CoreToolbar(object):
|
|||
"run command from one node to another",
|
||||
)
|
||||
self.create_regular_button(
|
||||
self.edit_frame, Images.get("run"), self.click_run_button
|
||||
self.edit_frame, Images.get("run"), self.click_run_button, "run"
|
||||
)
|
||||
|
|
|
@ -17,14 +17,42 @@ class CanvasGraph(tk.Canvas):
|
|||
cnf = {}
|
||||
kwargs["highlightthickness"] = 0
|
||||
super().__init__(master, cnf, **kwargs)
|
||||
|
||||
self.mode = GraphMode.SELECT
|
||||
self.selected = None
|
||||
self.node_context = None
|
||||
self.nodes = {}
|
||||
self.edges = {}
|
||||
self.drawing_edge = None
|
||||
|
||||
self.setup_menus()
|
||||
self.setup_bindings()
|
||||
self.draw_grid()
|
||||
|
||||
def draw_grid(self, width=1000, height=750):
|
||||
"""
|
||||
Create grid
|
||||
|
||||
:param int width: the width
|
||||
:param int height: the height
|
||||
|
||||
:return: nothing
|
||||
"""
|
||||
rectangle_id = self.create_rectangle(
|
||||
0,
|
||||
0,
|
||||
width,
|
||||
height,
|
||||
outline="#000000",
|
||||
fill="#ffffff",
|
||||
width=1,
|
||||
tags="rectangle",
|
||||
)
|
||||
self.tag_lower(rectangle_id)
|
||||
for i in range(0, width, 27):
|
||||
self.create_line(i, 0, i, height, dash=(2, 4), tags="grid line")
|
||||
for i in range(0, height, 27):
|
||||
self.create_line(0, i, width, i, dash=(2, 4), tags="grid line")
|
||||
|
||||
def setup_menus(self):
|
||||
self.node_context = tk.Menu(self.master)
|
||||
|
@ -33,6 +61,11 @@ class CanvasGraph(tk.Canvas):
|
|||
self.node_context.add_command(label="Three")
|
||||
|
||||
def setup_bindings(self):
|
||||
"""
|
||||
Bind any mouse events or hot keys to the matching action
|
||||
|
||||
:return: nothing
|
||||
"""
|
||||
self.bind("<ButtonPress-1>", self.click_press)
|
||||
self.bind("<ButtonRelease-1>", self.click_release)
|
||||
self.bind("<B1-Motion>", self.click_motion)
|
||||
|
@ -42,11 +75,25 @@ class CanvasGraph(tk.Canvas):
|
|||
self.bind("n", self.set_mode)
|
||||
|
||||
def canvas_xy(self, event):
|
||||
"""
|
||||
Convert window coordinate to canvas coordinate
|
||||
|
||||
:param event:
|
||||
:rtype: (int, int)
|
||||
:return: x, y canvas coordinate
|
||||
"""
|
||||
x = self.canvasx(event.x)
|
||||
y = self.canvasy(event.y)
|
||||
return x, y
|
||||
|
||||
def get_selected(self, event):
|
||||
"""
|
||||
Retrieve the item id that is on the mouse position
|
||||
|
||||
:param event: mouse event
|
||||
:rtype: int
|
||||
:return: the item that the mouse point to
|
||||
"""
|
||||
overlapping = self.find_overlapping(event.x, event.y, event.x, event.y)
|
||||
nodes = set(self.find_withtag("node"))
|
||||
selected = None
|
||||
|
@ -64,6 +111,12 @@ class CanvasGraph(tk.Canvas):
|
|||
return selected
|
||||
|
||||
def click_release(self, event):
|
||||
"""
|
||||
Draw a node or finish drawing an edge according to the current graph mode
|
||||
|
||||
:param event: mouse event
|
||||
:return: nothing
|
||||
"""
|
||||
self.focus_set()
|
||||
self.selected = self.get_selected(event)
|
||||
logging.debug(f"click release selected: {self.selected}")
|
||||
|
@ -109,6 +162,12 @@ class CanvasGraph(tk.Canvas):
|
|||
logging.debug(f"edges: {self.find_withtag('edge')}")
|
||||
|
||||
def click_press(self, event):
|
||||
"""
|
||||
Start drawing an edge if mouse click is on a node
|
||||
|
||||
:param event: mouse event
|
||||
:return: nothing
|
||||
"""
|
||||
logging.debug(f"click press: {event}")
|
||||
selected = self.get_selected(event)
|
||||
is_node = selected in self.find_withtag("node")
|
||||
|
@ -117,6 +176,12 @@ class CanvasGraph(tk.Canvas):
|
|||
self.drawing_edge = CanvasEdge(x, y, x, y, selected, self)
|
||||
|
||||
def click_motion(self, event):
|
||||
"""
|
||||
Redraw drawing edge according to the current position of the mouse
|
||||
|
||||
:param event: mouse event
|
||||
:return: nothing
|
||||
"""
|
||||
if self.mode == GraphMode.EDGE and self.drawing_edge is not None:
|
||||
x2, y2 = self.canvas_xy(event)
|
||||
x1, y1, _, _ = self.coords(self.drawing_edge.id)
|
||||
|
@ -130,6 +195,12 @@ class CanvasGraph(tk.Canvas):
|
|||
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
|
||||
|
||||
:param event: key event
|
||||
:return: nothing
|
||||
"""
|
||||
logging.debug(f"mode event: {event}")
|
||||
if event.char == "e":
|
||||
self.mode = GraphMode.EDGE
|
||||
|
@ -147,21 +218,41 @@ class CanvasGraph(tk.Canvas):
|
|||
|
||||
|
||||
class CanvasEdge:
|
||||
"""
|
||||
Canvas edge class
|
||||
"""
|
||||
|
||||
width = 3
|
||||
|
||||
def __init__(self, x1, y1, x2, y2, src, canvas):
|
||||
"""
|
||||
Create an instance of canvas edge object
|
||||
:param int x1: source x-coord
|
||||
:param int y1: source y-coord
|
||||
:param int x2: destination x-coord
|
||||
:param int y2: destination y-coord
|
||||
:param int src: source id
|
||||
:param tkinter.Canvas canvas: canvas object
|
||||
"""
|
||||
self.src = src
|
||||
self.dst = None
|
||||
self.canvas = canvas
|
||||
self.id = self.canvas.create_line(x1, y1, x2, y2, tags="edge", width=self.width)
|
||||
self.token = None
|
||||
self.canvas.tag_lower(self.id)
|
||||
|
||||
# TODO resolve this
|
||||
# self.canvas.tag_lower(self.id)
|
||||
|
||||
def complete(self, dst, x, y):
|
||||
self.dst = dst
|
||||
self.token = tuple(sorted((self.src, self.dst)))
|
||||
x1, y1, _, _ = self.canvas.coords(self.id)
|
||||
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)
|
||||
|
|
Loading…
Add table
Reference in a new issue