working on shapes and texts

This commit is contained in:
Huy Pham 2019-12-06 09:03:21 -08:00
parent 7e2ebb4a2c
commit 4a34aaa30d
5 changed files with 222 additions and 123 deletions

View file

@ -10,7 +10,7 @@ from core.api.grpc import client, core_pb2
from coretk import appconfig from coretk import appconfig
from coretk.dialogs.mobilityplayer import MobilityPlayer from coretk.dialogs.mobilityplayer import MobilityPlayer
from coretk.dialogs.sessions import SessionsDialog from coretk.dialogs.sessions import SessionsDialog
from coretk.graph.shape import Shape, ShapeData from coretk.graph.shape import AnnotationData, Shape
from coretk.interface import InterfaceManager from coretk.interface import InterfaceManager
from coretk.nodeutils import NodeDraw, NodeUtils from coretk.nodeutils import NodeDraw, NodeUtils
@ -136,6 +136,7 @@ class CoreClient:
self.custom_observers[observer.name] = observer self.custom_observers[observer.name] = observer
def handle_events(self, event): def handle_events(self, event):
print(event)
if event.HasField("link_event"): if event.HasField("link_event"):
logging.info("link event: %s", event) logging.info("link event: %s", event)
self.handle_link_event(event.link_event) self.handle_link_event(event.link_event)
@ -160,6 +161,8 @@ class CoreClient:
self.handle_node_event(event.node_event) self.handle_node_event(event.node_event)
elif event.HasField("config_event"): elif event.HasField("config_event"):
logging.info("config event: %s", event) logging.info("config event: %s", event)
elif event.HasField("throughput_event"):
print("throughput")
else: else:
logging.info("unhandled event: %s", event) logging.info("unhandled event: %s", event)
@ -189,7 +192,7 @@ class CoreClient:
interface_throughputs = event.interface_throughputs interface_throughputs = event.interface_throughputs
for i in interface_throughputs: for i in interface_throughputs:
print("") print("")
return # return
throughputs_belong_to_session = [] throughputs_belong_to_session = []
for if_tp in interface_throughputs: for if_tp in interface_throughputs:
if if_tp.node_id in self.node_ids: if if_tp.node_id in self.node_ids:
@ -312,8 +315,7 @@ class CoreClient:
config_type = annotation_config["type"] config_type = annotation_config["type"]
if config_type in ["rectangle", "oval"]: if config_type in ["rectangle", "oval"]:
coords = tuple(annotation_config["iconcoords"]) coords = tuple(annotation_config["iconcoords"])
data = ShapeData( data = AnnotationData(
False,
annotation_config["label"], annotation_config["label"],
annotation_config["fontfamily"], annotation_config["fontfamily"],
annotation_config["fontsize"], annotation_config["fontsize"],

View file

@ -5,6 +5,7 @@ import tkinter as tk
from tkinter import colorchooser, font, ttk from tkinter import colorchooser, font, ttk
from coretk.dialogs.dialog import Dialog from coretk.dialogs.dialog import Dialog
from coretk.images import ImageEnum
FONT_SIZES = [8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72] FONT_SIZES = [8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72]
BORDER_WIDTH = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] BORDER_WIDTH = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
@ -12,9 +13,17 @@ BORDER_WIDTH = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
class ShapeDialog(Dialog): class ShapeDialog(Dialog):
def __init__(self, master, app, shape): def __init__(self, master, app, shape):
super().__init__(master, app, "Add a new shape", modal=True) self.annotation_type = app.canvas.annotation_type
self.canvas = app.canvas self.canvas = app.canvas
if self.is_shape():
super().__init__(master, app, "Add a new shape", modal=True)
self.id = shape.id self.id = shape.id
self.fill = None
self.border = None
else:
super().__init__(master, app, "Add a new text", modal=True)
self.shape = shape
data = shape.shape_data data = shape.shape_data
self.shape_text = tk.StringVar(value=data.text) self.shape_text = tk.StringVar(value=data.text)
self.font = tk.StringVar(value=data.font) self.font = tk.StringVar(value=data.font)
@ -26,11 +35,18 @@ class ShapeDialog(Dialog):
self.bold = tk.IntVar(value=data.bold) self.bold = tk.IntVar(value=data.bold)
self.italic = tk.IntVar(value=data.italic) self.italic = tk.IntVar(value=data.italic)
self.underline = tk.IntVar(value=data.underline) self.underline = tk.IntVar(value=data.underline)
self.fill = None
self.border = None
self.top.columnconfigure(0, weight=1) self.top.columnconfigure(0, weight=1)
self.draw() self.draw()
def is_shape(self):
return (
self.annotation_type == ImageEnum.OVAL
or self.annotation_type == ImageEnum.RECTANGLE
)
def is_text(self):
return self.annotation_type == ImageEnum.TEXT
def draw(self): def draw(self):
frame = ttk.Frame(self.top) frame = ttk.Frame(self.top)
frame.columnconfigure(0, weight=1) frame.columnconfigure(0, weight=1)
@ -69,13 +85,16 @@ class ShapeDialog(Dialog):
button.grid(row=0, column=2) button.grid(row=0, column=2)
frame.grid(row=2, column=0, sticky="nsew", padx=3, pady=3) frame.grid(row=2, column=0, sticky="nsew", padx=3, pady=3)
if self.is_shape():
frame = ttk.Frame(self.top) frame = ttk.Frame(self.top)
frame.columnconfigure(0, weight=1) frame.columnconfigure(0, weight=1)
frame.columnconfigure(1, weight=1) frame.columnconfigure(1, weight=1)
frame.columnconfigure(2, weight=1) frame.columnconfigure(2, weight=1)
label = ttk.Label(frame, text="Fill color") label = ttk.Label(frame, text="Fill color")
label.grid(row=0, column=0, sticky="nsew") label.grid(row=0, column=0, sticky="nsew")
self.fill = ttk.Label(frame, text=self.fill_color, background=self.fill_color) self.fill = ttk.Label(
frame, text=self.fill_color, background=self.fill_color
)
self.fill.grid(row=0, column=1, sticky="nsew", padx=3) self.fill.grid(row=0, column=1, sticky="nsew", padx=3)
button = ttk.Button(frame, text="Color", command=self.choose_fill_color) button = ttk.Button(frame, text="Color", command=self.choose_fill_color)
button.grid(row=0, column=2, sticky="nsew") button.grid(row=0, column=2, sticky="nsew")
@ -101,7 +120,10 @@ class ShapeDialog(Dialog):
label = ttk.Label(frame, text="Border width:") label = ttk.Label(frame, text="Border width:")
label.grid(row=0, column=0, sticky="nsew") label.grid(row=0, column=0, sticky="nsew")
combobox = ttk.Combobox( combobox = ttk.Combobox(
frame, textvariable=self.border_width, values=BORDER_WIDTH, state="readonly" frame,
textvariable=self.border_width,
values=BORDER_WIDTH,
state="readonly",
) )
combobox.grid(row=0, column=1, sticky="nsew") combobox.grid(row=0, column=1, sticky="nsew")
frame.grid(row=5, column=0, sticky="nsew", padx=3, pady=3) frame.grid(row=5, column=0, sticky="nsew", padx=3, pady=3)
@ -109,7 +131,7 @@ class ShapeDialog(Dialog):
frame = ttk.Frame(self.top) frame = ttk.Frame(self.top)
frame.columnconfigure(0, weight=1) frame.columnconfigure(0, weight=1)
frame.columnconfigure(1, weight=1) frame.columnconfigure(1, weight=1)
button = ttk.Button(frame, text="Add shape", command=self.add_shape) button = ttk.Button(frame, text="Add shape", command=self.click_add)
button.grid(row=0, column=0, sticky="e", padx=3) button.grid(row=0, column=0, sticky="e", padx=3)
button = ttk.Button(frame, text="Cancel", command=self.cancel) button = ttk.Button(frame, text="Cancel", command=self.cancel)
button.grid(row=0, column=1, sticky="w", pady=3) button.grid(row=0, column=1, sticky="w", pady=3)
@ -130,11 +152,86 @@ class ShapeDialog(Dialog):
self.border.config(background=color[1], text=color[1]) self.border.config(background=color[1], text=color[1])
def cancel(self): def cancel(self):
if not self.canvas.shapes[self.id].created: if self.is_shape() and not self.canvas.shapes[self.id].created:
self.canvas.delete(self.id) self.canvas.delete(self.id)
self.canvas.shapes.pop(self.id) self.canvas.shapes.pop(self.id)
self.destroy() self.destroy()
def click_add(self):
if self.is_shape():
self.add_shape()
elif self.is_text():
self.add_text()
self.destroy()
def make_font(self):
"""
create font for text or shape label
:return: list(font specifications)
"""
size = int(self.font_size.get())
text_font = [self.font.get(), size]
if self.bold.get() == 1:
text_font.append("bold")
if self.italic.get() == 1:
text_font.append("italic")
if self.underline.get() == 1:
text_font.append("underline")
return text_font
def save_text(self):
"""
save info related to text or shape label
:return: nothing
"""
data = self.shape.shape_data
data.text = self.shape_text.get()
data.font = self.font.get()
data.font_size = int(self.font_size.get())
data.text_color = self.text_color
data.bold = self.bold.get()
data.italic = self.italic.get()
data.underline = self.underline.get()
def save_shape(self):
"""
save info related to shape
:return: nothing
"""
data = self.shape.shape_data
data.fill_color = self.fill_color
data.border_color = self.border_color
data.border_width = int(self.border_width.get())
def add_text(self):
"""
add text to canvas
:return: nothing
"""
text = self.shape_text.get()
x = self.shape.x0
y = self.shape.y0
text_font = self.make_font()
if self.shape.text_id is None:
tid = self.canvas.create_text(
x, y, text=text, fill=self.text_color, font=text_font, tags="text"
)
self.shape.text_id = tid
self.id = tid
self.shape.id = tid
self.canvas.texts[tid] = self.shape
self.shape.created = True
self.save_text()
print(self.canvas.texts)
# self.canvas.shapes[self.id].created = True
# else:
# self.canvas.itemconfig(
# self.shape.text_id, text=text, fill=self.text_color, font=f
# )
def add_shape(self): def add_shape(self):
self.canvas.itemconfig( self.canvas.itemconfig(
self.id, self.id,
@ -143,42 +240,28 @@ class ShapeDialog(Dialog):
outline=self.border_color, outline=self.border_color,
width=int(self.border_width.get()), width=int(self.border_width.get()),
) )
shape = self.canvas.shapes[self.id]
shape_text = self.shape_text.get() shape_text = self.shape_text.get()
size = int(self.font_size.get()) size = int(self.font_size.get())
x0, y0, x1, y1 = self.canvas.bbox(self.id) x0, y0, x1, y1 = self.canvas.bbox(self.id)
text_y = y0 + 1.5 * size _y = y0 + 1.5 * size
text_x = (x0 + x1) / 2 _x = (x0 + x1) / 2
f = [self.font.get(), size] text_font = self.make_font()
if self.bold.get() == 1: if self.shape.text_id is None:
f.append("bold") self.shape.text_id = self.canvas.create_text(
if self.italic.get() == 1: _x,
f.append("italic") _y,
if self.underline.get() == 1:
f.append("underline")
if shape.text_id is None:
shape.text_id = self.canvas.create_text(
text_x,
text_y,
text=shape_text, text=shape_text,
fill=self.text_color, fill=self.text_color,
font=f, font=text_font,
tags="shapetext", tags="shapetext",
) )
self.canvas.shapes[self.id].created = True self.shape.created = True
else: else:
self.canvas.itemconfig( self.canvas.itemconfig(
shape.text_id, text=shape_text, fill=self.text_color, font=f self.shape.text_id,
text=shape_text,
fill=self.text_color,
font=text_font,
) )
data = self.canvas.shapes[self.id].shape_data self.save_text()
data.text = shape_text self.save_shape()
data.font = self.font.get()
data.font_size = int(self.font_size.get())
data.text_color = self.text_color
data.fill_color = self.fill_color
data.border_color = self.border_color
data.border_width = int(self.border_width.get())
data.bold = self.bold.get()
data.italic = self.italic.get()
data.underline = self.underline.get()
self.destroy()

View file

@ -0,0 +1,26 @@
"""
text dialog
"""
import tkinter as tk
from tkinter import ttk
from coretk.dialogs.dialog import Dialog
class TextDialog(Dialog):
def __init__(self, master, app):
super().__init__(master, app, "Add a new text", modal=True)
self.canvas = app.canvas
self.text = tk.StringVar(value="")
self.draw()
def draw(self):
frame = ttk.Frame(self.top)
frame.columnconfigure(0, weight=1)
frame.columnconfigure(1, weight=4)
label = ttk.Label(frame, text="Text for top of text: ")
label.grid(row=0, column=0)
entry = ttk.Entry(frame, textvariable=self.text)
entry.grid(row=0, column=1)
frame.grid(row=0, column=0, sticky="nsew")

View file

@ -34,6 +34,7 @@ class CanvasGraph(tk.Canvas):
self.nodes = {} self.nodes = {}
self.edges = {} self.edges = {}
self.shapes = {} self.shapes = {}
self.texts = {}
self.wireless_edges = {} self.wireless_edges = {}
self.drawing_edge = None self.drawing_edge = None
self.grid = None self.grid = None
@ -276,6 +277,8 @@ class CanvasGraph(tk.Canvas):
if self.shape_drawing: if self.shape_drawing:
self.shapes[self.selected].shape_complete(x, y) self.shapes[self.selected].shape_complete(x, y)
self.shape_drawing = False self.shape_drawing = False
elif self.annotation_type == ImageEnum.TEXT:
self.text.shape_complete(self.text.cursor_x, self.text.cursor_y)
else: else:
self.focus_set() self.focus_set()
self.selected = self.get_selected(event) self.selected = self.get_selected(event)
@ -424,16 +427,19 @@ class CanvasGraph(tk.Canvas):
if self.mode == GraphMode.EDGE and is_node: if self.mode == GraphMode.EDGE and is_node:
x, y = self.coords(selected) x, y = self.coords(selected)
self.drawing_edge = CanvasEdge(x, y, x, y, selected, self) self.drawing_edge = CanvasEdge(x, y, x, y, selected, self)
if (
self.mode == GraphMode.ANNOTATION if self.mode == GraphMode.ANNOTATION and selected is None:
and self.annotation_type in [ImageEnum.OVAL, ImageEnum.RECTANGLE] if self.annotation_type in [ImageEnum.OVAL, ImageEnum.RECTANGLE]:
and selected is None
):
x, y = self.canvas_xy(event) x, y = self.canvas_xy(event)
shape = Shape(self.app, self, x, y) shape = Shape(self.app, self, x, y)
self.selected = shape.id self.selected = shape.id
self.shapes[shape.id] = shape self.shapes[shape.id] = shape
self.shape_drawing = True self.shape_drawing = True
elif self.annotation_type == ImageEnum.TEXT:
x, y = self.canvas_xy(event)
self.text = Shape(self.app, self, x, y)
# self.shapes[shape.id] = shape
if self.mode == GraphMode.SELECT: if self.mode == GraphMode.SELECT:
if selected is not None: if selected is not None:
if selected in self.shapes: if selected in self.shapes:

View file

@ -1,41 +1,27 @@
""" """
class for shapes class for shapes
""" """
import logging
from coretk.dialogs.shapemod import ShapeDialog from coretk.dialogs.shapemod import ShapeDialog
from coretk.images import ImageEnum from coretk.images import ImageEnum
ABOVE_COMPONENT = ["gridline", "edge", "linkinfo", "antenna", "node", "nodename"] ABOVE_COMPONENT = ["gridline", "edge", "linkinfo", "antenna", "node", "nodename"]
class ShapeData: class AnnotationData:
def __init__( def __init__(
self, self,
is_default=True, text="",
text=None, font="Arial",
font=None, font_size=12,
font_size=None, text_color="#000000",
text_color=None, fill_color="#CFCFFF",
fill_color=None, border_color="#000000",
border_color=None, border_width=0,
border_width=None,
bold=0, bold=0,
italic=0, italic=0,
underline=0, underline=0,
): ):
if is_default:
self.text = ""
self.font = "Arial"
self.font_size = 12
self.text_color = "#000000"
self.fill_color = "#CFCFFF"
self.border_color = "#000000"
self.border_width = 0
self.bold = 0
self.italic = 0
self.underline = 0
else:
self.text = text self.text = text
self.font = font self.font = font
self.font_size = font_size self.font_size = font_size
@ -66,7 +52,7 @@ class Shape:
self.y0 = top_y self.y0 = top_y
self.created = False self.created = False
self.text_id = None self.text_id = None
self.shape_data = ShapeData() self.shape_data = AnnotationData()
canvas.delete(canvas.find_withtag("selectednodes")) canvas.delete(canvas.find_withtag("selectednodes"))
annotation_type = self.canvas.annotation_type annotation_type = self.canvas.annotation_type
if annotation_type == ImageEnum.OVAL: if annotation_type == ImageEnum.OVAL:
@ -112,7 +98,6 @@ class Shape:
self.shape_data = data self.shape_data = data
self.cursor_x = None self.cursor_x = None
self.cursor_y = None self.cursor_y = None
self.canvas.tag_bind(self.id, "<ButtonRelease-1>", self.click_release)
def shape_motion(self, x1, y1): def shape_motion(self, x1, y1):
self.canvas.coords(self.id, self.x0, self.y0, x1, y1) self.canvas.coords(self.id, self.x0, self.y0, x1, y1)
@ -123,9 +108,6 @@ class Shape:
s = ShapeDialog(self.app, self.app, self) s = ShapeDialog(self.app, self.app, self)
s.show() s.show()
def click_release(self, event):
logging.debug("Click release on shape %s", self.id)
def motion(self, event, delta_x=None, delta_y=None): def motion(self, event, delta_x=None, delta_y=None):
if event is not None: if event is not None:
delta_x = event.x - self.cursor_x delta_x = event.x - self.cursor_x