pygui: toolbar cleanup for buttonbar frames

This commit is contained in:
Blake Harnden 2020-05-15 23:23:07 -07:00
parent 4eaecd6a7b
commit 29fc5acb99
2 changed files with 74 additions and 129 deletions

View file

@ -1,7 +1,7 @@
import logging
import math
import tkinter as tk
from tkinter import font, ttk
from tkinter import PhotoImage, font, ttk
from tkinter.ttk import Progressbar
import grpc
@ -160,5 +160,8 @@ class Application(ttk.Frame):
else:
self.toolbar.set_design()
def get_icon(self, image_enum: ImageEnum, width: int) -> PhotoImage:
return Images.get(image_enum, int(width * self.app_scale))
def close(self) -> None:
self.master.destroy()

View file

@ -37,6 +37,30 @@ def enable_buttons(frame: ttk.Frame, enabled: bool) -> None:
child.configure(state=state)
class ButtonBar(ttk.Frame):
def __init__(self, master: tk.Widget, app: "Application"):
super().__init__(master)
self.app = app
self.radio_buttons = []
def create_button(
self, image_enum: ImageEnum, func: Callable, tooltip: str, radio: bool = False
) -> ttk.Button:
image = self.app.get_icon(image_enum, TOOLBAR_SIZE)
button = ttk.Button(self, image=image, command=func)
button.image = image
button.grid(sticky="ew")
Tooltip(button, tooltip)
if radio:
self.radio_buttons.append(button)
return button
def select_radio(self, selected: ttk.Button) -> None:
for button in self.radio_buttons:
button.state(["!pressed"])
selected.state(["pressed"])
class Toolbar(ttk.Frame):
"""
Core toolbar class
@ -82,9 +106,6 @@ class Toolbar(ttk.Frame):
# draw components
self.draw()
def get_icon(self, image_enum: ImageEnum, width: int) -> PhotoImage:
return Images.get(image_enum, int(width * self.app.app_scale))
def draw(self) -> None:
self.columnconfigure(0, weight=1)
self.rowconfigure(0, weight=1)
@ -93,84 +114,59 @@ class Toolbar(ttk.Frame):
self.design_frame.tkraise()
def draw_design_frame(self) -> None:
self.design_frame = ttk.Frame(self)
self.design_frame = ButtonBar(self, self.app)
self.design_frame.grid(row=0, column=0, sticky="nsew")
self.design_frame.columnconfigure(0, weight=1)
self.play_button = self.create_button(
self.design_frame,
self.get_icon(ImageEnum.START, TOOLBAR_SIZE),
self.click_start,
"start the session",
self.play_button = self.design_frame.create_button(
ImageEnum.START, self.click_start, "Start Session"
)
self.select_button = self.create_button(
self.design_frame,
self.get_icon(ImageEnum.SELECT, TOOLBAR_SIZE),
self.click_selection,
"selection tool",
self.select_button = self.design_frame.create_button(
ImageEnum.SELECT, self.click_selection, "Selection Tool", radio=True
)
self.link_button = self.create_button(
self.design_frame,
self.get_icon(ImageEnum.LINK, TOOLBAR_SIZE),
self.click_link,
"link tool",
self.link_button = self.design_frame.create_button(
ImageEnum.LINK, self.click_link, "Link Tool", radio=True
)
self.node_enum = ImageEnum.ROUTER
self.node_button = self.design_frame.create_button(
self.node_enum, self.draw_node_picker, "Container Nodes", radio=True
)
self.network_enum = ImageEnum.HUB
self.network_button = self.design_frame.create_button(
self.network_enum, self.draw_network_picker, "Link Layer Nodes", radio=True
)
self.annotation_enum = ImageEnum.MARKER
self.annotation_button = self.design_frame.create_button(
self.annotation_enum,
self.draw_annotation_picker,
"Annotation Tools",
radio=True,
)
self.create_node_button()
self.create_network_button()
self.create_annotation_button()
def design_select(self, button: ttk.Button) -> None:
logging.debug("selecting design button: %s", button)
self.select_button.state(["!pressed"])
self.link_button.state(["!pressed"])
self.node_button.state(["!pressed"])
self.network_button.state(["!pressed"])
self.annotation_button.state(["!pressed"])
button.state(["pressed"])
def runtime_select(self, button: ttk.Button) -> None:
logging.debug("selecting runtime button: %s", button)
self.runtime_select_button.state(["!pressed"])
self.stop_button.state(["!pressed"])
self.runtime_marker_button.state(["!pressed"])
self.run_command_button.state(["!pressed"])
button.state(["pressed"])
def draw_runtime_frame(self) -> None:
self.runtime_frame = ttk.Frame(self)
self.runtime_frame = ButtonBar(self, self.app)
self.runtime_frame.grid(row=0, column=0, sticky="nsew")
self.runtime_frame.columnconfigure(0, weight=1)
self.stop_button = self.create_button(
self.runtime_frame,
self.get_icon(ImageEnum.STOP, TOOLBAR_SIZE),
self.click_stop,
"stop the session",
self.stop_button = self.runtime_frame.create_button(
ImageEnum.STOP, self.click_stop, "Stop Session"
)
self.runtime_select_button = self.create_button(
self.runtime_frame,
self.get_icon(ImageEnum.SELECT, TOOLBAR_SIZE),
self.click_runtime_selection,
"selection tool",
self.runtime_select_button = self.runtime_frame.create_button(
ImageEnum.SELECT, self.click_runtime_selection, "Selection Tool", radio=True
)
self.runtime_marker_button = self.create_button(
self.runtime_frame,
self.get_icon(ImageEnum.MARKER, TOOLBAR_SIZE),
self.click_marker_button,
"marker",
self.runtime_marker_button = self.runtime_frame.create_button(
ImageEnum.MARKER, self.click_marker_button, "Marker Tool", radio=True
)
self.run_command_button = self.create_button(
self.runtime_frame,
self.get_icon(ImageEnum.RUN, TOOLBAR_SIZE),
self.click_run_button,
"run",
self.run_command_button = self.runtime_frame.create_button(
ImageEnum.RUN, self.click_run_button, "Run Tool"
)
def draw_node_picker(self) -> None:
self.design_frame.select_radio(self.node_button)
self.hide_pickers()
self.node_picker = ttk.Frame(self.master)
# draw default nodes
for node_draw in NodeUtils.NODES:
toolbar_image = self.get_icon(node_draw.image_enum, TOOLBAR_SIZE)
image = self.get_icon(node_draw.image_enum, PICKER_SIZE)
toolbar_image = self.app.get_icon(node_draw.image_enum, TOOLBAR_SIZE)
image = self.app.get_icon(node_draw.image_enum, PICKER_SIZE)
func = partial(
self.update_button,
self.node_button,
@ -198,7 +194,6 @@ class Toolbar(ttk.Frame):
node_draw.image_file,
)
self.create_picker_button(image, func, self.node_picker, name)
self.design_select(self.node_button)
self.node_button.after(
0, lambda: self.show_picker(self.node_button, self.node_picker)
)
@ -231,23 +226,12 @@ class Toolbar(ttk.Frame):
button.bind("<ButtonRelease-1>", lambda e: func())
button.grid(pady=1)
def create_button(
self, frame: ttk.Frame, image: PhotoImage, func: Callable, tooltip: str
) -> ttk.Button:
button = ttk.Button(frame, image=image, command=func)
button.image = image
button.grid(sticky="ew")
Tooltip(button, tooltip)
return button
def click_selection(self) -> None:
logging.debug("clicked selection tool")
self.design_select(self.select_button)
self.design_frame.select_radio(self.select_button)
self.app.canvas.mode = GraphMode.SELECT
def click_runtime_selection(self) -> None:
logging.debug("clicked selection tool")
self.runtime_select(self.runtime_select_button)
self.runtime_frame.select_radio(self.runtime_select_button)
self.app.canvas.mode = GraphMode.SELECT
def click_start(self) -> None:
@ -284,8 +268,7 @@ class Toolbar(ttk.Frame):
self.click_selection()
def click_link(self) -> None:
logging.debug("Click LINK button")
self.design_select(self.link_button)
self.design_frame.select_radio(self.link_button)
self.app.canvas.mode = GraphMode.EDGE
def update_button(
@ -319,28 +302,16 @@ class Toolbar(ttk.Frame):
self.annotation_picker.destroy()
self.annotation_picker = None
def create_node_button(self) -> None:
"""
Create network layer button
"""
image = self.get_icon(ImageEnum.ROUTER, TOOLBAR_SIZE)
self.node_button = ttk.Button(
self.design_frame, image=image, command=self.draw_node_picker
)
self.node_button.image = image
self.node_button.grid(sticky="ew")
Tooltip(self.node_button, "Network-layer virtual nodes")
self.node_enum = ImageEnum.ROUTER
def draw_network_picker(self) -> None:
"""
Draw the options for link-layer button.
"""
self.design_frame.select_radio(self.network_button)
self.hide_pickers()
self.network_picker = ttk.Frame(self.master)
for node_draw in NodeUtils.NETWORK_NODES:
toolbar_image = self.get_icon(node_draw.image_enum, TOOLBAR_SIZE)
image = self.get_icon(node_draw.image_enum, PICKER_SIZE)
toolbar_image = self.app.get_icon(node_draw.image_enum, TOOLBAR_SIZE)
image = self.app.get_icon(node_draw.image_enum, PICKER_SIZE)
self.create_picker_button(
image,
partial(
@ -354,29 +325,15 @@ class Toolbar(ttk.Frame):
self.network_picker,
node_draw.label,
)
self.design_select(self.network_button)
self.network_button.after(
0, lambda: self.show_picker(self.network_button, self.network_picker)
)
def create_network_button(self) -> None:
"""
Create link-layer node button and the options that represent different
link-layer node types.
"""
image = self.get_icon(ImageEnum.HUB, TOOLBAR_SIZE)
self.network_button = ttk.Button(
self.design_frame, image=image, command=self.draw_network_picker
)
self.network_button.image = image
self.network_button.grid(sticky="ew")
Tooltip(self.network_button, "link-layer nodes")
self.network_enum = ImageEnum.HUB
def draw_annotation_picker(self) -> None:
"""
Draw the options for marker button.
"""
self.design_frame.select_radio(self.annotation_button)
self.hide_pickers()
self.annotation_picker = ttk.Frame(self.master)
nodes = [
@ -386,34 +343,20 @@ class Toolbar(ttk.Frame):
(ImageEnum.TEXT, ShapeType.TEXT),
]
for image_enum, shape_type in nodes:
toolbar_image = self.get_icon(image_enum, TOOLBAR_SIZE)
image = self.get_icon(image_enum, PICKER_SIZE)
toolbar_image = self.app.get_icon(image_enum, TOOLBAR_SIZE)
image = self.app.get_icon(image_enum, PICKER_SIZE)
self.create_picker_button(
image,
partial(self.update_annotation, toolbar_image, shape_type, image_enum),
self.annotation_picker,
shape_type.value,
)
self.design_select(self.annotation_button)
self.annotation_button.after(
0, lambda: self.show_picker(self.annotation_button, self.annotation_picker)
)
def create_annotation_button(self) -> None:
"""
Create marker button and options that represent different marker types
"""
image = self.get_icon(ImageEnum.MARKER, TOOLBAR_SIZE)
self.annotation_button = ttk.Button(
self.design_frame, image=image, command=self.draw_annotation_picker
)
self.annotation_button.image = image
self.annotation_button.grid(sticky="ew")
Tooltip(self.annotation_button, "background annotation tools")
self.annotation_enum = ImageEnum.MARKER
def create_observe_button(self) -> None:
image = self.get_icon(ImageEnum.OBSERVE, TOOLBAR_SIZE)
image = self.app.get_icon(ImageEnum.OBSERVE, TOOLBAR_SIZE)
menu_button = ttk.Menubutton(
self.runtime_frame, image=image, direction=tk.RIGHT
)
@ -476,8 +419,7 @@ class Toolbar(ttk.Frame):
dialog.show()
def click_marker_button(self) -> None:
logging.debug("Click on marker button")
self.runtime_select(self.runtime_marker_button)
self.runtime_frame.select_radio(self.runtime_marker_button)
self.app.canvas.mode = GraphMode.ANNOTATION
self.app.canvas.annotation_type = ShapeType.MARKER
if self.marker_tool:
@ -486,7 +428,7 @@ class Toolbar(ttk.Frame):
self.marker_tool.show()
def scale_button(self, button, image_enum) -> None:
image = self.get_icon(image_enum, TOOLBAR_SIZE)
image = self.app.get_icon(image_enum, TOOLBAR_SIZE)
button.config(image=image)
button.image = image