cleanup for shapes and creating shapes and storing and restoring shapes from metadata
This commit is contained in:
parent
c238b5dfc8
commit
742eb2bed6
7 changed files with 190 additions and 137 deletions
|
@ -5,12 +5,14 @@ import json
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
from core.api.grpc import client, core_pb2
|
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 AnnotationData, Shape
|
from coretk.graph.shape import AnnotationData, Shape
|
||||||
|
from coretk.graph.shapeutils import ShapeType
|
||||||
from coretk.interface import InterfaceManager
|
from coretk.interface import InterfaceManager
|
||||||
from coretk.nodeutils import NodeDraw, NodeUtils
|
from coretk.nodeutils import NodeDraw, NodeUtils
|
||||||
|
|
||||||
|
@ -136,7 +138,6 @@ 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)
|
||||||
|
@ -162,7 +163,7 @@ class CoreClient:
|
||||||
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"):
|
elif event.HasField("throughput_event"):
|
||||||
print("throughput")
|
logging.info("throughput event: %s", event)
|
||||||
else:
|
else:
|
||||||
logging.info("unhandled event: %s", event)
|
logging.info("unhandled event: %s", event)
|
||||||
|
|
||||||
|
@ -301,35 +302,42 @@ class CoreClient:
|
||||||
def parse_metadata(self, config):
|
def parse_metadata(self, config):
|
||||||
# canvas setting
|
# canvas setting
|
||||||
canvas_config = config.get("canvas")
|
canvas_config = config.get("canvas")
|
||||||
|
logging.info("canvas metadata: %s", canvas_config)
|
||||||
if canvas_config:
|
if canvas_config:
|
||||||
logging.info("canvas metadata: %s", canvas_config)
|
|
||||||
canvas_config = json.loads(canvas_config)
|
canvas_config = json.loads(canvas_config)
|
||||||
wallpaper_style = canvas_config["wallpaper-style"]
|
wallpaper_style = canvas_config["wallpaper-style"]
|
||||||
self.app.canvas.scale_option.set(wallpaper_style)
|
self.app.canvas.scale_option.set(wallpaper_style)
|
||||||
wallpaper = canvas_config["wallpaper"]
|
wallpaper = canvas_config["wallpaper"]
|
||||||
wallpaper = str(appconfig.BACKGROUNDS_PATH.joinpath(wallpaper))
|
if wallpaper:
|
||||||
self.app.canvas.set_wallpaper(wallpaper)
|
wallpaper = str(appconfig.BACKGROUNDS_PATH.joinpath(wallpaper))
|
||||||
for key, annotation_config in config.items():
|
self.app.canvas.set_wallpaper(wallpaper)
|
||||||
if "annotation" in key:
|
|
||||||
annotation_config = json.loads(annotation_config)
|
# load saved shapes
|
||||||
config_type = annotation_config["type"]
|
shapes_config = config.get("shapes")
|
||||||
if config_type in ["rectangle", "oval"]:
|
if shapes_config:
|
||||||
coords = tuple(annotation_config["iconcoords"])
|
shapes_config = json.loads(shapes_config)
|
||||||
|
for shape_config in shapes_config:
|
||||||
|
logging.info("loading shape: %s", shapes_config)
|
||||||
|
shape_type = shape_config["type"]
|
||||||
|
try:
|
||||||
|
shape_type = ShapeType(shape_type)
|
||||||
|
x1, y1, x2, y2 = shape_config["iconcoords"]
|
||||||
data = AnnotationData(
|
data = AnnotationData(
|
||||||
annotation_config["label"],
|
shape_config["label"],
|
||||||
annotation_config["fontfamily"],
|
shape_config["fontfamily"],
|
||||||
annotation_config["fontsize"],
|
shape_config["fontsize"],
|
||||||
annotation_config["labelcolor"],
|
shape_config["labelcolor"],
|
||||||
annotation_config["color"],
|
shape_config["color"],
|
||||||
annotation_config["border"],
|
shape_config["border"],
|
||||||
annotation_config["width"],
|
shape_config["width"],
|
||||||
)
|
)
|
||||||
shape = Shape(
|
shape = Shape(
|
||||||
self.app, self.app.canvas, None, None, coords, data, config_type
|
self.app, self.app.canvas, shape_type, x1, y1, x2, y2, data
|
||||||
)
|
)
|
||||||
self.app.canvas.shapes[shape.id] = shape
|
self.app.canvas.shapes[shape.id] = shape
|
||||||
else:
|
except ValueError:
|
||||||
logging.debug("not implemented")
|
logging.debug("unknown shape: %s", shape_type)
|
||||||
|
|
||||||
for tag in LIFT_ORDER:
|
for tag in LIFT_ORDER:
|
||||||
self.app.canvas.tag_raise(tag)
|
self.app.canvas.tag_raise(tag)
|
||||||
|
|
||||||
|
@ -427,6 +435,7 @@ class CoreClient:
|
||||||
service_configs,
|
service_configs,
|
||||||
file_configs,
|
file_configs,
|
||||||
)
|
)
|
||||||
|
self.set_metadata()
|
||||||
process_time = time.perf_counter() - start
|
process_time = time.perf_counter() - start
|
||||||
logging.debug("start session(%s), result: %s", self.session_id, response.result)
|
logging.debug("start session(%s), result: %s", self.session_id, response.result)
|
||||||
self.app.statusbar.start_session_callback(process_time)
|
self.app.statusbar.start_session_callback(process_time)
|
||||||
|
@ -447,6 +456,24 @@ class CoreClient:
|
||||||
self.app.statusbar.stop_session_callback(process_time)
|
self.app.statusbar.stop_session_callback(process_time)
|
||||||
logging.debug("stopped session(%s), result: %s", session_id, response.result)
|
logging.debug("stopped session(%s), result: %s", session_id, response.result)
|
||||||
|
|
||||||
|
def set_metadata(self):
|
||||||
|
# create canvas data
|
||||||
|
canvas_config = {
|
||||||
|
"wallpaper": Path(self.app.canvas.wallpaper_file).name,
|
||||||
|
"wallpaper-style": self.app.canvas.scale_option.get(),
|
||||||
|
}
|
||||||
|
canvas_config = json.dumps(canvas_config)
|
||||||
|
|
||||||
|
# create shapes data
|
||||||
|
shapes = []
|
||||||
|
for shape in self.app.canvas.shapes.values():
|
||||||
|
shapes.append(shape.metadata())
|
||||||
|
shapes = json.dumps(shapes)
|
||||||
|
|
||||||
|
metadata = {"canvas": canvas_config, "shapes": shapes}
|
||||||
|
response = self.client.set_session_metadata(self.session_id, metadata)
|
||||||
|
logging.info("set session metadata: %s", response)
|
||||||
|
|
||||||
def launch_terminal(self, node_id):
|
def launch_terminal(self, node_id):
|
||||||
response = self.client.get_node_terminal(self.session_id, node_id)
|
response = self.client.get_node_terminal(self.session_id, node_id)
|
||||||
logging.info("get terminal %s", response.terminal)
|
logging.info("get terminal %s", response.terminal)
|
||||||
|
|
|
@ -5,7 +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
|
from coretk.graph.shapeutils import is_draw_shape, is_shape_text
|
||||||
|
|
||||||
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]
|
||||||
|
@ -13,40 +13,34 @@ 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):
|
||||||
self.annotation_type = app.canvas.annotation_type
|
if is_draw_shape(shape.shape_type):
|
||||||
self.canvas = app.canvas
|
title = "Add Shape"
|
||||||
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:
|
else:
|
||||||
super().__init__(master, app, "Add a new text", modal=True)
|
title = "Add Text"
|
||||||
|
self.id = None
|
||||||
|
self.canvas = app.canvas
|
||||||
|
super().__init__(master, app, title, modal=True)
|
||||||
|
self.fill = None
|
||||||
|
self.border = None
|
||||||
self.shape = shape
|
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)
|
||||||
self.font_size = tk.IntVar(value=data.font_size)
|
self.font_size = tk.IntVar(value=data.font_size)
|
||||||
self.text_color = data.text_color
|
self.text_color = data.text_color
|
||||||
self.fill_color = data.fill_color
|
fill_color = data.fill_color
|
||||||
|
if not fill_color:
|
||||||
|
fill_color = "#CFCFFF"
|
||||||
|
self.fill_color = fill_color
|
||||||
self.border_color = data.border_color
|
self.border_color = data.border_color
|
||||||
self.border_width = tk.IntVar(value=data.border_width)
|
self.border_width = tk.IntVar(value=0)
|
||||||
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.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)
|
||||||
|
@ -85,7 +79,7 @@ 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():
|
if is_draw_shape(self.shape.shape_type):
|
||||||
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)
|
||||||
|
@ -152,15 +146,18 @@ 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 self.is_shape() and not self.canvas.shapes[self.id].created:
|
if (
|
||||||
|
is_draw_shape(self.shape.shape_type)
|
||||||
|
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):
|
def click_add(self):
|
||||||
if self.is_shape():
|
if is_draw_shape(self.shape.shape_type):
|
||||||
self.add_shape()
|
self.add_shape()
|
||||||
elif self.is_text():
|
elif is_shape_text(self.shape.shape_type):
|
||||||
self.add_text()
|
self.add_text()
|
||||||
self.destroy()
|
self.destroy()
|
||||||
|
|
||||||
|
@ -212,8 +209,8 @@ class ShapeDialog(Dialog):
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
text = self.shape_text.get()
|
text = self.shape_text.get()
|
||||||
x = self.shape.x0
|
x = self.shape.x1
|
||||||
y = self.shape.y0
|
y = self.shape.y1
|
||||||
text_font = self.make_font()
|
text_font = self.make_font()
|
||||||
if self.shape.text_id is None:
|
if self.shape.text_id is None:
|
||||||
tid = self.canvas.create_text(
|
tid = self.canvas.create_text(
|
||||||
|
|
|
@ -16,8 +16,3 @@ class ScaleOption(enum.Enum):
|
||||||
CENTERED = 2
|
CENTERED = 2
|
||||||
SCALED = 3
|
SCALED = 3
|
||||||
TILED = 4
|
TILED = 4
|
||||||
|
|
||||||
|
|
||||||
class ShapeType(enum.Enum):
|
|
||||||
OVAL = 0
|
|
||||||
RECTANGLE = 1
|
|
||||||
|
|
|
@ -10,7 +10,8 @@ from coretk.graph.enums import GraphMode, ScaleOption
|
||||||
from coretk.graph.linkinfo import LinkInfo, Throughput
|
from coretk.graph.linkinfo import LinkInfo, Throughput
|
||||||
from coretk.graph.node import CanvasNode
|
from coretk.graph.node import CanvasNode
|
||||||
from coretk.graph.shape import Shape
|
from coretk.graph.shape import Shape
|
||||||
from coretk.images import ImageEnum, Images
|
from coretk.graph.shapeutils import is_draw_shape, is_shape_text
|
||||||
|
from coretk.images import Images
|
||||||
from coretk.nodeutils import NodeUtils
|
from coretk.nodeutils import NodeUtils
|
||||||
|
|
||||||
ABOVE_WALLPAPER = ["edge", "linkinfo", "wireless", "antenna", "nodename", "node"]
|
ABOVE_WALLPAPER = ["edge", "linkinfo", "wireless", "antenna", "nodename", "node"]
|
||||||
|
@ -243,13 +244,13 @@ class CanvasGraph(tk.Canvas):
|
||||||
self.context = None
|
self.context = None
|
||||||
else:
|
else:
|
||||||
if self.mode == GraphMode.ANNOTATION:
|
if self.mode == GraphMode.ANNOTATION:
|
||||||
if self.annotation_type in [ImageEnum.OVAL, ImageEnum.RECTANGLE]:
|
if is_draw_shape(self.annotation_type):
|
||||||
self.focus_set()
|
self.focus_set()
|
||||||
x, y = self.canvas_xy(event)
|
x, y = self.canvas_xy(event)
|
||||||
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:
|
elif is_shape_text(self.annotation_type):
|
||||||
self.text.shape_complete(self.text.cursor_x, self.text.cursor_y)
|
self.text.shape_complete(self.text.cursor_x, self.text.cursor_y)
|
||||||
else:
|
else:
|
||||||
self.focus_set()
|
self.focus_set()
|
||||||
|
@ -401,15 +402,14 @@ class CanvasGraph(tk.Canvas):
|
||||||
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 and selected is None:
|
if self.mode == GraphMode.ANNOTATION and selected is None:
|
||||||
if self.annotation_type in [ImageEnum.OVAL, ImageEnum.RECTANGLE]:
|
x, y = self.canvas_xy(event)
|
||||||
x, y = self.canvas_xy(event)
|
if is_draw_shape(self.annotation_type):
|
||||||
shape = Shape(self.app, self, x, y)
|
shape = Shape(self.app, self, self.annotation_type, 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:
|
elif is_shape_text(self.annotation_type):
|
||||||
x, y = self.canvas_xy(event)
|
self.text = Shape(self.app, self, self.annotation_type, x, y)
|
||||||
self.text = Shape(self.app, self, x, y)
|
|
||||||
|
|
||||||
if self.mode == GraphMode.SELECT:
|
if self.mode == GraphMode.SELECT:
|
||||||
if selected is not None:
|
if selected is not None:
|
||||||
|
@ -446,10 +446,7 @@ class CanvasGraph(tk.Canvas):
|
||||||
x1, y1, _, _ = self.coords(self.drawing_edge.id)
|
x1, y1, _, _ = self.coords(self.drawing_edge.id)
|
||||||
self.coords(self.drawing_edge.id, x1, y1, x2, y2)
|
self.coords(self.drawing_edge.id, x1, y1, x2, y2)
|
||||||
if self.mode == GraphMode.ANNOTATION:
|
if self.mode == GraphMode.ANNOTATION:
|
||||||
if (
|
if is_draw_shape(self.annotation_type) and self.shape_drawing:
|
||||||
self.annotation_type in [ImageEnum.OVAL, ImageEnum.RECTANGLE]
|
|
||||||
and self.shape_drawing
|
|
||||||
):
|
|
||||||
x, y = self.canvas_xy(event)
|
x, y = self.canvas_xy(event)
|
||||||
self.shapes[self.selected].shape_motion(x, y)
|
self.shapes[self.selected].shape_motion(x, y)
|
||||||
if (
|
if (
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
"""
|
from tkinter.font import Font
|
||||||
class for shapes
|
|
||||||
"""
|
|
||||||
from coretk.dialogs.shapemod import ShapeDialog
|
from coretk.dialogs.shapemod import ShapeDialog
|
||||||
from coretk.images import ImageEnum
|
from coretk.graph.shapeutils import ShapeType
|
||||||
|
|
||||||
ABOVE_COMPONENT = ["gridline", "edge", "linkinfo", "antenna", "node", "nodename"]
|
ABOVE_COMPONENT = ["gridline", "edge", "linkinfo", "antenna", "node", "nodename"]
|
||||||
|
|
||||||
|
@ -14,14 +13,13 @@ class AnnotationData:
|
||||||
font="Arial",
|
font="Arial",
|
||||||
font_size=12,
|
font_size=12,
|
||||||
text_color="#000000",
|
text_color="#000000",
|
||||||
fill_color="#CFCFFF",
|
fill_color="",
|
||||||
border_color="#000000",
|
border_color="#000000",
|
||||||
border_width=0,
|
border_width=1,
|
||||||
bold=0,
|
bold=0,
|
||||||
italic=0,
|
italic=0,
|
||||||
underline=0,
|
underline=0,
|
||||||
):
|
):
|
||||||
|
|
||||||
self.text = text
|
self.text = text
|
||||||
self.font = font
|
self.font = font
|
||||||
self.font_size = font_size
|
self.font_size = font_size
|
||||||
|
@ -35,72 +33,77 @@ class AnnotationData:
|
||||||
|
|
||||||
|
|
||||||
class Shape:
|
class Shape:
|
||||||
def __init__(
|
def __init__(self, app, canvas, shape_type, x1, y1, x2=None, y2=None, data=None):
|
||||||
self,
|
|
||||||
app,
|
|
||||||
canvas,
|
|
||||||
top_x=None,
|
|
||||||
top_y=None,
|
|
||||||
coords=None,
|
|
||||||
data=None,
|
|
||||||
shape_type=None,
|
|
||||||
):
|
|
||||||
self.app = app
|
self.app = app
|
||||||
self.canvas = canvas
|
self.canvas = canvas
|
||||||
|
self.shape_type = shape_type
|
||||||
|
self.id = None
|
||||||
|
self.text_id = None
|
||||||
|
self.x1 = x1
|
||||||
|
self.y1 = y1
|
||||||
|
if x2 is None:
|
||||||
|
x2 = x1
|
||||||
|
self.x2 = x2
|
||||||
|
if y2 is None:
|
||||||
|
y2 = y1
|
||||||
|
self.y2 = y2
|
||||||
if data is None:
|
if data is None:
|
||||||
self.x0 = top_x
|
|
||||||
self.y0 = top_y
|
|
||||||
self.created = False
|
self.created = False
|
||||||
self.text_id = None
|
|
||||||
self.shape_data = AnnotationData()
|
self.shape_data = AnnotationData()
|
||||||
canvas.delete(canvas.find_withtag("selectednodes"))
|
self.cursor_x = x1
|
||||||
annotation_type = self.canvas.annotation_type
|
self.cursor_y = y1
|
||||||
if annotation_type == ImageEnum.OVAL:
|
|
||||||
self.id = canvas.create_oval(
|
|
||||||
top_x, top_y, top_x, top_y, tags="shape", dash="-"
|
|
||||||
)
|
|
||||||
elif annotation_type == ImageEnum.RECTANGLE:
|
|
||||||
self.id = canvas.create_rectangle(
|
|
||||||
top_x, top_y, top_x, top_y, tags="shape", dash="-"
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
x0, y0, x1, y1 = coords
|
|
||||||
self.x0 = x0
|
|
||||||
self.y0 = y0
|
|
||||||
self.created = True
|
self.created = True
|
||||||
if shape_type == "oval":
|
|
||||||
self.id = self.canvas.create_oval(
|
|
||||||
x0,
|
|
||||||
y0,
|
|
||||||
x1,
|
|
||||||
y1,
|
|
||||||
tags="shape",
|
|
||||||
fill=data.fill_color,
|
|
||||||
outline=data.border_color,
|
|
||||||
width=data.border_width,
|
|
||||||
)
|
|
||||||
elif shape_type == "rectangle":
|
|
||||||
self.id = self.canvas.create_rectangle(
|
|
||||||
x0,
|
|
||||||
y0,
|
|
||||||
x1,
|
|
||||||
y1,
|
|
||||||
tags="shape",
|
|
||||||
fill=data.fill_color,
|
|
||||||
outline=data.border_color,
|
|
||||||
width=data.border_width,
|
|
||||||
)
|
|
||||||
_x = (x0 + x1) / 2
|
|
||||||
_y = y0 + 1.5 * data.font_size
|
|
||||||
self.text_id = self.canvas.create_text(
|
|
||||||
_x, _y, tags="shapetext", text=data.text, fill=data.text_color
|
|
||||||
)
|
|
||||||
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.draw()
|
||||||
|
|
||||||
|
def draw(self):
|
||||||
|
if self.created:
|
||||||
|
dash = None
|
||||||
|
else:
|
||||||
|
dash = "-"
|
||||||
|
if self.shape_type == ShapeType.OVAL:
|
||||||
|
self.id = self.canvas.create_oval(
|
||||||
|
self.x1,
|
||||||
|
self.y1,
|
||||||
|
self.x2,
|
||||||
|
self.y2,
|
||||||
|
tags="shape",
|
||||||
|
dash=dash,
|
||||||
|
fill=self.shape_data.fill_color,
|
||||||
|
outline=self.shape_data.border_color,
|
||||||
|
width=self.shape_data.border_width,
|
||||||
|
)
|
||||||
|
elif self.shape_type == ShapeType.RECTANGLE:
|
||||||
|
self.id = self.canvas.create_rectangle(
|
||||||
|
self.x1,
|
||||||
|
self.y1,
|
||||||
|
self.x2,
|
||||||
|
self.y2,
|
||||||
|
tags="shape",
|
||||||
|
dash=dash,
|
||||||
|
fill=self.shape_data.fill_color,
|
||||||
|
outline=self.shape_data.border_color,
|
||||||
|
width=self.shape_data.border_width,
|
||||||
|
)
|
||||||
|
|
||||||
|
if self.shape_data.text:
|
||||||
|
x = (self.x1 + self.x2) / 2
|
||||||
|
y = self.y1 + 1.5 * self.shape_data.font_size
|
||||||
|
font = Font(family=self.shape_data.font, size=self.shape_data.font_size)
|
||||||
|
self.text_id = self.canvas.create_text(
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
tags="shapetext",
|
||||||
|
text=self.shape_data.text,
|
||||||
|
fill=self.shape_data.text_color,
|
||||||
|
font=font,
|
||||||
|
)
|
||||||
|
|
||||||
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.x1, self.y1, x1, y1)
|
||||||
|
|
||||||
def shape_complete(self, x, y):
|
def shape_complete(self, x, y):
|
||||||
for component in ABOVE_COMPONENT:
|
for component in ABOVE_COMPONENT:
|
||||||
|
@ -122,3 +125,17 @@ class Shape:
|
||||||
def delete(self):
|
def delete(self):
|
||||||
self.canvas.delete(self.id)
|
self.canvas.delete(self.id)
|
||||||
self.canvas.delete(self.text_id)
|
self.canvas.delete(self.text_id)
|
||||||
|
|
||||||
|
def metadata(self):
|
||||||
|
coords = self.canvas.coords(self.id)
|
||||||
|
return {
|
||||||
|
"type": self.shape_type.value,
|
||||||
|
"iconcoords": coords,
|
||||||
|
"label": self.shape_data.text,
|
||||||
|
"fontfamily": self.shape_data.font,
|
||||||
|
"fontsize": self.shape_data.font_size,
|
||||||
|
"labelcolor": self.shape_data.text_color,
|
||||||
|
"color": self.shape_data.fill_color,
|
||||||
|
"border": self.shape_data.border_color,
|
||||||
|
"width": self.shape_data.border_width,
|
||||||
|
}
|
||||||
|
|
19
coretk/coretk/graph/shapeutils.py
Normal file
19
coretk/coretk/graph/shapeutils.py
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
import enum
|
||||||
|
|
||||||
|
|
||||||
|
class ShapeType(enum.Enum):
|
||||||
|
MARKER = "marker"
|
||||||
|
OVAL = "oval"
|
||||||
|
RECTANGLE = "rectangle"
|
||||||
|
TEXT = "text"
|
||||||
|
|
||||||
|
|
||||||
|
SHAPES = {ShapeType.OVAL, ShapeType.RECTANGLE}
|
||||||
|
|
||||||
|
|
||||||
|
def is_draw_shape(shape_type):
|
||||||
|
return shape_type in SHAPES
|
||||||
|
|
||||||
|
|
||||||
|
def is_shape_text(shape_type):
|
||||||
|
return shape_type == ShapeType.TEXT
|
|
@ -6,6 +6,7 @@ from tkinter import ttk
|
||||||
|
|
||||||
from coretk.dialogs.customnodes import CustomNodesDialog
|
from coretk.dialogs.customnodes import CustomNodesDialog
|
||||||
from coretk.graph.enums import GraphMode
|
from coretk.graph.enums import GraphMode
|
||||||
|
from coretk.graph.shapeutils import ShapeType
|
||||||
from coretk.images import ImageEnum, Images
|
from coretk.images import ImageEnum, Images
|
||||||
from coretk.nodeutils import NodeUtils
|
from coretk.nodeutils import NodeUtils
|
||||||
from coretk.tooltip import Tooltip
|
from coretk.tooltip import Tooltip
|
||||||
|
@ -291,18 +292,18 @@ class Toolbar(ttk.Frame):
|
||||||
self.hide_pickers()
|
self.hide_pickers()
|
||||||
self.annotation_picker = ttk.Frame(self.master)
|
self.annotation_picker = ttk.Frame(self.master)
|
||||||
nodes = [
|
nodes = [
|
||||||
(ImageEnum.MARKER, "marker"),
|
(ImageEnum.MARKER, ShapeType.MARKER),
|
||||||
(ImageEnum.OVAL, "oval"),
|
(ImageEnum.OVAL, ShapeType.OVAL),
|
||||||
(ImageEnum.RECTANGLE, "rectangle"),
|
(ImageEnum.RECTANGLE, ShapeType.RECTANGLE),
|
||||||
(ImageEnum.TEXT, "text"),
|
(ImageEnum.TEXT, ShapeType.TEXT),
|
||||||
]
|
]
|
||||||
for image_enum, tooltip in nodes:
|
for image_enum, shape_type in nodes:
|
||||||
image = icon(image_enum)
|
image = icon(image_enum)
|
||||||
self.create_picker_button(
|
self.create_picker_button(
|
||||||
image,
|
image,
|
||||||
partial(self.update_annotation, image, image_enum),
|
partial(self.update_annotation, image, shape_type),
|
||||||
self.annotation_picker,
|
self.annotation_picker,
|
||||||
tooltip,
|
shape_type.value,
|
||||||
)
|
)
|
||||||
self.design_select(self.annotation_button)
|
self.design_select(self.annotation_button)
|
||||||
self.annotation_button.after(
|
self.annotation_button.after(
|
||||||
|
@ -362,13 +363,13 @@ class Toolbar(ttk.Frame):
|
||||||
|
|
||||||
self.design_frame.tkraise()
|
self.design_frame.tkraise()
|
||||||
|
|
||||||
def update_annotation(self, image, image_enum):
|
def update_annotation(self, image, shape_type):
|
||||||
logging.info("clicked annotation: ")
|
logging.info("clicked annotation: ")
|
||||||
self.hide_pickers()
|
self.hide_pickers()
|
||||||
self.annotation_button.configure(image=image)
|
self.annotation_button.configure(image=image)
|
||||||
self.annotation_button.image = image
|
self.annotation_button.image = image
|
||||||
self.app.canvas.mode = GraphMode.ANNOTATION
|
self.app.canvas.mode = GraphMode.ANNOTATION
|
||||||
self.app.canvas.annotation_type = image_enum
|
self.app.canvas.annotation_type = shape_type
|
||||||
|
|
||||||
def click_run_button(self):
|
def click_run_button(self):
|
||||||
logging.debug("Click on RUN button")
|
logging.debug("Click on RUN button")
|
||||||
|
|
Loading…
Add table
Reference in a new issue