import tkinter as tk import util # easy way to get data out of window events class Window_Interaction_Handler: # constructor def __init__(self): self.__window_interactions = {} # add a result for an interaction event, saves results in reverse order by default, can optionally call another function def interact(self, name, result, reverse_order=True, additional_action=None, additional_action_parameters=()): if name in self.__window_interactions: if reverse_order: self.__window_interactions[name] = [result] + self.__window_interactions[name] else: self.__window_interactions[name] = self.__window_interactions[name] + [result] else: self.__window_interactions[name] = [result] if not additional_action==None: additional_action(*additional_action_parameters) # get first result for a given event from the list of results (newest (default) or oldest), removes the returned result from the list by default def get_result(self, name, remove=True): if name in self.__window_interactions and len(self.__window_interactions[name])>0: if remove: result = self.__window_interactions[name].pop(0) if len(self.__window_interactions[name])==0: del self.__window_interactions[name] return result else: return self.__window_interactions[name][0] else: return None # get all results for a given event def get_results(self, name, clear=False): if name in self.__window_interactions and len(self.__window_interactions[name])>0: results = self.__window_interactions[name] if clear: del self.__window_interactions[name] return results # clear results for a given event def clear(self, name): if name in self.__window_interactions: del self.__window_interactions[name] # destructor def __del__(self): if len(self.__window_interactions)>0: util.warn("__window_interactions not empty upon destruction of Window_Interaction_Handler:\n"+str(self.__window_interactions)) def not_implemented(): util.warn("Not implemented!") # format: # "":{} -> menu or submenu # "":function -> menu entry # "":None -> disabled menu entry # None:None -> separator # # Entries with ... at the end are supposed to open dialogs whereas entries without dots are supposed to take effect immediately menu_structure = { "IDE": { "Preferences...": not_implemented, None: None, "Quit": not_implemented }, "Project": { "New": { "No known project types": None }, "Open...": not_implemented, "Close": { "No open projects": None }, None: None, "Preferences...": not_implemented, "Search...": not_implemented, "Build": not_implemented }, "File": { "New...": not_implemented, "Open...": not_implemented, "Save": not_implemented, "Close": not_implemented, None: None, "Rename...": not_implemented, "Move...": not_implemented, "View in File Explorer...": not_implemented }, "Edit": { "Cut": not_implemented, "Copy": not_implemented, "Paste": not_implemented, "Move code...": not_implemented, None: None, "Search and Replace...": not_implemented, None: None, "Format": not_implemented, "Indent": not_implemented, "Unindent": not_implemented, "Toggle Comment": not_implemented }, "View": { "Zoom in": not_implemented, "Zoom out": not_implemented, "Normal Size": not_implemented }, "Help": { "Manual...": not_implemented, "About IDE...": not_implemented, } } #FIXME: come up with a way to uniquely declare separators so they don't become the same element of a dict def build_menu(structure_dict, menu): for entry in structure_dict: if structure_dict[entry]==None: if entry==None: menu.add_separator() else: menu.add_command(label=entry) menu.entryconfig(entry, state="disabled") if isinstance(structure_dict[entry], dict): submenu = tk.Menu(menu, tearoff=False) build_menu(structure_dict[entry], submenu) menu.add_cascade(label=entry, menu=submenu) if callable(structure_dict[entry]): menu.add_command(label=entry, command=structure_dict[entry])