initial classes to help support creating layers for toggling visibility on the canvas for associated items

This commit is contained in:
Blake Harnden 2020-07-20 23:50:01 -07:00
parent 5e2ca0f549
commit f72d0d8a69
5 changed files with 176 additions and 0 deletions

View file

@ -0,0 +1,60 @@
import tkinter as tk
from tkinter import messagebox, ttk
from typing import TYPE_CHECKING, Optional
from core.gui.dialogs.dialog import Dialog
from core.gui.dialogs.simple import SimpleStringDialog
from core.gui.themes import PADX, PADY
from core.gui.widgets import ListboxScroll
if TYPE_CHECKING:
from core.gui.app import Application
class LayersDialog(Dialog):
def __init__(self, app: "Application") -> None:
super().__init__(app, "Canvas Layers", modal=False)
self.list: Optional[ListboxScroll] = None
self.draw()
def draw(self) -> None:
self.top.columnconfigure(0, weight=1)
self.list = ListboxScroll(self.top)
self.list.grid(sticky=tk.EW, pady=PADY)
for name in self.app.canvas.layers.names():
self.list.listbox.insert(tk.END, name)
frame = ttk.Frame(self.top)
frame.grid(sticky=tk.EW)
for i in range(3):
frame.columnconfigure(i, weight=1)
button = ttk.Button(frame, text="Add", command=self.click_add)
button.grid(row=0, column=0, sticky=tk.EW, padx=PADX)
button = ttk.Button(frame, text="Delete", command=self.click_delete)
button.grid(row=0, column=1, sticky=tk.EW, padx=PADX)
button = ttk.Button(frame, text="Toggle", command=self.click_toggle)
button.grid(row=0, column=2, sticky=tk.EW)
def click_add(self):
name = SimpleStringDialog(self, self.app, "Add Layer", "Layer Name").ask()
if name:
result = self.app.canvas.layers.add_layer(name)
if result:
self.list.listbox.insert(tk.END, name)
else:
messagebox.showerror(
"Add Layer", f"Duplicate Layer: {name}", parent=self
)
def click_delete(self):
selection = self.list.listbox.curselection()
if not selection:
return
name = self.list.listbox.get(selection)
print(name)
def click_toggle(self):
selection = self.list.listbox.curselection()
if not selection:
return
name = self.list.listbox.get(selection)
print(name)

View file

@ -0,0 +1,48 @@
import tkinter as tk
from tkinter import ttk
from typing import TYPE_CHECKING, Optional
from core.gui.dialogs.dialog import Dialog
from core.gui.themes import PADX, PADY
if TYPE_CHECKING:
from core.gui.app import Application
class SimpleStringDialog(Dialog):
def __init__(
self, master: tk.BaseWidget, app: "Application", title: str, prompt: str
):
super().__init__(app, title, master=master)
self.prompt: str = prompt
self.value = tk.StringVar()
self.entry: Optional[ttk.Entry] = None
self.canceled = False
self.draw()
def draw(self) -> None:
self.top.columnconfigure(0, weight=1)
label = ttk.Label(self.top, text=self.prompt)
label.grid(sticky=tk.EW, pady=PADY)
entry = ttk.Entry(self.top, textvariable=self.value)
entry.grid(stick=tk.EW, pady=PADY)
entry.focus_set()
frame = ttk.Frame(self.top)
frame.grid(sticky=tk.EW)
for i in range(2):
frame.columnconfigure(i, weight=1)
button = ttk.Button(frame, text="Submit", command=self.destroy)
button.grid(row=0, column=0, sticky=tk.EW, padx=PADX)
button = ttk.Button(frame, text="Cancel", command=self.click_cancel)
button.grid(row=0, column=1, sticky=tk.EW)
def click_cancel(self):
self.canceled = True
self.destroy()
def ask(self) -> Optional[str]:
self.show()
if self.canceled:
return None
else:
return self.value.get()

View file

@ -25,6 +25,7 @@ from core.gui.graph.edges import (
create_edge_token,
)
from core.gui.graph.enums import GraphMode, ScaleOption
from core.gui.graph.layers import CanvasLayers
from core.gui.graph.node import CanvasNode
from core.gui.graph.shape import Shape
from core.gui.graph.shapeutils import ShapeType, is_draw_shape, is_marker
@ -62,6 +63,7 @@ class CanvasGraph(tk.Canvas):
super().__init__(master, highlightthickness=0, background="#cccccc")
self.app: "Application" = app
self.core: "CoreClient" = core
self.layers = CanvasLayers(self)
self.mode: GraphMode = GraphMode.SELECT
self.annotation_type: Optional[ShapeType] = None
self.selection: Dict[int, int] = {}

View file

@ -0,0 +1,58 @@
import tkinter as tk
from typing import TYPE_CHECKING, Dict, Iterable, Set
if TYPE_CHECKING:
from core.gui.graph.graph import CanvasGraph
class CanvasLayers:
def __init__(self, canvas: "CanvasGraph"):
self.canvas: "CanvasGraph" = canvas
self.layers: Dict[str, Set[int]] = {}
self.hidden: Set[str] = set()
def names(self) -> Iterable[str]:
return self.layers.keys()
def add_layer(self, name: str) -> bool:
if name in self.layers:
return False
else:
self.layers[name] = set()
return True
def delete_layer(self, name: str) -> None:
items = self.layers.pop(name, set())
hidden_items = self.all_hidden()
items -= hidden_items
self.canvas.config(items, state=tk.NORMAL)
def add_item(self, name: str, item: int) -> None:
if name in self.layers:
self.layers[name].add(item)
if name in self.hidden:
self.canvas.config(item, state=tk.HIDDEN)
def delete_item(self, name: str, item: int) -> None:
if name in self.layers:
self.layers[name].remove(item)
hidden_items = self.all_hidden()
if item not in hidden_items:
self.canvas.config(item, state=tk.NORMAL)
def toggle_layer(self, name: str) -> None:
items = self.layers[name]
if name in self.hidden:
self.hidden.remove(name)
hidden_items = self.all_hidden()
items -= hidden_items
self.canvas.config(items, state=tk.NORMAL)
else:
self.hidden.add(name)
self.canvas.config(items, state=tk.HIDDEN)
def all_hidden(self) -> Set[int]:
items = set()
for name in self.hidden:
items |= self.layers[name]
return items

View file

@ -9,6 +9,7 @@ from PIL.ImageTk import PhotoImage
from core.api.grpc import core_pb2
from core.gui.dialogs.colorpicker import ColorPickerDialog
from core.gui.dialogs.layers import LayersDialog
from core.gui.dialogs.runtool import RunToolDialog
from core.gui.graph import tags
from core.gui.graph.enums import GraphMode
@ -237,6 +238,9 @@ class Toolbar(ttk.Frame):
"Annotation Tools",
radio=True,
)
self.design_frame.create_button(
self.annotation_enum, self.show_layers, "Layers"
)
def draw_runtime_frame(self) -> None:
self.runtime_frame = ButtonBar(self, self.app)
@ -256,6 +260,10 @@ class Toolbar(ttk.Frame):
ImageEnum.RUN, self.click_run_button, "Run Tool"
)
def show_layers(self) -> None:
dialog = LayersDialog(self.app)
dialog.show()
def draw_node_picker(self) -> None:
self.hide_marker()
self.app.canvas.mode = GraphMode.NODE