moved all modules creating dialogs under dialogs package, updated node config and node icon dialogs to use common dialog class, fixed common dialog class show order to fix delayed cases with grab_set

This commit is contained in:
bharnden 2019-11-02 23:47:43 -07:00
parent b991dc0242
commit d4f77a01e3
12 changed files with 184 additions and 274 deletions

View file

@ -5,8 +5,8 @@ canvas graph action
# import tkinter as tk
from core.api.grpc import core_pb2
from coretk.nodeconfigtable import NodeConfig
from coretk.wlanconfiguration import WlanConfiguration
from coretk.dialogs.nodeconfig import NodeConfigDialog
from coretk.dialogs.wlanconfig import WlanConfiguration
# TODO, finish classifying node types
NODE_TO_TYPE = {
@ -18,7 +18,6 @@ NODE_TO_TYPE = {
class CanvasAction:
def __init__(self, master, canvas):
self.master = master
self.canvas = canvas
self.node_to_show_config = None
@ -31,7 +30,8 @@ class CanvasAction:
self.display_wlan_configuration(canvas_node)
def display_node_configuration(self):
NodeConfig(self.canvas, self.node_to_show_config)
dialog = NodeConfigDialog(self.master, self.master, self.node_to_show_config)
dialog.show()
self.node_to_show_config = None
def display_wlan_configuration(self, canvas_node):

View file

@ -17,8 +17,9 @@ class Dialog(tk.Toplevel):
def show(self):
self.transient(self.master)
self.focus_force()
if self.modal:
self.grab_set()
self.update()
self.deiconify()
if self.modal:
self.wait_visibility()
self.grab_set()
self.wait_window()

View file

@ -0,0 +1,94 @@
import tkinter as tk
from tkinter import ttk
from coretk.dialogs.dialog import Dialog
from coretk.dialogs.nodeicon import NodeIconDialog
from coretk.dialogs.nodeservice import NodeServices
NETWORKNODETYPES = ["switch", "hub", "wlan", "rj45", "tunnel"]
DEFAULTNODES = ["router", "host", "PC"]
class NodeConfigDialog(Dialog):
def __init__(self, master, app, canvas_node):
"""
create an instance of node configuration
:param master: dialog master
:param coretk.app.Application: main app
:param coretk.graph.CanvasNode canvas_node: canvas node object
"""
super().__init__(master, app, f"{canvas_node.name} Configuration", modal=True)
self.canvas_node = canvas_node
self.image = canvas_node.image
self.image_button = None
self.name = tk.StringVar(value=canvas_node.name)
self.type = tk.StringVar(value=canvas_node.node_type)
self.server = tk.StringVar()
self.draw()
def draw(self):
self.columnconfigure(0, weight=1)
self.draw_first_row()
self.draw_second_row()
self.draw_third_row()
def draw_first_row(self):
frame = tk.Frame(self)
frame.grid(row=0, column=0, pady=2, sticky="ew")
frame.columnconfigure(0, weight=1)
frame.columnconfigure(1, weight=1)
frame.columnconfigure(2, weight=1)
entry = tk.Entry(frame, textvariable=self.name)
entry.grid(row=0, column=0, padx=2, sticky="ew")
combobox = ttk.Combobox(frame, textvariable=self.type, values=DEFAULTNODES)
combobox.grid(row=0, column=1, padx=2, sticky="ew")
combobox = ttk.Combobox(frame, textvariable=self.server, values=["localhost"])
combobox.current(0)
combobox.grid(row=0, column=2, sticky="ew")
def draw_second_row(self):
frame = tk.Frame(self)
frame.grid(row=1, column=0, pady=2, sticky="ew")
frame.columnconfigure(0, weight=1)
frame.columnconfigure(1, weight=1)
button = tk.Button(frame, text="Services", command=lambda: NodeServices())
button.grid(row=0, column=0, padx=2, sticky="ew")
self.image_button = tk.Button(
frame,
text="Icon",
image=self.image,
compound=tk.LEFT,
command=self.click_icon,
)
self.image_button.grid(row=0, column=1, sticky="ew")
def draw_third_row(self):
frame = tk.Frame(self)
frame.grid(row=2, column=0, sticky="ew")
frame.columnconfigure(0, weight=1)
frame.columnconfigure(1, weight=1)
button = tk.Button(frame, text="Apply", command=self.config_apply)
button.grid(row=0, column=0, padx=2, sticky="ew")
button = tk.Button(frame, text="Cancel", command=self.destroy)
button.grid(row=0, column=1, sticky="ew")
def click_icon(self):
dialog = NodeIconDialog(self, self.app, self.canvas_node)
dialog.show()
if dialog.image:
self.image = dialog.image
self.image_button.config(image=self.image)
def config_apply(self):
self.canvas_node.name = self.name.get()
self.canvas_node.image = self.image
self.canvas_node.canvas.itemconfig(self.canvas_node.id, image=self.image)
self.destroy()

View file

@ -0,0 +1,69 @@
import tkinter as tk
from tkinter import filedialog
from coretk.appdirs import ICONS_PATH
from coretk.dialogs.dialog import Dialog
from coretk.images import Images
class NodeIconDialog(Dialog):
def __init__(self, master, app, canvas_node):
"""
create an instance of ImageModification
:param master: dialog master
:param coretk.app.Application: main app
:param coretk.graph.CanvasNode canvas_node: node object
"""
super().__init__(master, app, f"{canvas_node.name} Icon", modal=True)
self.file_path = tk.StringVar()
self.image_label = None
self.image = canvas_node.image
self.draw()
def draw(self):
self.columnconfigure(0, weight=1)
# row one
frame = tk.Frame(self)
frame.grid(row=0, column=0, pady=2, sticky="ew")
frame.columnconfigure(0, weight=1)
frame.columnconfigure(1, weight=3)
label = tk.Label(frame, text="Image")
label.grid(row=0, column=0, sticky="ew")
entry = tk.Entry(frame, textvariable=self.file_path)
entry.grid(row=0, column=1, sticky="ew")
button = tk.Button(frame, text="...", command=self.click_file)
button.grid(row=0, column=2)
# row two
self.image_label = tk.Label(self, image=self.image)
self.image_label.grid(row=1, column=0, pady=2, sticky="ew")
# row three
frame = tk.Frame(self)
frame.grid(row=2, column=0, sticky="ew")
frame.columnconfigure(0, weight=1)
frame.columnconfigure(1, weight=1)
button = tk.Button(frame, text="Apply", command=self.destroy)
button.grid(row=0, column=0, sticky="ew")
button = tk.Button(frame, text="Cancel", command=self.click_cancel)
button.grid(row=0, column=1, sticky="ew")
def click_file(self):
file_path = filedialog.askopenfilename(
initialdir=str(ICONS_PATH),
title="Open",
filetypes=(
("images", "*.gif *.jpg *.png *.bmp *pcx *.tga ..."),
("All Files", "*"),
),
)
if file_path:
self.image = Images.create(file_path)
self.image_label.config(image=self.image)
self.file_path.set(file_path)
def click_cancel(self):
self.image = None
self.destroy()

View file

@ -4,7 +4,7 @@ size and scale
import tkinter as tk
from functools import partial
from coretk.setwallpaper import ScaleOption
from coretk.dialogs.setwallpaper import ScaleOption
DRAW_OBJECT_TAGS = ["edge", "node", "nodename", "linkinfo", "antenna"]

View file

@ -5,7 +5,7 @@ wlan configuration
import tkinter as tk
from functools import partial
from coretk.imagemodification import ImageModification
from coretk.dialogs.nodeicon import NodeIconDialog
class WlanConfiguration:
@ -57,16 +57,13 @@ class WlanConfiguration:
e.grid(row=0, column=1, padx=3, pady=3)
b = tk.Button(f, text="None")
b.grid(row=0, column=2, padx=3, pady=3)
b = tk.Button(
f,
image=self.image,
command=lambda: ImageModification(
canvas=self.canvas, canvas_node=self.canvas_node, node_config=self
),
)
b = tk.Button(f, image=self.image, command=lambda: self.click_image)
b.grid(row=0, column=3, padx=3, pady=3)
f.grid(padx=2, pady=2, ipadx=2, ipady=2)
def click_image(self):
NodeIconDialog(self.app, canvas_node=self.canvas_node, node_config=self)
def create_string_var(self, val):
"""
create string variable for convenience

View file

@ -1,91 +0,0 @@
"""
node image modification
"""
import os
import tkinter as tk
from tkinter import filedialog
from PIL import Image, ImageTk
PATH = os.path.abspath(os.path.dirname(__file__))
ICONS_DIR = os.path.join(PATH, "icons")
class ImageModification:
def __init__(self, canvas, canvas_node, node_config):
"""
create an instance of ImageModification
:param coretk.graph.CanvasGraph canvas: canvas object
:param coretk.graph.CanvasNode canvas_node: node object
:param coretk.nodeconfigtable.NodeConfig node_config: node configuration object
"""
self.canvas = canvas
self.image = canvas_node.image
self.node_type = canvas_node.node_type
self.name = canvas_node.name
self.canvas_node = canvas_node
self.node_configuration = node_config
self.p_top = node_config.top
self.top = tk.Toplevel()
self.top.title(self.name + " image")
self.image_modification()
def open_icon_dir(self, toplevel, entry_text):
filename = filedialog.askopenfilename(
initialdir=ICONS_DIR,
title="Open",
filetypes=(
("images", "*.gif *.jpg *.png *.bmp *pcx *.tga ..."),
("All Files", "*"),
),
)
if len(filename) > 0:
img = Image.open(filename)
tk_img = ImageTk.PhotoImage(img)
lb = toplevel.grid_slaves(1, 0)[0]
lb.configure(image=tk_img)
lb.image = tk_img
entry_text.set(filename)
def click_apply(self, toplevel, entry_text):
imgfile = entry_text.get()
if imgfile:
img = Image.open(imgfile)
tk_img = ImageTk.PhotoImage(img)
f = self.p_top.grid_slaves(row=0, column=0)[0]
lb = f.grid_slaves(row=0, column=3)[0]
lb.configure(image=tk_img)
lb.image = tk_img
self.image = tk_img
self.node_configuration.image = tk_img
toplevel.destroy()
def image_modification(self):
f = tk.Frame(self.top)
entry_text = tk.StringVar()
image_file_label = tk.Label(f, text="Image file: ")
image_file_label.grid(row=0, column=0)
image_file_entry = tk.Entry(f, textvariable=entry_text, width=32, bg="white")
image_file_entry.grid(row=0, column=1)
image_file_button = tk.Button(
f, text="...", command=lambda: self.open_icon_dir(self.top, entry_text)
)
image_file_button.grid(row=0, column=2)
f.grid()
img = tk.Label(self.top, image=self.image)
img.grid()
f = tk.Frame(self.top)
apply_button = tk.Button(
f, text="Apply", command=lambda: self.click_apply(self.top, entry_text)
)
apply_button.grid(row=0, column=0)
apply_to_multiple_button = tk.Button(f, text="Apply to multiple...")
apply_to_multiple_button.grid(row=0, column=1)
cancel_button = tk.Button(f, text="Cancel", command=self.top.destroy)
cancel_button.grid(row=0, column=2)
f.grid()

View file

@ -10,6 +10,11 @@ from coretk.appdirs import LOCAL_ICONS_PATH
class Images:
images = {}
@classmethod
def create(cls, file_path):
image = Image.open(file_path)
return ImageTk.PhotoImage(image)
@classmethod
def load_all(cls):
for image in LOCAL_ICONS_PATH.glob("*"):
@ -17,8 +22,7 @@ class Images:
@classmethod
def load(cls, name, file_path):
image = Image.open(file_path)
tk_image = ImageTk.PhotoImage(image)
tk_image = cls.create(file_path)
cls.images[name] = tk_image
@classmethod

View file

@ -11,8 +11,8 @@ from coretk.appdirs import XML_PATH
from coretk.dialogs.hooks import HooksDialog
from coretk.dialogs.sessionoptions import SessionOptionsDialog
from coretk.dialogs.sessions import SessionsDialog
from coretk.setwallpaper import CanvasWallpaper
from coretk.sizeandscale import SizeAndScale
from coretk.dialogs.setwallpaper import CanvasWallpaper
from coretk.dialogs.sizeandscale import SizeAndScale
def sub_menu_items():

View file

@ -1,164 +0,0 @@
"""
Create toplevel for node configuration
"""
import logging
import os
import tkinter as tk
from tkinter import filedialog
from PIL import Image, ImageTk
from coretk.imagemodification import ImageModification
from coretk.nodeservice import NodeServices
PATH = os.path.abspath(os.path.dirname(__file__))
ICONS_DIR = os.path.join(PATH, "icons")
NETWORKNODETYPES = ["switch", "hub", "wlan", "rj45", "tunnel"]
DEFAULTNODES = ["router", "host", "PC"]
class NodeConfig:
def __init__(self, canvas, canvas_node):
"""
create an instance of node configuration
:param coretk.graph.CanvasGraph canvas: canvas object
:param coretk.graph.CanvasNode canvas_node: canvas node object
"""
self.canvas = canvas
self.image = canvas_node.image
self.node_type = canvas_node.node_type
self.name = canvas_node.name
self.canvas_node = canvas_node
self.top = tk.Toplevel()
self.top.title(canvas_node.node_type + " configuration")
self.namevar = tk.StringVar(self.top, value="default name")
self.name_and_image_definition()
self.type_and_service_definition()
self.select_definition()
def open_icon_dir(self, toplevel, entry_text):
filename = filedialog.askopenfilename(
initialdir=ICONS_DIR,
title="Open",
filetypes=(
("images", "*.gif *.jpg *.png *.bmp *pcx *.tga ..."),
("All Files", "*"),
),
)
if len(filename) > 0:
img = Image.open(filename)
tk_img = ImageTk.PhotoImage(img)
lb = toplevel.grid_slaves(1, 0)[0]
lb.configure(image=tk_img)
lb.image = tk_img
entry_text.set(filename)
def click_apply(self, toplevel, entry_text):
imgfile = entry_text.get()
if imgfile:
img = Image.open(imgfile)
tk_img = ImageTk.PhotoImage(img)
lb = self.top.grid_slaves(row=0, column=3)[0]
lb.configure(image=tk_img)
lb.image = tk_img
self.image = tk_img
toplevel.destroy()
def img_modification(self):
t = tk.Toplevel()
t.title(self.name + " image")
f = tk.Frame(t)
entry_text = tk.StringVar()
image_file_label = tk.Label(f, text="Image file: ")
image_file_label.grid(row=0, column=0)
image_file_entry = tk.Entry(f, textvariable=entry_text, width=32, bg="white")
image_file_entry.grid(row=0, column=1)
image_file_button = tk.Button(
f, text="...", command=lambda: self.open_icon_dir(t, entry_text)
)
image_file_button.grid(row=0, column=2)
f.grid()
img = tk.Label(t, image=self.image)
img.grid()
f = tk.Frame(t)
apply_button = tk.Button(
f, text="Apply", command=lambda: self.click_apply(t, entry_text)
)
apply_button.grid(row=0, column=0)
apply_to_multiple_button = tk.Button(f, text="Apply to multiple...")
apply_to_multiple_button.grid(row=0, column=1)
cancel_button = tk.Button(f, text="Cancel", command=t.destroy)
cancel_button.grid(row=0, column=2)
f.grid()
def name_and_image_definition(self):
f = tk.Frame(self.top, bg="#d9d9d9")
name_label = tk.Label(f, text="Node name: ", bg="#d9d9d9")
name_label.grid(padx=2, pady=2)
name_entry = tk.Entry(f, textvariable=self.namevar)
name_entry.grid(row=0, column=1, padx=2, pady=2)
core_button = tk.Button(f, text="None")
core_button.grid(row=0, column=2, padx=2, pady=2)
img_button = tk.Button(
f,
image=self.image,
width=40,
height=40,
command=lambda: ImageModification(self.canvas, self.canvas_node, self),
bg="#d9d9d9",
)
img_button.grid(row=0, column=3, padx=4, pady=4)
f.grid(padx=4, pady=4)
def type_and_service_definition(self):
f = tk.Frame(self.top)
type_label = tk.Label(f, text="Type: ")
type_label.grid(row=0, column=0)
type_button = tk.Button(f, text="None")
type_button.grid(row=0, column=1)
service_button = tk.Button(
f, text="Services...", command=lambda: NodeServices()
)
service_button.grid(row=0, column=2)
f.grid(padx=2, pady=2)
def config_apply(self):
"""
modify image of the canvas node
:return: nothing
"""
logging.debug("nodeconfigtable.py configuration apply")
self.canvas_node.image = self.image
self.canvas_node.canvas.itemconfig(self.canvas_node.id, image=self.image)
self.top.destroy()
def config_cancel(self):
"""
save chosen image but not modify canvas node
:return: nothing
"""
logging.debug("nodeconfigtable.py configuration cancel")
self.canvas_node.image = self.image
self.top.destroy()
def select_definition(self):
f = tk.Frame(self.top)
apply_button = tk.Button(f, text="Apply", command=self.config_apply)
apply_button.grid(row=0, column=0)
cancel_button = tk.Button(f, text="Cancel", command=self.config_cancel)
cancel_button.grid(row=0, column=1)
f.grid()
def network_node_config(self):
self.name_and_image_definition()
self.select_definition()