"""
Frontend Main File for AGE-ABM Visual Interface
@Author Meghan Ireland
@Co-Authors Max Hall and Matthew Fleischman
"""
import tkinter as tk
import customtkinter
from interface.agents import Agents
from interface.components import Components
from interface.model_details import Details
from interface.data_collection import DataCollection
from interface.compile import Compile
from interface.home import Home
from interface.execute import Execute
from interface.edit_attributes import EditAttributes
from interface.libraries import Libraries
from interface.systems import Systems
from interface.visualisation import Visualisation
[docs]
class ECAppUI:
"""Defines widgets and functionality of main tab buttons.
"""
def __init__(self):
"""Creates the main variables used for the application.
"""
# Create the main application window
self.collapsed = False
self.frame_colour = '#1E1E1E'
self.entry_colour = '#434644'
self.title_colour = '#252526'
self.highlight_colour = "#7CA188"
self.root = tk.Tk()
self.root.title("EC-App")
self.root.configure(bg="#FFFFFF")
taskbar = 50
screen_width = self.root.winfo_screenwidth()
screen_height = self.root.winfo_screenheight()
logo_picture = tk.PhotoImage(file = 'logo.png')
self.root.iconphoto(False, logo_picture)
# Calculate the size and position for the full-screen window
self.window_width = screen_width
self.window_height = screen_height - taskbar - 40
self.panel_height = self.window_height
self.panel_width = self.window_width/4
self.page_frame_height = self.window_height
self.page_frame_width = self.window_width - self.panel_width
x_pos = 0
self.collapse_bar_color = "#3A644E"
y_pos = 0
self.root.geometry(f"{self.window_width}x{self.window_height}+{x_pos}+{y_pos}")
### Variables ###
self.button_height = 50
self.button_width = self.window_width/4
self.frame_btn_width = self.panel_width - 4
self.tbl_colour = "#C6EBCA"
self.panel_colour = "#323233"
self.label_colour1 = "#5b7e84"
self.dropdown_menu_color = "#86AD99"
self.home_colour = "#16634B"
self.label_text_colour = "white"
self.entry_text_colour = "white"
self.button_colour = "#0EA374"
self.check_color = "#0EA374"
self.space_btw_btns = 5
self.font1 = customtkinter.CTkFont(family="Montserrat", size=25)
#self.font1=("Verdana", 20)
self.font2 = customtkinter.CTkFont(family="Montserrat", size=18)
self.font_menu = customtkinter.CTkFont(family="Montserrat", size=16)
#self.font2=("Verdana", 16)
#self.font3_underlined = Font(family="Verdana", size=16, underline=True)
self.font3_underlined = customtkinter.CTkFont(family="Montserrat", size=16, underline=True)
self.button_font_colour = "white"
self.tbl_font_colour = "black"
self.label_pos = 50
self.under_tbl = self.window_height/2 + 40
self.btn_comp_width = self.window_width//12
self.comp_btn_colour = "#53a57d"
self.off_switch = "#F57872"
self.menu_font_colour = "white"
self.entry_height = 30
self.entry_width = self.entry_height*8
self.page_frame = tk.Frame(master = self.root, bg=self.frame_colour
, height = 7*self.page_frame_height/8
, width = self.page_frame_width)
self.page_frame.grid_columnconfigure(0, weight=1)
self.page_frame.grid_columnconfigure(1, weight=1)
self.page_frame.grid_columnconfigure(2, weight=1)
self.page_frame.grid_propagate(0)
self.title_frame = tk.Frame(master = self.root, bg=self.title_colour
, height = self.page_frame_height/8
, width = self.page_frame_width)
self.title_frame.grid_propagate(0)
self.title_frame.grid_rowconfigure(0, weight=1)
self.title_frame.grid_columnconfigure(0, weight=1)
self.left_frame = tk.Frame(master = self.root, bg = self.panel_colour
, height = self.panel_height
, width = self.panel_width)
self.left_frame.grid_propagate(0)
self.collapser_frame = tk.Frame(master = self.root, bg = self.collapse_bar_color
, height=self.window_height, width=6)
self.title_position_row = 0
self.title_position_column = 0
self.title_position_pady = 25
self.title_position_padx = 350
### Variables for model ###
self.new_model = None # Creates model_env object
self.visual = None
self.components = Components(self)
self.agents = Agents(self)
self.edit_attributes = EditAttributes(self)
self.home = Home(self)
self.details = Details(self)
self.compile = Compile(self)
self.data_collection = DataCollection(self)
self.libraries = Libraries(self)
self.visualisation = Visualisation(self)
self.execute = Execute(self)
self.systems = Systems(self)
self.menu_height = self.page_frame_height//20
self.menu_frame = tk.Frame(master = self.root, bg=self.panel_colour
, height = self.menu_height
, width = self.window_width)
self.menu_frame.grid_propagate(0)
self.root.protocol("WM_DELETE_WINDOW", self.on_closing)
### Instantiating variables for frame
self.home_save_button = None
self.home_new_button = None
self.home_upload_button = None
self.home_tab_button = None
self.libraries_tab_button = None
self.components_tab_button = None
self.edit_attribute_tab_button = None
self.agents_tab_button = None
self.systems_tab_button = None
self.execute_tab_button = None
self.data_tab_button = None
self.details_button = None
self.compile_tab_button = None
self.visual_tab_button = None
self.collapse_button = None
[docs]
def on_closing(self):
"""Runs when the user tries to close the application
"""
message = "Have you saved your model?\n" \
"'No' to cancel - 'Yes' to close"
# Show a message box with the help message and "Yes" and "No" buttons
result = tk.messagebox.askyesno("Close Application", message)
# Check the user's choice and act accordingly
if result:
# User clicked "Yes," close the application
self.visualisation.on_close_graphs()
self.root.quit()
self.root.destroy()
[docs]
def on_open(self):
"""Runs when the user tries to open an old model
"""
message = "Have you saved your model?\n"
# Show a message box with the help message and "Yes" and "No" buttons
result = tk.messagebox.askyesno("Close Application", message)
# Check the user's choice and act accordingly
if result:
self.home.btn_home_make_exist_model()
[docs]
def enable(self):
"""Enables buttons again
"""
self.libraries_tab_button.configure(state = "normal")
self.components_tab_button.configure(state = "normal")
self.edit_attribute_tab_button.configure(state = "normal")
self.agents_tab_button.configure(state = "normal")
self.systems_tab_button.configure(state = "normal")
self.execute_tab_button.configure(state = "normal")
self.data_tab_button.configure(state = "normal")
self.details_button.configure(state = "normal")
self.compile_tab_button.configure(state = "normal")
self.visual_tab_button.configure(state = "normal")
[docs]
def on_new(self):
"""Runs when the user tries to start a new model
"""
message = "Have you saved your model?\n" \
"'No' to cancel - 'Yes' to close"
# Show a message box with the help message and "Yes" and "No" buttons
result = tk.messagebox.askyesno("Close Application", message)
# Check the user's choice and act accordingly
if result:
self.home.home_tab_btn()
self.home_tab_button.configure(state = "disabled")
self.libraries_tab_button.configure(state = "disabled")
self.components_tab_button.configure(state = "disabled")
self.edit_attribute_tab_button.configure(state = "disabled")
self.agents_tab_button.configure(state = "disabled")
self.systems_tab_button.configure(state = "disabled")
self.execute_tab_button.configure(state = "disabled")
self.data_tab_button.configure(state = "disabled")
self.details_button.configure(state = "disabled")
self.compile_tab_button.configure(state = "disabled")
self.visual_tab_button.configure(state = "disabled")
[docs]
def ec_app(self):
"""Below this point you will find the functions which are called when a user interacts with
a widget. The functions also place widgets on the page and clear widgets from the interface.
"""
self.panel_height = self.window_height
self.panel_width = self.window_width/4
menu_item_width = 2*self.menu_height
### Add main frames
self.menu_frame.pack(fill="both")
self.left_frame.pack(side='left', fill = "both", anchor="w")
self.collapser_frame.pack(side="left", fill="both", anchor="w")
self.title_frame.pack(side='top', fill = "both", anchor="w", expand=1)
self.page_frame.pack(fill = "both", anchor="w", expand=1)
# Create a PhotoImage object from an image file (replace 'icon.gif' with your image file)
lib_icon = tk.PhotoImage(file="icons/lib.png")
comp_icon = tk.PhotoImage(file="icons/comp.png")
att_icon = tk.PhotoImage(file="icons/edit.png")
agent_icon = tk.PhotoImage(file="icons/agent.png")
system_icon = tk.PhotoImage(file="icons/chain.png")
data_icon = tk.PhotoImage(file="icons/basket.png")
exec_icon = tk.PhotoImage(file="icons/execute.png")
details_icon = tk.PhotoImage(file="icons/details.png")
visual_icon = tk.PhotoImage(file="icons/visual.png")
compile_icon = tk.PhotoImage(file="icons/download.png")
### Add menu options ###
self.home_save_button = customtkinter.CTkButton(master = self.menu_frame,text="💾 Save",
command=self.home.home_tab_btn, fg_color=self.panel_colour
, border_color=self.panel_colour, text_color = self.menu_font_colour
, hover_color=self.highlight_colour
, font = self.font_menu, height=self.menu_height - 4, width=menu_item_width)
self.home_save_button.configure(state = "disabled")
self.home_new_button = customtkinter.CTkButton(master = self.menu_frame,text="📄 New",
command=self.on_new, fg_color=self.panel_colour
, border_color=self.panel_colour, text_color = self.menu_font_colour
, hover_color=self.highlight_colour, font = self.font_menu, height=self.menu_height - 4
, width=menu_item_width)
self.home_upload_button = customtkinter.CTkButton(master = self.menu_frame,text="📂 Open",
command=self.on_open, fg_color=self.panel_colour
, border_color=self.panel_colour, text_color = self.menu_font_colour
, hover_color=self.highlight_colour, font = self.font_menu, height=self.menu_height - 4
, width=menu_item_width)
self.home_save_button.grid(row = 0, column = 0, padx = (0,2), pady = 2)
self.home_new_button.grid(row = 0, column = 2, padx = 2, pady = 2)
self.home_upload_button.grid(row = 0, column = 1, padx = 2, pady = 2)
### Left Frame Buttons ###
self.home_tab_button = customtkinter.CTkButton(master = self.left_frame
, text="ECAgent Builder", command=self.home.home_tab_btn, fg_color=self.home_colour
, border_color=self.panel_colour, font = self.font1,hover_color=self.highlight_colour
, height=3*self.button_height, width=self.frame_btn_width)
self.home_tab_button.grid(pady=(0,2),row = 0, column = 0)
self.libraries_tab_button = customtkinter.CTkButton(self.left_frame
, text="Libraries to Import", command=self.libraries.libraries_tab_btn
, fg_color=self.button_colour, border_color=self.panel_colour
, image=lib_icon, compound="left"
, font = self.font1, anchor = "w", height=self.button_height
, width=self.frame_btn_width, hover_color=self.highlight_colour)
self.libraries_tab_button.grid(pady=1,row = 1,column = 0)
self.components_tab_button = customtkinter.CTkButton(self.left_frame,text="Components",
command=self.components.components_tab_btn, fg_color=self.button_colour,
border_color=self.panel_colour, font = self.font1, anchor = "w"
, image=comp_icon, compound="left"
, height=self.button_height, width=self.frame_btn_width
, hover_color=self.highlight_colour)
self.components_tab_button.grid(pady=1,row = 2,column = 0)
self.edit_attribute_tab_button = customtkinter.CTkButton(self.left_frame
, text="Attribute Editing", command=self.edit_attributes.edit_attribute_tab_btn
, fg_color=self.button_colour, border_color=self.panel_colour, font = self.font1
, hover_color=self.highlight_colour, anchor = "w", height=self.button_height
, image=att_icon, compound="left"
, width=self.frame_btn_width)
self.edit_attribute_tab_button.grid(pady=1,row = 3,column = 0)
self.agents_tab_button = customtkinter.CTkButton(self.left_frame,text="Agents"
, command=self.agents.agents_tab_btn, fg_color=self.button_colour
, image=agent_icon, compound="left"
, border_color=self.panel_colour, font = self.font1, anchor = "w",
height=self.button_height, width=self.frame_btn_width,hover_color=self.highlight_colour)
self.agents_tab_button.grid(pady=1,row = 4,column = 0)
self.systems_tab_button = customtkinter.CTkButton(self.left_frame,text="Systems"
, command=self.systems.systems_tab_btn, fg_color=self.button_colour
, image=system_icon, compound="left"
, border_color=self.panel_colour, font = self.font1,hover_color=self.highlight_colour
, anchor = "w", height=self.button_height, width=self.frame_btn_width)
self.systems_tab_button.grid(pady=1,row = 5,column = 0)
self.execute_tab_button = customtkinter.CTkButton(self.left_frame
, text="System's Executes", command=self.execute.execute_tab_btn
, fg_color=self.button_colour, border_color=self.panel_colour, font = self.font1
, image=exec_icon, compound="left"
, anchor = "w", height=self.button_height, width=self.frame_btn_width,
hover_color=self.highlight_colour)
self.execute_tab_button.grid(pady=1,row = 6,column = 0)
self.data_tab_button = customtkinter.CTkButton(self.left_frame, text="Data Collection",
command=self.data_collection.data_tab_btn, fg_color=self.button_colour
, image=data_icon, compound="left"
, border_color=self.panel_colour, font = self.font1, anchor = "w"
, height=self.button_height, hover_color=self.highlight_colour
, width=self.frame_btn_width)
self.data_tab_button.grid(pady=1,row = 7,column = 0)
self.details_button = customtkinter.CTkButton(self.left_frame,text="Model Details",
command=self.details.details_tab_btn, fg_color=self.button_colour
, image=details_icon, compound="left"
, border_color=self.panel_colour, font = self.font1, anchor = "w"
, height=self.button_height, width=self.frame_btn_width
, hover_color=self.highlight_colour)
self.details_button.grid(pady=1,row = 8,column = 0)
self.visual_tab_button = customtkinter.CTkButton(self.left_frame,text="Visualisation"
, command=self.visualisation.visual_tab_btn, fg_color=self.button_colour
, image=visual_icon, compound="left"
, border_color=self.panel_colour, font = self.font1, anchor = "w"
, height=self.button_height, width=self.frame_btn_width
, hover_color=self.highlight_colour)
self.visual_tab_button.grid(pady=1,row = 9,column = 0)
self.compile_tab_button = customtkinter.CTkButton(self.left_frame,text="Model Download"
, command=self.compile.compile_tab_btn, fg_color=self.button_colour
, image=compile_icon, compound="left"
, border_color=self.panel_colour, font = self.font1, anchor = "w"
, height=self.button_height, width=self.frame_btn_width
, hover_color=self.highlight_colour)
self.compile_tab_button.grid(pady=1,row = 10,column = 0)
self.collapse_button = customtkinter.CTkButton(self.collapser_frame,text="<"
, command=self.collapse_tab_btn, fg_color=self.collapse_bar_color
, border_color=self.panel_colour, font = self.font1, anchor = "w"
, height=self.window_height, hover_color=self.highlight_colour, width=6)
self.collapse_button.grid(row = 0, column = 0)
#self.home.button_home_make_model.config(state=tk.NORMAL)
self.home.home_tab_btn()
### Initially these buttons are disabled:
#self.edit_attribute_tab_button.config(state=tk.DISABLED)
#self.agents_tab_button.config(state=tk.DISABLED)
#self.systems_tab_button.config(state=tk.DISABLED)
#self.execute_tab_button.config(state=tk.DISABLED)
#self.visual_tab_button.config(state=tk.DISABLED)
# Enter the main event loop
self.root.mainloop()
[docs]
def collapse_tab_btn(self):
"""This method is called when the collapse button is pressed.
"""
if self.collapsed:
self.panel_height = self.window_height
self.panel_width = self.window_width/4
self.frame_btn_width = self.window_width/4 - 4
self.page_frame_width = self.window_width - self.panel_width
self.left_frame.configure(width=self.panel_width,height=self.panel_height)
self.page_frame.configure(height = 7*self.page_frame_height/8
, width = self.page_frame_width)
self.title_frame.configure(height = self.page_frame_height/8
, width = self.page_frame_width)
self.home_tab_button.configure(text="ECAgent Builder", width=self.frame_btn_width)
self.libraries_tab_button.configure(text="Libraries to Import", width=self.frame_btn_width)
self.components_tab_button.configure(text="Components", width=self.frame_btn_width)
self.edit_attribute_tab_button.configure(text="Attribute Editing", width=self.frame_btn_width)
self.agents_tab_button.configure(text="Agents", width=self.frame_btn_width)
self.systems_tab_button.configure(text="Systems", width=self.frame_btn_width)
self.execute_tab_button.configure(text="System's Executes", width=self.frame_btn_width)
self.data_tab_button.configure(text="Data Collection", width=self.frame_btn_width)
self.details_button.configure(text="Model Details", width=self.frame_btn_width)
self.compile_tab_button.configure(text="Model Download", width=self.frame_btn_width)
self.visual_tab_button.configure(self.left_frame,text="Visualisation", width=self.frame_btn_width)
self.collapse_button.configure(text="<")
self.collapsed = False
else:
self.frame_btn_width = 60
self.panel_height = self.window_height
self.panel_width = 64
self.left_frame.configure(width=self.panel_width,height=self.panel_height)
self.page_frame.configure(height = 7*self.page_frame_height/8
, width = self.page_frame_width+9*self.panel_width)
self.title_frame.configure(height = self.page_frame_height/8
, width = self.page_frame_width+9*self.panel_width)
self.home_tab_button.configure(text=" ", width=self.frame_btn_width)
self.libraries_tab_button.configure(text="", width=self.frame_btn_width)
self.components_tab_button.configure(text="", width=self.frame_btn_width)
self.edit_attribute_tab_button.configure(text="", width=self.frame_btn_width)
self.agents_tab_button.configure(text="", width=self.frame_btn_width)
self.systems_tab_button.configure(text="", width=self.frame_btn_width)
self.execute_tab_button.configure(text="", width=self.frame_btn_width)
self.data_tab_button.configure(text="", width=self.frame_btn_width)
self.details_button.configure(text="", width=self.frame_btn_width)
self.compile_tab_button.configure(text="", width=self.frame_btn_width)
self.visual_tab_button.configure(self.left_frame,text="", width=self.frame_btn_width)
self.collapse_button.configure(text=">")
self.collapsed = True
[docs]
def clear_all(self):
"""Clears all the pages
"""
self.systems.clear_systems()
self.agents.clear_agents()
self.agents.clear_add_agent()
self.components.clear_components()
self.components.clear_add_comp()
self.compile.clear_compile()
self.home.clear_home()
self.edit_attributes.clear_edit_attributes()
self.components.clear_add_comp()
self.agents.clear_add_agent()
self.systems.clear_add_system()
self.systems.clear_systems()
self.libraries.clear_lib()
self.data_collection.clear_collectors()
self.details.clear_details()
self.visualisation.clear_visual()
self.execute.clear_execute()
if __name__ == "__main__":
model = ECAppUI()
model.ec_app()