def __init__(self, all_atoms: t.List[u.Atom]): ''' :param all_atoms: List of all atoms in the Molecules, which should be connected :type all_atoms: t.List[u.Atom] ''' self.all_atoms: t.List[u.Atom] = all_atoms self.selected_atoms: t.List[u.Atom] = [] self.selected_restraints: t.List[Restraint._Restraint] = [] # Define Restraint-Types self.available_restraint_types = u.get_all_subclasses(Restraint._Restraint) self.current_restraint_type = None self.my_restraint = None # Define Importer-Types self.available_importer_types = u.get_all_subclasses(Importer._Importer) self.current_importer_type = None self.my_importer = None # Define Selection-Types self.available_selection_types: t.list[t.type] = u.get_all_subclasses(Selection._Selection) self.current_selection_type = None self.my_selection = None # Unlike my_filter my_selection needs to be accessed by several methods: do_pick, set_selection # Define Filter-Types self.available_filter_types: t.list[t.type] = u.get_all_subclasses(Filter._Filter) self.current_filter_type = None self.my_filter = None # Define-Optimizer Types self.available_optimizer_types: t.List[t.type] = u.get_all_subclasses(Optimizer._Optimizer) self.current_optimizer_type = None self.my_optimizer = None # Define-Exporter-Types self.available_exporter_types = u.get_all_subclasses(Exporter._Exporter) self.current_exporter_type = None self.my_exporter = None # Modes & Action_States (Modes: What do to atoms, when they are selected. Action states: Which actions are possible right now) # TODO CLEAN (1): If we ever use more porgram modes it mioght be cleaner to make the enum u.ActionStates a class, # which contains one attribute indicating actions AND one for each mode self.select_or_delete_mode = True # True = select, False = delte self.atom_or_restraint_mode = True # True = atom, False = Restraint self._action_states: dict = { 'toggle_select_delete': u.ActionState.ALWAYS_ENABLED, 'toggle_atom_restraint': u.ActionState.ALWAYS_ENABLED, 'Importer': u.ActionState.ALWAYS_DISABLED, 'Restraint': u.ActionState.ALWAYS_DISABLED, 'Selection': u.ActionState.ALWAYS_DISABLED, 'Filter': u.ActionState.ALWAYS_DISABLED, 'Optimizer': u.ActionState.ALWAYS_DISABLED, 'Exporter': u.ActionState.ALWAYS_DISABLED, 'Done': u.ActionState.ALWAYS_ENABLED} self.set_action_states()
def __init__(self, all_atoms: t.List[u.Atom]): """ Handles the program flow. By defining it inside a class we get proper encapsulation and prevent problems with multiple imports When a GUI Program Launches it should create one instance of a Logic_Handler and use it to control the program flow. It should pass GUI-events to it (by calling the react_to_event method.). The GUI Module should NOT need to directly access any other modules. (Except utilities). Warning: To keep things clean there is not backwards communicatopn from the Logic_Handler to the GUI module. It is the GUI Modules responsibility to check on the current state of the program, after creating events. Warning: I really do NOT want the GUI-Program to inherit form the Logic_Handler. It will inherit from a GUI Element (e.g. interface_Pymol.Wizard). Python suppports multiple inheritance, but I don't. RECOMMENDATIONS TO WRITE A NEW GUI MODULE: The GUI Module should have the following functions/Elements 1) Buttons/Lists... for the different actions that can be performed (Import, RestraintType, Selection ...). These should call the function set_importer_type, set_restraint_type ... The GUI Program should use the action_states dict, to check which actions are currently available. 2) 2 Toggle buttons / radio buttons... to switch between select / delete mode and atom / restraint mode 2) Events: The GUI Module is responsible for translating whatever events it understands into events relevant to the selections. It can do this by calling the function react_to_event(event_type, kw_args) Recommended translations: SELECT: When the user clicks a certain Atom MOVE: Mouse movement / keyboard arrows ... SIZE: Mouse wheel / keyboard arrows CONFIRM: Double Click, Enter ... The GUI module should check the state of the program (event_state dict and selected_atoms, selected-restraints) every time after calling react_to_event. I recommend wrapping the react_to_event function into a function of the GUI module to do that automatically. 3) Some Selections (SphericalSelection & subclasses) are more intuitive if the GUI program draws a sphere at the corresponding position. => If you want that you have to introduce special for the GUI module to check the current selection Parameters ---------- all_atoms : t.List[u.Atom] List of all atoms in the Molecules, which should be connected """ self.all_atoms: t.List[u.Atom] = all_atoms self.selected_atoms: t.List[u.Atom] = [] self.selected_restraints: t.List[Restraints._Restraint] = [] # Define Restraint-Types self.all_restraint_types = u.get_all_subclasses(Restraint_Types._Restraint_Type) self.available_restraint_types = [] self.current_restraint_type:Restraint_Types._Restraint_Type = Restraint_Types.DistanceRestraintType self.my_restraint: Restraint_Types._Restraint_Type = None # Define Importer-Types self.available_importer_types = u.get_all_subclasses(Importer._Importer) self.current_importer_type = None self.my_importer = None # Define Selection-Types self.available_selection_types: t.List[t.Type] = u.get_all_subclasses(Selection._Selection) self.current_selection_type = None self.my_selection = None # Unlike my_filter my_selection needs to be accessed by several methods: do_pick, set_selection # Define Filter-Types self.available_filter_types: t.List[t.Type] = u.get_all_subclasses(Filter._Filter) self.current_filter_type = None self.my_filter = None # Define-Optimizer Types self.available_optimizer_types: t.List[t.Type] = [x for x in u.get_all_subclasses(Optimizer._Optimizer) if (not x == Optimizer.MetaMoleculeRingOptimizer)] self.current_optimizer_type = None self.my_optimizer = None # Define-Exporter-Types self.all_exporter_types = u.get_all_subclasses(Exporter._Exporter) self.available_exporter_types = u.get_all_subclasses(Exporter._Export_Distance_Restraints) self.current_exporter_type = None self.my_exporter = None # Modes & Action_States (Modes: What do to atoms, when they are selected. Action states: Which actions are possible right now) # which contains one attribute indicating actions AND one for each mode self._action_states: dict = { 'toggle_select_delete': program_states.ActionState.ALWAYS_ENABLED, 'toggle_atom_restraint': program_states.ActionState.ALWAYS_ENABLED, 'Reset': program_states.ActionState.ALWAYS_ENABLED, 'Importer': program_states.ActionState.ALWAYS_DISABLED, 'Restraint': program_states.ActionState.ALWAYS_DISABLED, 'Selection': program_states.ActionState.ALWAYS_DISABLED, 'Filter': program_states.ActionState.ALWAYS_DISABLED, 'Optimizer': program_states.ActionState.ALWAYS_DISABLED, 'Exporter': program_states.ActionState.ALWAYS_DISABLED, 'Done': program_states.ActionState.ALWAYS_ENABLED} #initialize self.set_mode(select_delete=True, atom_restraint=True) self.set_action_states() self._set_restraint_type(self.current_restraint_type)