class Analysis_wizard: """The analysis selection wizard.""" def Destroy(self): """Properly delete the wizard and all its elements.""" self.wizard.Destroy() def run(self): """Run through the analysis selection wizard, returning the results. @return: The analysis type, analysis name, data pipe name, data pipe bundle name, and user function on_execute method list. @rtype: tuple of str """ # Change the cursor to busy. wx.Yield() wx.BeginBusyCursor() # Set up the wizard. self.wizard = Wiz_window(size_x=1000, size_y=700, title='Analysis selection wizard') # Change the finish button. self.wizard.TEXT_FINISH = " Start" # Add the new analysis panel. self.new_page = New_analysis_page(self.wizard) self.wizard.add_page(self.new_page, apply_button=False) self.wizard.set_seq_next_fn(0, self.wizard_page_after_analysis) # Add the data pipe name panel. self.pipe_page = Data_pipe_page(self.wizard, height_desc=400) self.wizard.add_page(self.pipe_page, apply_button=False) # Reset the cursor. if wx.IsBusy(): wx.EndBusyCursor() # Execute the wizard. setup = self.wizard.run(modal=True) if setup != wx.ID_OK: return # Return the analysis type, analysis name, data pipe name, data pipe bundle name, and user function on_execute method list. return self.get_data() def get_data(self): """Assemble and return the analysis type, analysis name, and pipe name. @return: The analysis type, analysis name, data pipe name, data pipe bundle name, and list of user function on_execute methods. @rtype: str, str, str, str, list of methods """ # Get the data. analysis_type = gui_to_str(self.wizard.analysis_type) analysis_name = gui_to_str(self.new_page.analysis_name.GetValue()) pipe_name = gui_to_str(self.pipe_page.pipe_name.GetValue()) pipe_bundle = gui_to_str(self.pipe_page.pipe_bundle.GetValue()) # The user function on_execute methods. uf_exec = [] # Return it. return analysis_type, analysis_name, pipe_name, pipe_bundle, uf_exec def wizard_page_after_analysis(self): """Set the page after the data pipe setup. @return: The index of the next page, which is the current page index plus one. @rtype: int """ # The selected analysis. analysis_name = gui_to_str(self.new_page.analysis_name.GetValue()) # Default to the second page. return 1
class Spin_view_window(wx.Frame): """A window element for the tree view.""" def __init__(self, *args, **kwds): """Set up the relax prompt.""" # Store the parent object. self.gui = kwds.pop('parent') # Create GUI elements kwds["style"] = wx.DEFAULT_FRAME_STYLE if not status.debug and status.wx_info["os"] != 'darwin': kwds["style"] = kwds["style"] | wx.MAXIMIZE wx.Frame.__init__(self, *args, **kwds) # Force the main window to start maximised (needed for MS Windows). if not status.debug and status.wx_info["os"] != 'darwin': self.Maximize() # Set up the window icon. self.SetIcons(relax_icons) # Some default values. self.size_x = 1000 self.size_y = 750 # Set up the window. sizer = self.setup_window() # Create a menu. self._create_menu() # Build the toolbar. self.toolbar() # The splitter window. splitter = Tree_splitter(self.gui, self, -1) sizer.Add(splitter, 1, wx.EXPAND|wx.ALL, 0) # Initialise observer name. self.name = 'spin viewer' def _activate(self): """Activate or deactivate certain elements in response to the execution lock.""" # Flag for enabling or disabling the elements. enable = False if not status.exec_lock.locked(): enable = True # Loop over the menus. for menu, label in self.menubar.GetMenus(): # Loop over the menu items. for item in menu.GetMenuItems(): wx.CallAfter(item.Enable, enable) # The spin loader. wx.CallAfter(self.bar.EnableTool, self.spin_loader_id, enable) # The pipe selector. wx.CallAfter(self.pipe_name.Enable, enable) def _create_menu(self): """Build a menu for the window.""" # Create the menu bar GUI item and add it to the main frame. self.menubar = wx.MenuBar() if status.show_gui: self.SetMenuBar(self.menubar) # The user function menus. self.menu_uf_ids = build_uf_menus(parent=self, menubar=self.menubar) def Show(self, show=True): """Change the behaviour of showing the window to update the content. @keyword show: A flag which is True shows the window. @type show: bool """ # Register a few methods in the observer objects. status.observers.gui_uf.register(self.name, self.refresh, method_name='ref') status.observers.pipe_alteration.register(self.name, self.refresh, method_name='ref') status.observers.exec_lock.register(self.name, self._activate, method_name='_activate') # First update. self.refresh() # Activate or deactivate the frame. self._activate() # Then show the window using the base class method. if status.show_gui: super(Spin_view_window, self).Show(show) def refresh(self, event=None): """Event handler for the refresh action (thread safe). @keyword event: The wx event. @type event: wx event """ # Thread safe. wx.CallAfter(self.refresh_safe) def refresh_safe(self): """Refresh the spin viewer window.""" # Change the cursor to busy. wx.BeginBusyCursor() # Update the data pipe selector. self.update_pipes() # Update the tree. self.tree_panel.update() # Redisplay the container. self.container.display(self.tree_panel.get_info()) # Reset the cursor. if wx.IsBusy(): wx.EndBusyCursor() def handler_close(self, event=None): """Event handler for the close window action. @keyword event: The wx event. @type event: wx event """ # Unregister the methods from the observers to avoid unnecessary updating. status.observers.gui_uf.unregister(self.name) status.observers.pipe_alteration.unregister(self.name) status.observers.exec_lock.unregister(self.name) # Close the window. self.Hide() def load_spins_wizard(self, event=None): """The spin loading wizard. @keyword event: The wx event. @type event: wx event """ # No current data pipe. if not cdp_name(): gui_raise(RelaxNoPipeError()) return # Change the cursor to busy. wx.BeginBusyCursor() # Initialise a wizard. self.wizard = Wiz_window(parent=self, size_x=1000, size_y=800, title="Load spins") self.page_indices = {} # The loading method page. self.page_method = Load_method_page(self.wizard) self.page_indices['method'] = self.wizard.add_page(self.page_method, apply_button=True, skip_button=False) self.wizard.set_seq_next_fn(self.page_indices['method'], self.wizard_page_after_load_method) # The sequence.read page. page = uf_store['sequence.read'].create_page(self.wizard) self.page_indices['sequence.read'] = self.wizard.add_page(page, skip_button=True) self.wizard.set_seq_next_fn(self.page_indices['sequence.read'], self.wizard_page_after_sequence_read) # The structure.read_pdb page. page = uf_store['structure.read_pdb'].create_page(self.wizard) self.page_indices['structure.read_pdb'] = self.wizard.add_page(page, skip_button=True) self.wizard.set_seq_next_fn(self.page_indices['structure.read_pdb'], self.wizard_page_after_structure_read) # The structure.read_xyz page. page = uf_store['structure.read_xyz'].create_page(self.wizard) self.page_indices['structure.read_xyz'] = self.wizard.add_page(page, skip_button=True) self.wizard.set_seq_next_fn(self.page_indices['structure.read_xyz'], self.wizard_page_after_structure_read) # The spectrum.read_spins page. page = uf_store['spectrum.read_spins'].create_page(self.wizard) self.page_indices['spectrum.read_spins'] = self.wizard.add_page(page, skip_button=True) self.wizard.set_seq_next_fn(self.page_indices['spectrum.read_spins'], self.wizard_page_after_sequence_read) # The structure.load_spins page. page = uf_store['structure.load_spins'].create_page(self.wizard) self.page_indices['structure.load_spins'] = self.wizard.add_page(page) # The termination page. page = Finish_page(self.wizard) self.page_indices['fin'] = self.wizard.add_page(page, apply_button=False, skip_button=False) # Reset the cursor. if wx.IsBusy(): wx.EndBusyCursor() # Run the wizard. self.wizard.run() def setup_window(self): """Set up the window. @return: The sizer object. @rtype: wx.Sizer instance """ # Set the frame title. self.SetTitle("The spin viewer") # Use a box sizer for packing the shell. sizer = wx.BoxSizer(wx.VERTICAL) self.SetSizer(sizer) # Close the window cleanly (hide so it can be reopened). self.Bind(wx.EVT_CLOSE, self.handler_close) # Set the default size of the controller. self.SetSize((self.size_x, self.size_y)) # Return the sizer. return sizer def toolbar(self): """Create the toolbar.""" # Init. self.bar = self.CreateToolBar(wx.TB_HORIZONTAL|wx.TB_FLAT|wx.TB_TEXT) # The spin loading button. self.spin_loader_id = wx.NewId() tooltip = "Load spins from either a sequence file or from a 3D structure file." self.bar.AddLabelTool(self.spin_loader_id, "Load spins", wx.Bitmap(fetch_icon('relax.spin', '32x32'), wx.BITMAP_TYPE_ANY), bmpDisabled=wx.Bitmap(fetch_icon('relax.spin_grey', '32x32'), wx.BITMAP_TYPE_ANY), shortHelp=tooltip, longHelp=tooltip) self.Bind(wx.EVT_TOOL, self.load_spins_wizard, id=self.spin_loader_id) # A separator. self.bar.AddSeparator() # The refresh button. id = wx.NewId() tooltip = "Refresh the spin view." self.bar.AddLabelTool(id, "Refresh", wx.Bitmap(fetch_icon('oxygen.actions.view-refresh', '32x32'), wx.BITMAP_TYPE_ANY), shortHelp=tooltip, longHelp=tooltip) self.Bind(wx.EVT_TOOL, self.refresh, id=id) # A separator. self.bar.AddSeparator() # The pipe text. text = wx.StaticText(self.bar, -1, ' Current data pipe: ', style=wx.ALIGN_LEFT) self.bar.AddControl(text) # The pipe selection. self.pipe_name = wx.ComboBox(self.bar, -1, "", style=wx.CB_DROPDOWN|wx.CB_READONLY, choices=[]) self.bar.AddControl(self.pipe_name) self.Bind(wx.EVT_COMBOBOX, self.update_pipes, self.pipe_name) # Build the toolbar. self.bar.Realize() def uf_call(self, event=None): """Catch the user function call to properly specify the parent window. @keyword event: The wx event. @type event: wx event """ # The user function ID. uf_id = event.GetId() # Get the user function name. name = uf_store.get_uf(uf_id) # Call the user function GUI object. uf_store[name](event=event, wx_parent=self) def update_pipes(self, event=None): """Update the spin view data pipe selector. @keyword event: The wx event. @type event: wx event """ # Change the cursor to busy. wx.BeginBusyCursor() # Init. pipe_switch = False # The selected pipe. if event: # The name of the selected pipe. pipe = gui_to_str(self.pipe_name.GetString(event.GetSelection())) # A pipe change. if pipe != cdp_name(): pipe_switch = True else: pipe = cdp_name() if not pipe: pipe = '' # Clear the previous data. self.pipe_name.Clear() # The list of pipe names. for name in pipe_names(): self.pipe_name.Append(str_to_gui(name)) # Switch. if pipe_switch: # Switch data pipes. self.gui.interpreter.apply('pipe.switch', pipe) # Update the tree view. self.tree_panel.update() # Set the pipe name to the cdp. self.pipe_name.SetValue(str_to_gui(pipe)) # Reset the cursor. if wx.IsBusy(): wx.EndBusyCursor() def wizard_page_after_load_method(self): """Set the page after the load method choice. @return: The index of the next page. @rtype: int """ # Go to the sequence.read page. if self.page_method.selection == 'sequence': return self.page_indices['sequence.read'] # Go to the structure.read_pdb page. elif self.page_method.selection == 'new pdb': return self.page_indices['structure.read_pdb'] # Go to the structure.read_xyz page. elif self.page_method.selection == 'new xyz': return self.page_indices['structure.read_xyz'] # Go to the spectrum.read_spins page. elif self.page_method.selection == 'new spectrum': return self.page_indices['spectrum.read_spins'] # Skip to the structure.load_spins page. elif self.page_method.selection == 'preload': return self.page_indices['structure.load_spins'] def wizard_page_after_sequence_read(self): """Set the page after the sequence.read user function page. @return: The index of the last page. @rtype: int """ # Return the index of the terminal page. return self.page_indices['fin'] def wizard_page_after_structure_read(self): """Set the page after the structure.read_* user function pages. @return: The index of the structure.load_spins page. @rtype: int """ # Return the index of the terminal page. return self.page_indices['structure.load_spins']
class Spin_view_window(wx.Frame): """A window element for the tree view.""" def __init__(self, *args, **kwds): """Set up the relax prompt.""" # Store the parent object. self.gui = kwds.pop('parent') # Create GUI elements kwds["style"] = wx.DEFAULT_FRAME_STYLE if not status.debug and status.wx_info["os"] != 'darwin': kwds["style"] = kwds["style"] | wx.MAXIMIZE wx.Frame.__init__(self, *args, **kwds) # Force the main window to start maximised (needed for MS Windows). if not status.debug and status.wx_info["os"] != 'darwin': self.Maximize() # Set up the window icon. self.SetIcons(relax_icons) # Some default values. self.size_x = 1000 self.size_y = 750 # Set up the window. sizer = self.setup_window() # Create a menu. self._create_menu() # Build the toolbar. self.toolbar() # The splitter window. splitter = Tree_splitter(self.gui, self, -1) sizer.Add(splitter, 1, wx.EXPAND|wx.ALL, 0) # Initialise observer name. self.name = 'spin viewer' def _activate(self): """Activate or deactivate certain elements in response to the execution lock.""" # Flag for enabling or disabling the elements. enable = False if not status.exec_lock.locked(): enable = True # Loop over the menus. for menu, label in self.menubar.GetMenus(): # Loop over the menu items. for item in menu.GetMenuItems(): wx.CallAfter(item.Enable, enable) # The spin loader. wx.CallAfter(self.bar.EnableTool, TB_SPIN_LOADER_ID, enable) # The pipe selector. wx.CallAfter(self.pipe_name.Enable, enable) def _create_menu(self): """Build a menu for the window.""" # Create the menu bar GUI item and add it to the main frame. self.menubar = wx.MenuBar() if status.show_gui: self.SetMenuBar(self.menubar) # The user function menus. self.menu_uf_ids = build_uf_menus(parent=self, menubar=self.menubar) def Destroy(self, event=None): """Cleanly destroy the spin viewer window. @keyword event: The wx event. @type event: wx event """ # First unregister the methods from the observers. status.observers.gui_uf.unregister(self.name) status.observers.pipe_alteration.unregister(self.name) status.observers.exec_lock.unregister(self.name) # Destroy the spin loading wizard, if it exists. if hasattr(self, 'wizard'): self.wizard.Destroy() del self.wizard # Destroy all children of the window. super(Spin_view_window, self).DestroyChildren() # Destroy the spin viewer window. super(Spin_view_window, self).Destroy() def Show(self, show=True): """Change the behaviour of showing the window to update the content. @keyword show: A flag which is True shows the window. @type show: bool """ # Register a few methods in the observer objects. status.observers.gui_uf.register(self.name, self.refresh, method_name='ref') status.observers.pipe_alteration.register(self.name, self.refresh, method_name='ref') status.observers.exec_lock.register(self.name, self._activate, method_name='_activate') # First update. self.refresh() # Activate or deactivate the frame. self._activate() # Then show the window using the base class method. if status.show_gui: super(Spin_view_window, self).Show(show) def refresh(self, event=None): """Event handler for the refresh action (thread safe). @keyword event: The wx event. @type event: wx event """ # Thread safe. wx.CallAfter(self.refresh_safe) def refresh_safe(self): """Refresh the spin viewer window.""" # Change the cursor to busy. wx.BeginBusyCursor() # Update the data pipe selector. self.update_pipes() # Update the tree. self.tree_panel.update() # Redisplay the container. self.container.display(self.tree_panel.get_info()) # Reset the cursor. if wx.IsBusy(): wx.EndBusyCursor() def handler_close(self, event=None): """Event handler for the close window action. @keyword event: The wx event. @type event: wx event """ # Unregister the methods from the observers to avoid unnecessary updating. status.observers.gui_uf.unregister(self.name) status.observers.pipe_alteration.unregister(self.name) status.observers.exec_lock.unregister(self.name) # Close the window. self.Hide() def load_spins_wizard(self, event=None): """The spin loading wizard. @keyword event: The wx event. @type event: wx event """ # No current data pipe. if not cdp_name(): gui_raise(RelaxNoPipeError()) return # Change the cursor to busy. wx.BeginBusyCursor() # Destroy the spin loading wizard, if it exists. if hasattr(self, 'wizard'): self.wizard.Destroy() # Initialise a wizard. self.wizard = Wiz_window(parent=self, size_x=1000, size_y=750, title="Load spins") self.page_indices = {} # The loading method page. self.page_method = Load_method_page(self.wizard) self.page_indices['method'] = self.wizard.add_page(self.page_method, apply_button=True, skip_button=False) self.wizard.set_seq_next_fn(self.page_indices['method'], self.wizard_page_after_load_method) # The sequence.read page. page = uf_store['sequence.read'].create_page(self.wizard) self.page_indices['sequence.read'] = self.wizard.add_page(page, skip_button=True) self.wizard.set_seq_next_fn(self.page_indices['sequence.read'], self.wizard_page_after_sequence_read) # The structure.read_pdb page. page = uf_store['structure.read_pdb'].create_page(self.wizard) self.page_indices['structure.read_pdb'] = self.wizard.add_page(page, skip_button=True) self.wizard.set_seq_next_fn(self.page_indices['structure.read_pdb'], self.wizard_page_after_structure_read) # The structure.read_xyz page. page = uf_store['structure.read_xyz'].create_page(self.wizard) self.page_indices['structure.read_xyz'] = self.wizard.add_page(page, skip_button=True) self.wizard.set_seq_next_fn(self.page_indices['structure.read_xyz'], self.wizard_page_after_structure_read) # The spectrum.read_spins page. page = uf_store['spectrum.read_spins'].create_page(self.wizard) self.page_indices['spectrum.read_spins'] = self.wizard.add_page(page, skip_button=True) self.wizard.set_seq_next_fn(self.page_indices['spectrum.read_spins'], self.wizard_page_after_sequence_read) # The structure.load_spins page. page = uf_store['structure.load_spins'].create_page(self.wizard) self.page_indices['structure.load_spins'] = self.wizard.add_page(page) # The termination page. page = Finish_page(self.wizard) self.page_indices['fin'] = self.wizard.add_page(page, apply_button=False, skip_button=False) # Reset the cursor. if wx.IsBusy(): wx.EndBusyCursor() # Run the wizard. self.wizard.run() def setup_window(self): """Set up the window. @return: The sizer object. @rtype: wx.Sizer instance """ # Set the frame title. self.SetTitle("The spin viewer") # Use a box sizer for packing the shell. sizer = wx.BoxSizer(wx.VERTICAL) self.SetSizer(sizer) # Close the window cleanly (hide so it can be reopened). self.Bind(wx.EVT_CLOSE, self.handler_close) # Set the default size of the controller. self.SetSize((self.size_x, self.size_y)) # Return the sizer. return sizer def toolbar(self): """Create the toolbar.""" # Init. self.bar = self.CreateToolBar(wx.TB_HORIZONTAL|wx.TB_FLAT|wx.TB_TEXT) # The spin loading button. tooltip = "Load spins from either a sequence file or from a 3D structure file." self.bar.AddLabelTool(TB_SPIN_LOADER_ID, "Load spins", wx.Bitmap(fetch_icon('relax.spin', '32x32'), wx.BITMAP_TYPE_ANY), bmpDisabled=wx.Bitmap(fetch_icon('relax.spin_grey', '32x32'), wx.BITMAP_TYPE_ANY), shortHelp=tooltip, longHelp=tooltip) self.Bind(wx.EVT_TOOL, self.load_spins_wizard, id=TB_SPIN_LOADER_ID) # A separator. self.bar.AddSeparator() # The refresh button. tooltip = "Refresh the spin view." self.bar.AddLabelTool(TB_REFRESH, "Refresh", wx.Bitmap(fetch_icon('oxygen.actions.view-refresh', '32x32'), wx.BITMAP_TYPE_ANY), shortHelp=tooltip, longHelp=tooltip) self.Bind(wx.EVT_TOOL, self.refresh, id=TB_REFRESH) # A separator. self.bar.AddSeparator() # The pipe text. text = wx.StaticText(self.bar, -1, ' Current data pipe: ', style=wx.ALIGN_LEFT) self.bar.AddControl(text) # The pipe selection. self.pipe_name = wx.ComboBox(self.bar, -1, "", style=wx.CB_DROPDOWN|wx.CB_READONLY, choices=[]) self.bar.AddControl(self.pipe_name) self.Bind(wx.EVT_COMBOBOX, self.update_pipes, self.pipe_name) # Build the toolbar. self.bar.Realize() def uf_call(self, event=None): """Catch the user function call to properly specify the parent window. @keyword event: The wx event. @type event: wx event """ # The user function ID. uf_id = event.GetId() # Get the user function name. name = uf_store.get_uf(uf_id) # Call the user function GUI object. uf_store[name](event=event, wx_parent=self) def update_pipes(self, event=None): """Update the spin view data pipe selector. @keyword event: The wx event. @type event: wx event """ # Change the cursor to busy. wx.BeginBusyCursor() # Init. pipe_switch = False # The selected pipe. if event: # The name of the selected pipe. pipe = gui_to_str(self.pipe_name.GetString(event.GetSelection())) # A pipe change. if pipe != cdp_name(): pipe_switch = True else: pipe = cdp_name() if not pipe: pipe = '' # Clear the previous data. self.pipe_name.Clear() # The list of pipe names. for name in pipe_names(): self.pipe_name.Append(str_to_gui(name)) # Switch. if pipe_switch: # Switch data pipes. self.gui.interpreter.apply('pipe.switch', pipe) # Update the tree view. self.tree_panel.update() # Set the pipe name to the cdp. self.pipe_name.SetValue(str_to_gui(pipe)) # Reset the cursor. if wx.IsBusy(): wx.EndBusyCursor() def wizard_page_after_load_method(self): """Set the page after the load method choice. @return: The index of the next page. @rtype: int """ # Go to the sequence.read page. if self.page_method.selection == 'sequence': return self.page_indices['sequence.read'] # Go to the structure.read_pdb page. elif self.page_method.selection == 'new pdb': return self.page_indices['structure.read_pdb'] # Go to the structure.read_xyz page. elif self.page_method.selection == 'new xyz': return self.page_indices['structure.read_xyz'] # Go to the spectrum.read_spins page. elif self.page_method.selection == 'new spectrum': return self.page_indices['spectrum.read_spins'] # Skip to the structure.load_spins page. elif self.page_method.selection == 'preload': return self.page_indices['structure.load_spins'] def wizard_page_after_sequence_read(self): """Set the page after the sequence.read user function page. @return: The index of the last page. @rtype: int """ # Return the index of the terminal page. return self.page_indices['fin'] def wizard_page_after_structure_read(self): """Set the page after the structure.read_* user function pages. @return: The index of the structure.load_spins page. @rtype: int """ # Return the index of the terminal page. return self.page_indices['structure.load_spins']