"""
Frontend Libraries Page File for AGE-ABM Visual Interface
@Author Meghan Ireland
@Co-Authors Max Hall and Matthew Fleischman
"""
import tkinter as tk
from tkinter import ttk
import customtkinter
[docs]
class Libraries:
"""This class defines a libraries page
"""
def __init__(self, ec_app_ui):
"""Defines the variables and widgets for libraries page.
"""
self.ec_app_ui = ec_app_ui
self.selected_library = ""
self.gridworld = tk.BooleanVar()
### Label frames ###
self.labelframe_libraries_details = tk.LabelFrame(self.ec_app_ui.page_frame
, font=self.ec_app_ui.font2, text="Extras from ECAgent"
, height = self.ec_app_ui.entry_height*2
, width = 3*self.ec_app_ui.button_width//2 + 20, bg=self.ec_app_ui.frame_colour
, fg = "white")
### Frame ###
self.frame_small = tk.Frame(master = self.ec_app_ui.page_frame, bg=self.ec_app_ui.frame_colour
, height = self.ec_app_ui.button_height
, width = 3*self.ec_app_ui.button_width//2)
### Labels ###
self.label_libraries_name = tk.Label(self.ec_app_ui.page_frame, text="Library:",
font=self.ec_app_ui.font2, justify="left",bg=self.ec_app_ui.frame_colour,
fg=self.ec_app_ui.label_text_colour)
self.label_libraries_nickname = tk.Label(self.ec_app_ui.page_frame, text="Nickname:",
font=self.ec_app_ui.font2, justify="left",bg=self.ec_app_ui.frame_colour,
fg=self.ec_app_ui.label_text_colour)
self.label_libraries_type = tk.Label(self.ec_app_ui.page_frame, text="Import Type:",
font=self.ec_app_ui.font2, justify="left",bg=self.ec_app_ui.frame_colour,
fg=self.ec_app_ui.label_text_colour)
self.label_libraries_methods = tk.Label(self.ec_app_ui.page_frame,
text="Comma Seperated List of Methods:",
font=self.ec_app_ui.font2, justify="left",bg=self.ec_app_ui.frame_colour,
fg=self.ec_app_ui.label_text_colour)
### Entry ###
self.entry_libraries_name = customtkinter.CTkEntry(self.ec_app_ui.page_frame
, font = self.ec_app_ui.font2, height=self.ec_app_ui.entry_height
, width = self.ec_app_ui.entry_width, fg_color = self.ec_app_ui.entry_colour
, text_color = self.ec_app_ui.entry_text_colour)
self.entry_libraries_nickname = customtkinter.CTkEntry(self.ec_app_ui.page_frame
, font = self.ec_app_ui.font2, height=self.ec_app_ui.entry_height
, width = self.ec_app_ui.entry_width, fg_color = self.ec_app_ui.entry_colour
, text_color = self.ec_app_ui.entry_text_colour)
self.entry_libraries_methods = customtkinter.CTkTextbox(self.ec_app_ui.page_frame
, font = self.ec_app_ui.font2, height=2*self.ec_app_ui.entry_height
, fg_color = self.ec_app_ui.entry_colour, width = self.ec_app_ui.entry_width
, text_color = self.ec_app_ui.entry_text_colour)
### Dropdowns ###
self.dropdown_libraries_type = customtkinter.CTkOptionMenu(self.ec_app_ui.page_frame
, values = ["as", "from", "*"], button_hover_color= self.ec_app_ui.highlight_colour
, fg_color = self.ec_app_ui.dropdown_menu_color
, button_color=self.ec_app_ui.comp_btn_colour, height = self.ec_app_ui.entry_height
, width=self.ec_app_ui.entry_width, font = self.ec_app_ui.font2
, command = self.on_user_click)
### Buttons ###
self.button_libraries_add = customtkinter.CTkButton(self.frame_small
, hover_color=self.ec_app_ui.highlight_colour, text="Add"
, command=self.btn_libraries_add,fg_color=self.ec_app_ui.comp_btn_colour
, font = self.ec_app_ui.font2, height=self.ec_app_ui.button_height
, width=self.ec_app_ui.button_width/2)
self.button_libraries_edit = customtkinter.CTkButton(self.frame_small
, hover_color=self.ec_app_ui.highlight_colour, text="Edit"
, command=self.btn_libraries_edit, fg_color=self.ec_app_ui.comp_btn_colour
, font = self.ec_app_ui.font2, height=self.ec_app_ui.button_height
, width=self.ec_app_ui.button_width/2)
self.button_libraries_remove = customtkinter.CTkButton(self.frame_small
, hover_color=self.ec_app_ui.highlight_colour, text="Remove"
, command=self.btn_libraries_remove, fg_color=self.ec_app_ui.comp_btn_colour
, font = self.ec_app_ui.font2, height=self.ec_app_ui.button_height
, width=self.ec_app_ui.button_width/2)
self.button_libraries_save = customtkinter.CTkButton(self.ec_app_ui.page_frame
, hover_color=self.ec_app_ui.highlight_colour, text="Save Library"
, command=self.btn_libraries_save, fg_color=self.ec_app_ui.comp_btn_colour
, font = self.ec_app_ui.font2,height = self.ec_app_ui.button_height
, width = self.ec_app_ui.entry_width)
self.button_libraries_save_edit= customtkinter.CTkButton(self.ec_app_ui.page_frame
, hover_color=self.ec_app_ui.highlight_colour, text="Save Library"
, command=self.btn_libraries_save_edit, fg_color=self.ec_app_ui.comp_btn_colour
, font = self.ec_app_ui.font2,height = self.ec_app_ui.button_height
, width = self.ec_app_ui.entry_width)
### Check Boxes ###
self.checkbox_libraries_gridworld = customtkinter.CTkCheckBox(self.labelframe_libraries_details
, border_color=self.ec_app_ui.tbl_colour, command=self.on_tick_gridworld
, hover_color=self.ec_app_ui.highlight_colour
, text_color = self.ec_app_ui.button_font_colour, font = self.ec_app_ui.font2
, variable=self.gridworld, text = "GridWorld", fg_color = self.ec_app_ui.check_color)
### Table for Libraries ###
ttk.Style().configure("Treeview", background=self.ec_app_ui.tbl_colour
, foreground=self.ec_app_ui.tbl_font_colour)
self.lib_frame = customtkinter.CTkFrame(self.ec_app_ui.page_frame
, fg_color=self.ec_app_ui.tbl_colour, height = 300
, width = 3*self.ec_app_ui.button_width//2)
self.vertical_scroll = tk.Scrollbar(self.lib_frame)
self.lib_tbl = ttk.Treeview(self.lib_frame,padding = 5,height = 8
, yscrollcommand=self.vertical_scroll.set)
### Titles ###
self.lib_title = tk.Label(self.ec_app_ui.title_frame, text="Libraries to Import"
, font=self.ec_app_ui.font1, fg=self.ec_app_ui.label_text_colour
, bg=self.ec_app_ui.title_colour)
self.lib_title_add = tk.Label(self.ec_app_ui.title_frame, text="Add Import"
, font=self.ec_app_ui.font1, fg=self.ec_app_ui.label_text_colour
, bg=self.ec_app_ui.title_colour)
self.lib_title_edit = tk.Label(self.ec_app_ui.title_frame, text="Edit Import"
, font=self.ec_app_ui.font1, fg=self.ec_app_ui.label_text_colour
, bg=self.ec_app_ui.title_colour)
# The code below sets up the table for libraries
self.lib_tbl['columns'] = ('Name', 'Nickname')
self.lib_tbl.column("#0", width=0, stretch='NO')
self.lib_tbl.column("Name",anchor='center', width=285)
self.lib_tbl.column("Nickname",anchor='center',width=285)
self.lib_tbl.heading("#0",text="",anchor='center')
self.lib_tbl.heading("Name",text="Name",anchor='center')
self.lib_tbl.heading("Nickname",text="Nickname",anchor='center')
self.lib_tbl.bind("<<TreeviewSelect>>", self.display_selected_library)
[docs]
def clear_lib(self):
"""Clears the libtraries page.
"""
self.lib_frame.grid_forget()
self.lib_tbl.pack_forget()
self.lib_title.grid_forget()
self.entry_libraries_name.grid_forget()
self.entry_libraries_nickname.grid_forget()
self.entry_libraries_methods.grid_forget()
self.dropdown_libraries_type.grid_forget()
self.label_libraries_name.grid_forget()
self.label_libraries_nickname.grid_forget()
self.label_libraries_type.grid_forget()
self.label_libraries_methods.grid_forget()
self.button_libraries_add.grid_forget()
self.button_libraries_edit.grid_forget()
self.button_libraries_remove.grid_forget()
self.button_libraries_save.grid_forget()
self.button_libraries_save_edit.grid_forget()
self.labelframe_libraries_details.grid_forget()
self.frame_small.grid_forget()
self.lib_title_add.grid_forget()
self.lib_title_edit.grid_forget()
[docs]
def libraries_tab_btn(self):
"""Places widgets when user opens library page.
"""
self.selected_library = ""
self.ec_app_ui.clear_all()
if self.ec_app_ui.new_model.get_model_details().get_gridworld():
self.checkbox_libraries_gridworld.select()
else:
self.checkbox_libraries_gridworld.deselect()
self.lib_title.grid(row = self.ec_app_ui.title_position_row
, column = self.ec_app_ui.title_position_column
, pady=self.ec_app_ui.title_position_pady
, padx = self.ec_app_ui.title_position_padx)
### Clear all entries ###
self.entry_libraries_name.delete(0, 'end')
self.entry_libraries_nickname.delete(0, 'end')
self.entry_libraries_methods.delete("1.0", 'end-1c')
### Options ###
self.labelframe_libraries_details.grid(row = 0, column = 0, columnspan=3,pady = 5)
self.labelframe_libraries_details.grid_propagate(0)
self.checkbox_libraries_gridworld.grid(row = 0, column = 0, padx = 5, sticky = "W"
, pady = 5)
### Fill Table ###
self.update_tbl()
### Add, edit, remove buttons ###
self.frame_small.grid(row=2, column = 0, columnspan=3,pady = 5)
self.button_libraries_add.grid(row = 0,column = 0,padx = 5)
self.button_libraries_edit.grid(row = 0, column = 1,padx = 5)
self.button_libraries_remove.grid(row = 0, column = 2,padx = 5)
[docs]
def btn_libraries_add(self):
"""Allows user to add a library.
"""
self.ec_app_ui.clear_all()
self.lib_title_add.grid(row = 0, column = 0)
### Library Name ###
self.label_libraries_name.grid(row = 0, column = 0,padx = (150,200),pady = 5,sticky="W")
self.entry_libraries_name.grid(row = 0, column = 1,pady = 5)
### Nickname ###
self.label_libraries_nickname.grid(row = 1, column = 0, padx = (150,200), pady = 5
, sticky="W")
self.entry_libraries_nickname.grid(row = 1, column = 1, pady = 5)
self.dropdown_libraries_type.set("*")
### Type ###
self.label_libraries_type.grid(row = 2, column = 0, padx = (150,200), pady = 5, sticky="W")
self.dropdown_libraries_type.grid(row = 2, column = 1, pady = 5)
### Save ###
self.button_libraries_save.grid(row = 4, column = 1, pady = 5)
[docs]
def btn_libraries_edit(self):
"""Allows user to edit a library.
"""
if self.selected_library != "":
self.ec_app_ui.clear_all()
self.lib_title_edit.grid(row = 0, column = 0)
### Library Name ###
self.entry_libraries_name.insert(0, self.selected_library)
self.label_libraries_name.grid(row = 0, column = 0,padx = (150,200),pady = 5,sticky="W")
self.entry_libraries_name.grid(row = 0, column = 1,pady = 5)
### Nickname ###
nickname = self.ec_app_ui.new_model.get_import(self.selected_library).get_nickname()
self.entry_libraries_nickname.insert(0, nickname)
self.label_libraries_nickname.grid(row = 1, column = 0, padx = (150,200), pady = 5
, sticky="W")
self.entry_libraries_nickname.grid(row = 1, column = 1, pady = 5)
type_import = self.ec_app_ui.new_model.get_import(self.selected_library).get_import_type()
self.dropdown_libraries_type.set(type_import)
if self.dropdown_libraries_type.get() == "from":
self.entry_libraries_methods.delete("1.0", 'end-1c')
methods = self.ec_app_ui.new_model.get_import(self.selected_library).get_list_of_methods()
methods = ",".join([str(method) for method in methods])
self.entry_libraries_methods.insert("1.0", methods)
self.label_libraries_methods.grid(row = 3, column = 0, padx = (150,0)
, pady = 5, sticky="W")
self.entry_libraries_methods.grid(row = 3, column = 1, pady = 5)
### Type ###
self.label_libraries_type.grid(row = 2, column = 0, padx = (150,200), pady = 5, sticky="W")
self.dropdown_libraries_type.grid(row = 2, column = 1, pady = 5)
### Save ###
self.button_libraries_save_edit.grid(row = 4, column = 1, pady = 5)
[docs]
def btn_libraries_remove(self):
"""Allows user to remove a library.
"""
self.ec_app_ui.new_model.remove_import(self.selected_library)
self.update_tbl()
[docs]
def on_user_click(self, *args):
"""Checks what selected type is.
"""
if self.dropdown_libraries_type.get() == "from":
self.entry_libraries_methods.delete("1.0", 'end-1c')
self.label_libraries_methods.grid(row = 3, column = 0, padx = (150,0), pady = 5
, sticky="W")
self.entry_libraries_methods.grid(row = 3, column = 1, pady = 5)
else:
self.label_libraries_methods.grid_forget()
self.entry_libraries_methods.grid_forget()
[docs]
def btn_libraries_save(self):
"""Saves the library to the backend.
"""
if self.dropdown_libraries_type.get() == "from":
list_of_methods = self.entry_libraries_methods.get("1.0", 'end-1c')
list_of_methods = list_of_methods.replace(" , ", ",")
list_of_methods = list_of_methods.replace(", ", ",")
list_of_methods = list_of_methods.replace(" ,", ",")
list_of_methods = list_of_methods.split(",")
self.ec_app_ui.new_model.add_import(self.entry_libraries_name.get(),
self.entry_libraries_nickname.get(), self.dropdown_libraries_type.get(),
list_of_methods)
else:
self.ec_app_ui.new_model.add_import(self.entry_libraries_name.get(),
self.entry_libraries_nickname.get(), self.dropdown_libraries_type.get())
self.libraries_tab_btn()
[docs]
def btn_libraries_save_edit(self):
"""Saves the edited library to the backend.
"""
if self.dropdown_libraries_type.get() == "from":
list_of_methods = self.entry_libraries_methods.get("1.0", 'end-1c')
list_of_methods = list_of_methods.replace(" , ", ",")
list_of_methods = list_of_methods.replace(", ", ",")
list_of_methods = list_of_methods.replace(" ,", ",")
list_of_methods = list_of_methods.split(",")
self.ec_app_ui.new_model.edit_import(self.selected_library
, self.entry_libraries_nickname.get()
, self.dropdown_libraries_type.get()
, list_of_methods)
else:
self.ec_app_ui.new_model.edit_import(self.selected_library
, self.entry_libraries_nickname.get()
, self.dropdown_libraries_type.get())
self.libraries_tab_btn()
[docs]
def display_selected_library(self, *args):
"""Saves the component the user clicked on.
"""
selected_items = self.lib_tbl.selection()
if selected_items:
selected_item = self.lib_tbl.selection()[0]
self.selected_library = self.lib_tbl.item(selected_item)['values'][0]
[docs]
def update_tbl(self):
"""Fills table
"""
### Fill Table ###
id3 = 0
list_of_imports = self.ec_app_ui.new_model.get_list_imports()
self.lib_frame.grid(row = 1, column = 0, columnspan=3)
self.vertical_scroll.pack(side="right", fill="y", padx=(0,5), pady=5)
self.lib_tbl.pack(padx = (5,0), pady = 5)
for lib in self.lib_tbl.get_children():
self.lib_tbl.delete(lib)
for name in list_of_imports:
nickname = self.ec_app_ui.new_model.get_import(name).get_nickname()
self.lib_tbl.insert(parent='',index='end',iid=id3,text='',values=[name, nickname])
id3+=1
[docs]
def on_tick_gridworld(self, *args):
"""When Grid World is clicked
"""
if self.checkbox_libraries_gridworld.get():
self.ec_app_ui.new_model.edit_model_details(gridworld = True)
self.update_tbl()
else:
self.ec_app_ui.new_model.edit_model_details(gridworld = False)
self.update_tbl()