updated config generation to use config frame where possible

This commit is contained in:
bharnden 2019-11-06 20:49:09 -08:00
parent 9987637564
commit 0147bb9988
3 changed files with 65 additions and 140 deletions

View file

@ -1,99 +0,0 @@
import enum
import logging
import tkinter as tk
from tkinter import ttk
class ConfigType(enum.Enum):
STRING = 10
BOOL = 11
EMANECONFIG = 7
def create_config(master, config, padx=2, pady=2):
"""
Creates a scrollable canvas with an embedded window for displaying configuration
options. Will use grid layout to consume row 0 and columns 0-2.
:param master: master to add scrollable canvas to
:param dict config: config option mapping keys to config options
:param int padx: x padding for widgets
:param int pady: y padding for widgets
:return: widget value mapping
"""
master.rowconfigure(0, weight=1)
master.columnconfigure(0, weight=1)
master.columnconfigure(1, weight=1)
canvas = tk.Canvas(master, highlightthickness=0)
canvas.grid(row=0, columnspan=2, sticky="nsew", padx=padx, pady=pady)
canvas.columnconfigure(0, weight=1)
canvas.rowconfigure(0, weight=1)
scroll_y = tk.Scrollbar(master, orient="vertical", command=canvas.yview)
scroll_y.grid(row=0, column=2, sticky="ns")
frame = tk.Frame(canvas, padx=padx, pady=pady)
frame.columnconfigure(0, weight=1)
frame.columnconfigure(1, weight=3)
values = {}
for index, key in enumerate(sorted(config)):
option = config[key]
label = tk.Label(frame, text=option.label)
label.grid(row=index, pady=pady, padx=padx, sticky="ew")
value = tk.StringVar()
config_type = ConfigType(option.type)
if config_type == ConfigType.BOOL:
select = tuple(option.select)
combobox = ttk.Combobox(frame, textvariable=value, values=select)
combobox.grid(row=index, column=1, sticky="ew", pady=pady)
if option.value == "1":
value.set("On")
else:
value.set("Off")
elif config_type == ConfigType.STRING:
value.set(option.value)
entry = tk.Entry(frame, textvariable=value)
entry.grid(row=index, column=1, sticky="ew", pady=pady)
elif config_type == ConfigType.EMANECONFIG:
value.set(option.value)
entry = tk.Entry(frame, textvariable=value, bg="white")
entry.grid(row=index, column=1, sticky="ew", pady=pady)
else:
logging.error("unhandled config option type: %s", config_type)
values[key] = value
frame_id = canvas.create_window(0, 0, anchor="nw", window=frame)
canvas.update_idletasks()
canvas.configure(scrollregion=canvas.bbox("all"), yscrollcommand=scroll_y.set)
frame.bind(
"<Configure>", lambda event: canvas.configure(scrollregion=canvas.bbox("all"))
)
canvas.bind(
"<Configure>", lambda event: canvas.itemconfig(frame_id, width=event.width)
)
return values
def parse_config(options, values):
"""
Given a set of configurations, parse out values and transform them when needed.
:param dict options: option key mapping to configuration options
:param dict values: option key mapping to widget values
:return: nothing
"""
for key in options:
option = options[key]
value = values[key]
config_type = ConfigType(option.type)
config_value = value.get()
if config_type == ConfigType.BOOL:
if config_value == "On":
option.value = "1"
else:
option.value = "0"
else:
option.value = config_value

View file

@ -7,9 +7,9 @@ import tkinter as tk
import webbrowser import webbrowser
from tkinter import ttk from tkinter import ttk
from coretk import configutils
from coretk.dialogs.dialog import Dialog from coretk.dialogs.dialog import Dialog
from coretk.images import ImageEnum, Images from coretk.images import ImageEnum, Images
from coretk.widgets import ConfigFrame
PAD_X = 2 PAD_X = 2
PAD_Y = 2 PAD_Y = 2
@ -38,10 +38,10 @@ class EmaneConfiguration(Dialog):
self.emane_options() self.emane_options()
self.draw_apply_and_cancel() self.draw_apply_and_cancel()
self.values = None self.emane_config_frame = None
self.options = app.core.emane_config self.options = app.core.emane_config
self.model_options = None self.model_options = None
self.model_values = None self.model_config_frame = None
def create_text_variable(self, val): def create_text_variable(self, val):
""" """
@ -75,7 +75,7 @@ class EmaneConfiguration(Dialog):
f.grid(row=0, column=0, sticky="nsew") f.grid(row=0, column=0, sticky="nsew")
def save_emane_option(self): def save_emane_option(self):
configutils.parse_config(self.options, self.values) self.emane_config_frame.parse_config()
self.emane_dialog.destroy() self.emane_dialog.destroy()
def draw_emane_options(self): def draw_emane_options(self):
@ -83,10 +83,6 @@ class EmaneConfiguration(Dialog):
self.emane_dialog = Dialog( self.emane_dialog = Dialog(
self, self.app, "emane configuration", modal=False self, self.app, "emane configuration", modal=False
) )
b1 = tk.Button(self.emane_dialog, text="Appy", command=self.save_emane_option)
b2 = tk.Button(
self.emane_dialog, text="Cancel", command=self.emane_dialog.destroy
)
if self.options is None: if self.options is None:
session_id = self.app.core.session_id session_id = self.app.core.session_id
@ -94,11 +90,20 @@ class EmaneConfiguration(Dialog):
logging.info("emane config: %s", response) logging.info("emane config: %s", response)
self.options = response.config self.options = response.config
self.values = configutils.create_config( self.emane_dialog.columnconfigure(0, weight=1)
self.emane_dialog, self.options, PAD_X, PAD_Y self.emane_dialog.rowconfigure(0, weight=1)
) self.emane_config_frame = ConfigFrame(self.emane_dialog, config=self.options)
b1.grid(row=1, column=0) self.emane_config_frame.draw_config()
b2.grid(row=1, column=1) self.emane_config_frame.grid(sticky="nsew")
frame = tk.Frame(self.emane_dialog)
frame.grid(sticky="ew")
for i in range(2):
frame.columnconfigure(i, weight=1)
b1 = tk.Button(frame, text="Appy", command=self.save_emane_option)
b1.grid(row=0, column=0, sticky="ew")
b2 = tk.Button(frame, text="Cancel", command=self.emane_dialog.destroy)
b2.grid(row=0, column=1, sticky="ew")
self.emane_dialog.show() self.emane_dialog.show()
def save_emane_model_options(self): def save_emane_model_options(self):
@ -111,8 +116,7 @@ class EmaneConfiguration(Dialog):
model_name = self.emane_models[self.emane_model_combobox.current()] model_name = self.emane_models[self.emane_model_combobox.current()]
# parse configuration # parse configuration
configutils.parse_config(self.model_options, self.model_values) config = self.model_config_frame.parse_config()
config = {x: self.model_options[x].value for x in self.model_options}
# add string emane_ infront for grpc call # add string emane_ infront for grpc call
response = self.app.core.client.set_emane_model_config( response = self.app.core.client.set_emane_model_config(
@ -141,17 +145,10 @@ class EmaneConfiguration(Dialog):
# create the dialog and the necessry widget # create the dialog and the necessry widget
if not self.emane_model_dialog or not self.emane_model_dialog.winfo_exists(): if not self.emane_model_dialog or not self.emane_model_dialog.winfo_exists():
self.emane_model_dialog = Dialog( self.emane_model_dialog = Dialog(
self, self.app, model_name + " configuration", modal=False self, self.app, f"{model_name} configuration", modal=False
) )
self.emane_model_dialog.columnconfigure(0, weight=1)
b1 = tk.Button( self.emane_model_dialog.rowconfigure(0, weight=1)
self.emane_model_dialog, text="Apply", command=self.save_emane_model_options
)
b2 = tk.Button(
self.emane_model_dialog,
text="Cancel",
command=self.emane_model_dialog.destroy,
)
# query for configurations # query for configurations
session_id = self.app.core.session_id session_id = self.app.core.session_id
@ -162,12 +159,20 @@ class EmaneConfiguration(Dialog):
logging.info("emane model config %s", response) logging.info("emane model config %s", response)
self.model_options = response.config self.model_options = response.config
self.model_values = configutils.create_config( self.model_config_frame = ConfigFrame(
self.emane_model_dialog, self.model_options, PAD_X, PAD_Y self.emane_model_dialog, config=self.model_options
) )
self.model_config_frame.grid(sticky="nsew")
self.model_config_frame.draw_config()
b1.grid(row=1, column=0, sticky="nsew") frame = tk.Frame(self.emane_model_dialog)
b2.grid(row=1, column=1, sticky="nsew") frame.grid(sticky="ew")
for i in range(2):
frame.columnconfigure(i, weight=1)
b1 = tk.Button(frame, text="Apply", command=self.save_emane_model_options)
b1.grid(row=0, column=0, sticky="ew")
b2 = tk.Button(frame, text="Cancel", command=self.emane_model_dialog.destroy)
b2.grid(row=0, column=1, sticky="ew")
self.emane_model_dialog.show() self.emane_model_dialog.show()
def draw_option_buttons(self, parent): def draw_option_buttons(self, parent):

View file

@ -3,7 +3,18 @@ import tkinter as tk
from functools import partial from functools import partial
from tkinter import ttk from tkinter import ttk
from coretk.configutils import ConfigType from core.api.grpc import core_pb2
INT_TYPES = {
core_pb2.ConfigOptionType.UINT8,
core_pb2.ConfigOptionType.UINT16,
core_pb2.ConfigOptionType.UINT32,
core_pb2.ConfigOptionType.UINT64,
core_pb2.ConfigOptionType.INT8,
core_pb2.ConfigOptionType.INT16,
core_pb2.ConfigOptionType.INT32,
core_pb2.ConfigOptionType.INT64,
}
class FrameScroll(tk.LabelFrame): class FrameScroll(tk.LabelFrame):
@ -30,11 +41,8 @@ class FrameScroll(tk.LabelFrame):
def _configure_frame(self, event): def _configure_frame(self, event):
req_width = self.frame.winfo_reqwidth() req_width = self.frame.winfo_reqwidth()
req_height = self.frame.winfo_reqheight()
if req_width != self.canvas.winfo_reqwidth(): if req_width != self.canvas.winfo_reqwidth():
self.canvas.configure(width=req_width) self.canvas.configure(width=req_width)
if req_height != self.canvas.winfo_reqheight():
self.canvas.configure(height=req_height)
self.canvas.configure(scrollregion=self.canvas.bbox("all")) self.canvas.configure(scrollregion=self.canvas.bbox("all"))
def _configure_canvas(self, event): def _configure_canvas(self, event):
@ -68,34 +76,45 @@ class ConfigFrame(FrameScroll):
label = tk.Label(self.frame, text=option.label) label = tk.Label(self.frame, text=option.label)
label.grid(row=index, pady=pady, padx=padx, sticky="w") label.grid(row=index, pady=pady, padx=padx, sticky="w")
value = tk.StringVar() value = tk.StringVar()
config_type = ConfigType(option.type) if option.type == core_pb2.ConfigOptionType.BOOL:
if config_type == ConfigType.BOOL:
select = tuple(option.select) select = tuple(option.select)
combobox = ttk.Combobox(self.frame, textvariable=value, values=select) combobox = ttk.Combobox(
self.frame, textvariable=value, values=select, state="readonly"
)
combobox.grid(row=index, column=1, sticky="ew", pady=pady) combobox.grid(row=index, column=1, sticky="ew", pady=pady)
if option.value == "1": if option.value == "1":
value.set("On") value.set("On")
else: else:
value.set("Off") value.set("Off")
elif config_type == ConfigType.STRING: elif option.select:
value.set(option.value)
select = tuple(option.select)
combobox = ttk.Combobox(
self.frame, textvariable=value, values=select, state="readonly"
)
combobox.grid(row=index, column=1, sticky="ew", pady=pady)
elif option.type == core_pb2.ConfigOptionType.STRING:
value.set(option.value) value.set(option.value)
entry = tk.Entry(self.frame, textvariable=value) entry = tk.Entry(self.frame, textvariable=value)
entry.grid(row=index, column=1, sticky="ew", pady=pady) entry.grid(row=index, column=1, sticky="ew", pady=pady)
elif config_type == ConfigType.EMANECONFIG: elif option.type in INT_TYPES:
value.set(option.value)
entry = tk.Entry(self.frame, textvariable=value)
entry.grid(row=index, column=1, sticky="ew", pady=pady)
elif option.type == core_pb2.ConfigOptionType.FLOAT:
value.set(option.value) value.set(option.value)
entry = tk.Entry(self.frame, textvariable=value) entry = tk.Entry(self.frame, textvariable=value)
entry.grid(row=index, column=1, sticky="ew", pady=pady) entry.grid(row=index, column=1, sticky="ew", pady=pady)
else: else:
logging.error("unhandled config option type: %s", config_type) logging.error("unhandled config option type: %s", option.type)
self.values[key] = value self.values[key] = value
def parse_config(self): def parse_config(self):
for key in self.config: for key in self.config:
option = self.config[key] option = self.config[key]
value = self.values[key] value = self.values[key]
config_type = ConfigType(option.type)
config_value = value.get() config_value = value.get()
if config_type == ConfigType.BOOL: if option.type == core_pb2.ConfigOptionType.BOOL:
if config_value == "On": if config_value == "On":
option.value = "1" option.value = "1"
else: else: