"""
Frontend Edit Attributes 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 EditAttributes:
"""The class which is responsible for the look and workings of the edit_attributes page.
"""
def __init__(self, ec_app_ui):
"""Creates all variables and widgets for the edit_attributes page.
"""
self.ec_app_ui = ec_app_ui
self.current_component = ""
self.user_value_edit_attribute = tk.BooleanVar()
self.primitive_types = ["int", "float", "bool"]
self.selected_primitive_ea = tk.StringVar()
self.selected_primitive_ea.set(self.primitive_types[0])
self.selected_level = tk.StringVar()
self.selected_attribute = None
### Frames ###
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_edit_attributes_name = tk.Label(self.ec_app_ui.page_frame,text="Attribute Name:"
, 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_edit_attributes_type = tk.Label(self.ec_app_ui.page_frame,text="Attribute 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_edit_attributes_default = tk.Label(self.ec_app_ui.page_frame
, text="Attribute Default Value:", 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_edit_attributes_component_name = tk.Label(self.ec_app_ui.page_frame
, text="Select Component:",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_edit_attributes_layer = tk.Label(self.ec_app_ui.page_frame,
text="At which layer:",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_edit_attributes_default = customtkinter.CTkTextbox(self.ec_app_ui.page_frame
, font = self.ec_app_ui.font2, height=4*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)
self.entry_edit_attribute_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)
### Combobox ###
self.dropdown_edit_attributes_components = customtkinter.CTkOptionMenu(self.ec_app_ui.page_frame
, values = [], 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
, button_hover_color= self.ec_app_ui.highlight_colour, width=self.ec_app_ui.entry_width
, font = self.ec_app_ui.font2, command = self.selected_comp_attr)
self.dropdown_edit_attributes_components.set("Select Component")
self.dropdown_edit_attributes_attribute_type = customtkinter.CTkOptionMenu(self.ec_app_ui.page_frame
, button_hover_color= self.ec_app_ui.highlight_colour
, variable = self.selected_primitive_ea, values=self.primitive_types
, 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)
self.dropdown_edit_attributes_layer = customtkinter.CTkOptionMenu(self.ec_app_ui.page_frame
, variable = self.selected_level
, values = ["Component Layer", "Agent Layer", "Model Layer"]
, fg_color = self.ec_app_ui.dropdown_menu_color
, button_color=self.ec_app_ui.comp_btn_colour
, button_hover_color= self.ec_app_ui.highlight_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_edit_attributes_edit = customtkinter.CTkButton(self.frame_small
, hover_color=self.ec_app_ui.highlight_colour, text="Edit"
, command=self.btn_edit_attributes_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.btn_comp_width)
self.button_edit_attributes_remove = customtkinter.CTkButton(self.frame_small
, hover_color=self.ec_app_ui.highlight_colour, text="Remove"
, command=self.btn_edit_attributes_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.btn_comp_width)
self.button_edit_attributes_save = customtkinter.CTkButton(self.ec_app_ui.page_frame
, hover_color=self.ec_app_ui.highlight_colour, text="Save Attribute"
, command=self.btn_edit_attributes_save, fg_color=self.ec_app_ui.comp_btn_colour
, font = self.ec_app_ui.font2, height = self.ec_app_ui.entry_height
, width=self.ec_app_ui.entry_width)
### Titles ###
self.label_edit_attributes_title = tk.Label(self.ec_app_ui.title_frame
,text="Edit Attributes", font=self.ec_app_ui.font1, justify="left"
,bg=self.ec_app_ui.title_colour, fg=self.ec_app_ui.label_text_colour)
### Table for Attributes ###
ttk.Style().configure("Treeview", background=self.ec_app_ui.tbl_colour
, foreground=self.ec_app_ui.tbl_font_colour)
self.attr_frame = customtkinter.CTkFrame(self.ec_app_ui.page_frame
, fg_color=self.ec_app_ui.tbl_colour
, height = 80
, width = self.ec_app_ui.window_width/4)
self.attr_frame.grid_propagate(0)
self.vertical_scroll = tk.Scrollbar(self.attr_frame)
self.attr_tbl = ttk.Treeview(self.attr_frame,padding = 5,height = 5
, yscrollcommand=self.vertical_scroll.set)
# The code below sets up the table for attributes
self.attr_tbl['columns'] = 'Name'
self.attr_tbl.column("#0", width=0, stretch='NO')
self.attr_tbl.column("Name",anchor='center', width=self.ec_app_ui.btn_comp_width*3+5)
self.attr_tbl.heading("#0",text="",anchor='center')
self.attr_tbl.heading("Name",text="Attributes",anchor='center')
self.attr_tbl.bind("<<TreeviewSelect>>", self.display_selected_attribute)
[docs]
def clear_individual_attribute(self):
"""Clears the editing of attribute widgets
"""
self.dropdown_edit_attributes_attribute_type.grid_forget()
self.label_edit_attributes_name.grid_forget()
self.entry_edit_attribute_name.grid_forget()
self.label_edit_attributes_type.grid_forget()
self.label_edit_attributes_default.grid_forget()
self.entry_edit_attributes_default.grid_forget()
self.button_edit_attributes_save.grid_forget()
self.label_edit_attributes_layer.grid_forget()
self.dropdown_edit_attributes_layer.grid_forget()
[docs]
def clear_edit_attributes(self):
"""Clears the tab as a whole
"""
self.attr_frame.grid_forget()
self.attr_tbl.pack_forget()
self.label_edit_attributes_component_name.grid_forget()
self.dropdown_edit_attributes_components.grid_forget()
self.button_edit_attributes_edit.grid_forget()
self.button_edit_attributes_remove.grid_forget()
self.label_edit_attributes_title.grid_forget()
self.clear_individual_attribute()
self.frame_small.grid_forget()
[docs]
def on_user_click(self, *args):
"""When user selects the combo box
"""
att_vals = self.ec_app_ui.new_model.get_attribute(str(self.current_component)
, str(self.selected_attribute))
level = att_vals.get_define_level()
if self.dropdown_edit_attributes_layer.get() == "Component Layer" and level == "comp_lvl":
self.entry_edit_attributes_default.delete("1.0", 'end-1c')
default = self.ec_app_ui.new_model.get_attribute(self.current_component
, self.selected_attribute).get_default_value()
if default == {}:
default = ""
self.entry_edit_attributes_default.insert("1.0", default)
self.label_edit_attributes_default.grid(row = 3, column = 0, padx = 150, pady = 5
, sticky="W")
self.entry_edit_attributes_default.grid(row = 3, column = 1, pady = 5)
elif self.dropdown_edit_attributes_layer.get() == "Component Layer" and level != "comp_lvl":
self.entry_edit_attributes_default.delete("1.0", 'end-1c')
default = ""
self.entry_edit_attributes_default.insert("1.0", default)
self.label_edit_attributes_default.grid(row = 3, column = 0, padx = 150, pady = 5
, sticky="W")
self.entry_edit_attributes_default.grid(row = 3, column = 1, pady = 5)
else:
self.label_edit_attributes_default.grid_forget()
self.entry_edit_attributes_default.grid_forget()
[docs]
def edit_attribute_tab_btn(self):
"""Places all wigets on the page
"""
self.ec_app_ui.clear_all()
self.button_edit_attributes_edit.grid_forget()
self.button_edit_attributes_remove.grid_forget()
self.label_edit_attributes_title.grid(row = 0, column = 0)
self.dropdown_edit_attributes_components.configure(self
,values = self.ec_app_ui.new_model.get_list_components())
self.label_edit_attributes_component_name.grid(row = 0, column = 0, padx = (100,0)
, pady = 5)
self.dropdown_edit_attributes_components.grid(row = 0, column = 2, pady = 5, sticky = "W")
self.dropdown_edit_attributes_components.set("Select Component")
[docs]
def btn_edit_attributes_edit(self):
"""Fills in known information about the attribute.
"""
if self.selected_attribute != "":
self.ec_app_ui.clear_all()
self.label_edit_attributes_title.grid(row = 0, column = 0)
self.button_edit_attributes_edit.grid_forget()
self.button_edit_attributes_remove.grid_forget()
att_vals = self.ec_app_ui.new_model.get_attribute(str(self.current_component)
, str(self.selected_attribute))
### Attribute name ###
self.label_edit_attributes_name.grid(row = 0, column = 0,padx = 150,pady = 5,sticky="W")
self.entry_edit_attribute_name.grid(row = 0, column = 1,pady = 5)
self.entry_edit_attribute_name.insert(0, self.selected_attribute)
self.entry_edit_attribute_name.configure(state= "disabled")
### Set Attribute Type ###
self.selected_primitive_ea.set(att_vals.get_type_attr())
### Set the level as what it was defined as ###
level = att_vals.get_define_level()
if level == "comp_lvl":
level = "Component Layer"
self.entry_edit_attributes_default.delete("1.0", 'end-1c')
default = self.ec_app_ui.new_model.get_attribute(self.current_component
, self.selected_attribute).get_default_value()
if default == {}:
default = ""
self.entry_edit_attributes_default.insert("1.0", default)
self.label_edit_attributes_default.grid(row = 3, column = 0, padx = 150, pady = 5
, sticky="W")
self.entry_edit_attributes_default.grid(row = 3, column = 1, pady = 5)
elif level == "model_lvl":
level = "Model Layer"
elif level == "agent_lvl":
level = "Agent Layer"
self.selected_level.set(level)
### Attribute type ###
self.label_edit_attributes_type.grid(row = 1, column = 0,padx = 150, pady = 5, sticky="W")
self.dropdown_edit_attributes_attribute_type.grid(row = 1, column = 1, pady = 5)
if not self.ec_app_ui.new_model.get_component(self.current_component).get_is_class_component():
### Attribute layer ###
self.label_edit_attributes_layer.grid(row = 2, column = 0, padx = 150, pady = 5
, sticky="W")
self.dropdown_edit_attributes_layer.grid(row = 2, column = 1, pady = 5)
self.button_edit_attributes_save.grid(row = 4, column = 1, pady = 5)
[docs]
def btn_edit_attributes_remove(self):
"""Phase 2
"""
self.ec_app_ui.new_model.remove_attribute(self.current_component, self.selected_attribute)
self.btn_edit_attributes_add()
[docs]
def btn_edit_attributes_save(self):
"""Allows users to save the edited attribute to the backend.
"""
attribute = self.entry_edit_attribute_name.get()
primitive = self.selected_primitive_ea.get()
layer = self.dropdown_edit_attributes_layer.get()
default = None
if not self.ec_app_ui.new_model.get_component(self.current_component).get_is_class_component():
if layer == "Component Layer":
default = self.entry_edit_attributes_default.get("1.0", 'end-1c')
else:
default = None
layer = None
if self.dropdown_edit_attributes_layer.get() == "Component Layer":
layer = "comp_lvl"
elif self.dropdown_edit_attributes_layer.get() == "Agent Layer":
layer = "agent_lvl"
default = None
elif self.dropdown_edit_attributes_layer.get() == "Model Layer":
layer = "model_lvl"
default = None
self.ec_app_ui.new_model.edit_attribute(self.current_component, attribute, primitive
, layer, default)
else:
self.ec_app_ui.new_model.edit_attribute(self.current_component,attribute, primitive
, "model_lvl", default)
self.entry_edit_attribute_name.configure(state= "normal")
self.entry_edit_attribute_name.delete(0,'end')
self.clear_individual_attribute()
self.edit_attribute_tab_btn()
[docs]
def on_user_click_edit_attribute(self):
"""Checks whether the checkbox is clicked.
"""
if self.user_value_edit_attribute.get():
self.label_edit_attributes_default.grid_forget()
self.entry_edit_attributes_default.grid_forget()
else:
self.entry_edit_attributes_default.delete("1.0", 'end-1c')
self.label_edit_attributes_default.grid(row = 2, column = 0, padx = 150,pady = 5
, sticky="W")
self.entry_edit_attributes_default.grid(row = 2, column = 1,pady = 5)
[docs]
def on_selected_primitive(self, *args):
"""Required for dropdown box
"""
[docs]
def selected_comp_attr(self, *args):
"""Checks which component the user has selected
"""
id4 = 0
self.selected_attribute = ""
selected = self.dropdown_edit_attributes_components.get()
self.current_component = selected
self.attr_tbl.delete(*self.attr_tbl.get_children())
if not selected == "Select Component":
arrt = self.ec_app_ui.new_model.get_list_attributes(selected)
for i in (arrt):
self.attr_tbl.insert(parent='',index="end",iid=id4,text='',values=(i,))
id4+=1
self.attr_frame.grid(row = 2,column = 1, pady = 20)
self.vertical_scroll.pack(side="right", fill="y", padx=(0,5), pady=5)
self.attr_tbl.pack(fill = "x", padx = (5,0), pady = 5)
self.button_edit_attributes_edit.grid_forget()
self.button_edit_attributes_remove.grid_forget()
[docs]
def display_selected_attribute(self, *args):
"""Saves the attribute the user clicked on.
"""
selected_items = self.attr_tbl.selection()
if selected_items:
selected_item = self.attr_tbl.selection()[0]
self.selected_attribute = self.attr_tbl.item(selected_item)['values'][0]
self.frame_small.grid(row=3, column = 1)
self.button_edit_attributes_edit.grid(row = 0,column = 0, padx = (0,15))
self.button_edit_attributes_remove.grid(row = 0,column = 1)