source: sasview/guiframe/gui_manager.py @ f43827cc

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalccostrafo411magnetic_scattrelease-4.1.1release-4.1.2release-4.2.2release_4.0.1ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249ticket885unittest-saveload
Last change on this file since f43827cc was af20f6b, checked in by Mathieu Doucet <doucetm@…>, 15 years ago

guiframe: removed version checking

  • Property mode set to 100644
File size: 33.7 KB
Line 
1"""
2This software was developed by the University of Tennessee as part of the
3Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
4project funded by the US National Science Foundation.
5
6See the license text in license.txt
7
8copyright 2008, University of Tennessee
9
10How-to build an application using guiframe:
11
12 1- Write a main application script along the lines of dummyapp.py
13 2- Write a config script along the lines of config.py, and name it local_config.py
14 3- Write your plug-ins and place them in a directory called "perspectives".
15     - Look at local_perspectives/plotting for an example of a plug-in.
16     - A plug-in should define a class called Plugin. See abstract class below.
17
18"""
19#TODO: rewrite the status bar monstrosity
20
21import wx
22import wx.aui
23import os, sys
24import xml
25try:
26    # Try to find a local config
27    import imp
28    path = os.getcwd()
29    if(os.path.isfile("%s/%s.py" % (path, 'local_config'))) or \
30      (os.path.isfile("%s/%s.pyc" % (path, 'local_config'))):
31            fObj, path, descr = imp.find_module('local_config', [path])
32            config = imp.load_module('local_config', fObj, path, descr) 
33    else:
34        # Try simply importing local_config
35        import local_config as config
36except:
37    # Didn't find local config, load the default
38    import config
39   
40from sans.guicomm.events import EVT_STATUS
41from sans.guicomm.events import EVT_NEW_PLOT,EVT_SLICER_PARS_UPDATE
42
43import warnings
44warnings.simplefilter("ignore")
45
46import logging
47
48class Plugin:
49    """
50        This class defines the interface for a Plugin class
51        that can be used by the gui_manager.
52       
53        Plug-ins should be placed in a sub-directory called "perspectives".
54        For example, a plug-in called Foo should be place in "perspectives/Foo".
55        That directory contains at least two files:
56            perspectives/Foo/__init.py contains two lines:
57           
58                PLUGIN_ID = "Foo plug-in 1.0"
59                from Foo import *
60               
61            perspectives/Foo/Foo.py contains the definition of the Plugin
62            class for the Foo plug-in. The interface of that Plugin class
63            should follow the interface of the class you are looking at.
64           
65        See dummyapp.py for a plugin example.
66    """
67   
68    def __init__(self, name="Test_plugin"):
69        """
70            Abstract class for gui_manager Plugins.
71        """
72        ## Plug-in name. It will appear on the application menu.
73        self.sub_menu = name     
74       
75        ## Reference to the parent window. Filled by get_panels() below.
76        self.parent = None
77       
78        ## List of panels that you would like to open in AUI windows
79        #  for your plug-in. This defines your plug-in "perspective"
80        self.perspective = []
81       
82       
83    def populate_menu(self, id, parent):
84        """
85            Create and return the list of application menu
86            items for the plug-in.
87           
88            @param id: deprecated. Un-used.
89            @param parent: parent window
90            @return: plug-in menu
91        """
92        return []
93   
94    def get_panels(self, parent):
95        """
96            Create and return the list of wx.Panels for your plug-in.
97            Define the plug-in perspective.
98           
99            Panels should inherit from DefaultPanel defined below,
100            or should present the same interface. They must define
101            "window_caption" and "window_name".
102           
103            @param parent: parent window
104            @return: list of panels
105        """
106        ## Save a reference to the parent
107        self.parent = parent
108       
109        # Return the list of panels
110        return []
111   
112    def get_tools(self):
113        """
114            Returns a set of menu entries for tools
115        """
116        return []
117       
118   
119    def get_context_menu(self, graph=None):
120        """
121            This method is optional.
122       
123            When the context menu of a plot is rendered, the
124            get_context_menu method will be called to give you a
125            chance to add a menu item to the context menu.
126           
127            A ref to a Graph object is passed so that you can
128            investigate the plot content and decide whether you
129            need to add items to the context menu. 
130           
131            This method returns a list of menu items.
132            Each item is itself a list defining the text to
133            appear in the menu, a tool-tip help text, and a
134            call-back method.
135           
136            @param graph: the Graph object to which we attach the context menu
137            @return: a list of menu items with call-back function
138        """
139        return []
140   
141    def get_perspective(self):
142        """
143            Get the list of panel names for this perspective
144        """
145        return self.perspective
146   
147    def on_perspective(self, event):
148        """
149            Call back function for the perspective menu item.
150            We notify the parent window that the perspective
151            has changed.
152            @param event: menu event
153        """
154        self.parent.set_perspective(self.perspective)
155   
156    def post_init(self):
157        """
158            Post initialization call back to close the loose ends
159        """
160        pass
161   
162    def set_default_perspective(self):
163        """
164           Call back method that True to notify the parent that the current plug-in
165           can be set as default  perspective.
166           when returning False, the plug-in is not candidate for an automatic
167           default perspective setting
168        """
169        return False
170
171class ViewerFrame(wx.Frame):
172    """
173        Main application frame
174    """
175    def __init__(self, parent, id, title, window_height=300, window_width=300):
176        """
177            Initialize the Frame object
178        """
179        from local_perspectives.plotting import plotting
180        wx.Frame.__init__(self, parent, id, title, wx.DefaultPosition, size=(window_width, window_height))
181        # Preferred window size
182        self._window_height = window_height
183        self._window_width  = window_width
184       
185        # Logging info
186        logging.basicConfig(level=logging.DEBUG,
187                    format='%(asctime)s %(levelname)s %(message)s',
188                    filename='sans_app.log',
189                    filemode='w')       
190        path = os.path.dirname(__file__)
191        temp_path= os.path.join(path,'images')
192        ico_file = os.path.join(temp_path,'ball.ico')
193        if os.path.isfile(ico_file):
194            self.SetIcon(wx.Icon(ico_file, wx.BITMAP_TYPE_ICO))
195        else:
196            temp_path= os.path.join(os.getcwd(),'images')
197            ico_file = os.path.join(temp_path,'ball.ico')
198            if os.path.isfile(ico_file):
199                self.SetIcon(wx.Icon(ico_file, wx.BITMAP_TYPE_ICO))
200       
201        ## Application manager
202        self.app_manager = None
203       
204        ## Find plug-ins
205        # Modify this so that we can specify the directory to look into
206        self.plugins =[]
207        self.plugins.append(plotting.Plugin())
208        self.plugins += self._find_plugins()
209     
210        ## List of panels
211        self.panels = {}
212
213        ## Next available ID for wx gui events
214        #TODO:  No longer used - remove all calls to this
215        self.next_id = 20000
216
217        # Default locations
218        self._default_save_location = os.getcwd()       
219
220        # Welcome panel
221        self.defaultPanel = None
222
223        # Check for update
224        #self._check_update(None)
225        ## maximum number of opened files' paths to store
226        self.n_maxfileopen =  2
227        ## number of file open
228        self.n_fileOpen=0
229        ## list of path of open files
230        self.filePathList=[]
231        ## list of open file with name form menu
232        #self._saveOpenData()
233        ## Dictionary of open file where keys are filename  and values are number of copy of data plotted
234        ## using the same loaded file
235        self.indice_load_data={}
236        # Register the close event so it calls our own method
237        wx.EVT_CLOSE(self, self._onClose)
238        # Register to status events
239        self.Bind(EVT_STATUS, self._on_status_event)
240   
241       
242    def build_gui(self):
243        # Set up the layout
244        self._setup_layout()
245       
246        # Set up the menu
247        self._setup_menus()
248       
249        #self.Fit()
250       
251        #self._check_update(None)
252             
253    def _setup_layout(self):
254        """
255            Set up the layout
256        """
257        # Status bar
258        from statusbar import MyStatusBar
259        self.sb = MyStatusBar(self,wx.ID_ANY)
260        self.SetStatusBar(self.sb)
261
262        # Add panel
263        self._mgr = wx.aui.AuiManager(self)
264        self._mgr.SetDockSizeConstraint(0.5, 0.5) 
265       
266        # Load panels
267        self._load_panels()
268       
269        self._mgr.Update()
270
271    def add_perspective(self, plugin):
272        """
273            Add a perspective if it doesn't already
274            exist.
275        """
276        is_loaded = False
277        for item in self.plugins:
278             if plugin.__class__==item.__class__:
279                 print "Plugin %s already loaded" % plugin.__class__.__name__
280                 is_loaded = True
281                 
282        if not is_loaded:
283            self.plugins.append(plugin)
284     
285    def _find_plugins(self, dir="perspectives"):
286        """
287            Find available perspective plug-ins
288            @param dir: directory in which to look for plug-ins
289            @return: list of plug-ins
290        """
291        import imp
292       
293        plugins = []
294        # Go through files in panels directory
295        try:
296            list = os.listdir(dir)
297            ## the default panel is the panel is the last plugin added
298            for item in list:
299                toks = os.path.splitext(os.path.basename(item))
300                name = None
301                if not toks[0] == '__init__':
302                   
303                    if toks[1]=='.py' or toks[1]=='':
304                        name = toks[0]
305               
306                    path = [os.path.abspath(dir)]
307                    file = None
308                    try:
309                        if toks[1]=='':
310                            mod_path = '.'.join([dir, name])
311                            module = __import__(mod_path, globals(), locals(), [name])
312                        else:
313                            (file, path, info) = imp.find_module(name, path)
314                            module = imp.load_module( name, file, item, info )
315                        if hasattr(module, "PLUGIN_ID"):
316                            try:
317                                plugins.append(module.Plugin())
318                                logging.info("Found plug-in: %s" % module.PLUGIN_ID)
319                            except:
320                                config.printEVT("Error accessing PluginPanel in %s\n  %s" % (name, sys.exc_value))
321                       
322                    except:
323                        print sys.exc_value
324                        logging.error("ViewerFrame._find_plugins: %s" % sys.exc_value)
325                    finally:
326                        if not file==None:
327                            file.close()
328        except:
329            # Should raise and catch at a higher level and display error on status bar
330            pass   
331        return plugins
332   
333    def set_welcome_panel(self, panel_class):
334        """
335           Sets the default panel as the given welcome panel
336           @param panel_class: class of the welcome panel to be instantiated
337        """
338        self.defaultPanel    = panel_class(self, -1, style=wx.RAISED_BORDER)
339       
340    def _load_panels(self):
341        """
342            Load all panels in the panels directory
343        """
344       
345        # Look for plug-in panels
346        panels = []   
347        for item in self.plugins:
348            if hasattr(item, "get_panels"):
349                ps = item.get_panels(self)
350                panels.extend(ps)
351
352        # Show a default panel with some help information
353        # It also sets the size of the application windows
354        #TODO: Use this for slpash screen
355        if self.defaultPanel is None:
356            self.defaultPanel    = DefaultPanel(self, -1, style=wx.RAISED_BORDER)
357           
358        self.panels["default"] = self.defaultPanel
359       
360        self._mgr.AddPane(self.defaultPanel, wx.aui.AuiPaneInfo().
361                              Name("default").
362                              CenterPane().
363                              # This is where we set the size of the application window
364                              BestSize(wx.Size(self._window_width, self._window_height)).
365                              #MinSize(wx.Size(self._window_width, self._window_height)).
366                              Show())
367     
368
369        # Add the panels to the AUI manager
370        for panel_class in panels:
371            p = panel_class
372            id = wx.NewId()
373           
374            # Check whether we need to put this panel
375            # in the center pane
376            if hasattr(p, "CENTER_PANE") and p.CENTER_PANE:
377                if p.CENTER_PANE:
378                    self.panels[str(id)] = p
379                    self._mgr.AddPane(p, wx.aui.AuiPaneInfo().
380                                          Name(p.window_name).Caption(p.window_caption).
381                                          CenterPane().
382                                          #BestSize(wx.Size(550,600)).
383                                          #MinSize(wx.Size(500,500)).
384                                          Hide())
385            else:
386                self.panels[str(id)] = p
387                self._mgr.AddPane(p, wx.aui.AuiPaneInfo().
388                                  Name(p.window_name).Caption(p.window_caption).
389                                  Right().
390                                  Dock().
391                                  TopDockable().
392                                  BottomDockable().
393                                  LeftDockable().
394                                  RightDockable().
395                                  MinimizeButton().
396                                  Hide())
397                                  #BestSize(wx.Size(550,600)))
398                                  #MinSize(wx.Size(500,500)))                 
399     
400    def get_context_menu(self, graph=None):
401        """
402            Get the context menu items made available
403            by the different plug-ins.
404            This function is used by the plotting module
405        """
406        menu_list = []
407        for item in self.plugins:
408            if hasattr(item, "get_context_menu"):
409                menu_list.extend(item.get_context_menu(graph))
410           
411        return menu_list
412       
413    def popup_panel(self, p):
414        """
415            Add a panel object to the AUI manager
416            @param p: panel object to add to the AUI manager
417            @return: ID of the event associated with the new panel [int]
418        """
419       
420        ID = wx.NewId()
421        self.panels[str(ID)] = p
422       
423        count = 0
424        for item in self.panels:
425            if self.panels[item].window_name.startswith(p.window_name): 
426                count += 1
427       
428        windowname = p.window_name
429        caption = p.window_caption
430       
431        if count>0:
432            windowname += str(count+1)
433            caption += (' '+str(count))
434         
435        p.window_name = windowname
436        p.window_caption = caption
437           
438        self._mgr.AddPane(p, wx.aui.AuiPaneInfo().
439                          Name(windowname).Caption(caption).
440                          Floatable().
441                          #Float().
442                          Right().
443                          Dock().
444                          TopDockable().
445                          BottomDockable().
446                          LeftDockable().
447                          RightDockable().
448                          MinimizeButton().
449                          #Hide().
450                          #Show().
451                          Resizable(True).
452                          # Use a large best size to make sure the AUI manager
453                          # takes all the available space
454                          BestSize(wx.Size(400,400)))
455        pane = self._mgr.GetPane(windowname)
456        self._mgr.MaximizePane(pane)
457        self._mgr.RestoreMaximizedPane()
458       
459       
460        # Register for showing/hiding the panel
461       
462        wx.EVT_MENU(self, ID, self._on_view)
463       
464        self._mgr.Update()
465        return ID
466       
467    def _setup_menus(self):
468        """
469            Set up the application menus
470        """
471        # Menu
472        menubar = wx.MenuBar()
473       
474        # File menu
475        self.filemenu = wx.Menu()
476       
477        id = wx.NewId()
478        self.filemenu.Append(id, '&Open', 'Open a file')
479        wx.EVT_MENU(self, id, self._on_open)
480        #self.filemenu.AppendSeparator()
481       
482        id = wx.NewId()
483        self.filemenu.Append(id,'&Quit', 'Exit') 
484        wx.EVT_MENU(self, id, self.Close)
485       
486        # Add sub menus
487        menubar.Append(self.filemenu,  '&File')
488       
489        # Window menu
490        # Attach a menu item for each panel in our
491        # panel list that also appears in a plug-in.
492       
493        # Only add the panel menu if there is only one perspective and
494        # it has more than two panels.
495        # Note: the first plug-in is always the plotting plug-in. The first application
496        # plug-in is always the second one in the list.
497        if len(self.plugins)==2:
498            plug = self.plugins[1]
499            pers = plug.get_perspective()
500       
501            if len(pers)>1:
502                viewmenu = wx.Menu()
503                for item in self.panels:
504                    if item == 'default':
505                        continue
506                    panel = self.panels[item]
507                    if panel.window_name in pers:
508                        viewmenu.Append(int(item), panel.window_caption, "Show %s window" % panel.window_caption)
509                        wx.EVT_MENU(self, int(item), self._on_view)
510                menubar.Append(viewmenu, '&Window')
511
512        # Perspective
513        # Attach a menu item for each defined perspective.
514        # Only add the perspective menu if there are more than one perspectives
515        n_perspectives = 0
516        for plug in self.plugins:
517            if len(plug.get_perspective()) > 0:
518                n_perspectives += 1
519       
520        if n_perspectives>1:
521            p_menu = wx.Menu()
522            for plug in self.plugins:
523                if len(plug.get_perspective()) > 0:
524                    id = wx.NewId()
525                    p_menu.Append(id, plug.sub_menu, "Switch to %s perspective" % plug.sub_menu)
526                    wx.EVT_MENU(self, id, plug.on_perspective)
527            menubar.Append(p_menu,   '&Perspective')
528 
529        # Tools menu
530        # Go through plug-ins and find tools to populate the tools menu
531        toolsmenu = None
532        for item in self.plugins:
533            if hasattr(item, "get_tools"):
534                for tool in item.get_tools():
535                    # Only create a menu if we have at least one tool
536                    if toolsmenu is None:
537                        toolsmenu = wx.Menu()
538                    id = wx.NewId()
539                   
540                    toolsmenu.Append(id, tool[0], tool[1])
541                    wx.EVT_MENU(self, id, tool[2])
542        if toolsmenu is not None:
543            menubar.Append(toolsmenu, '&Tools')
544 
545        # Help menu
546        helpmenu = wx.Menu()
547        # add the welcome panel menu item
548        if self.defaultPanel is not None:
549            id = wx.NewId()
550            helpmenu.Append(id,'&Welcome', '')
551            helpmenu.AppendSeparator()
552            wx.EVT_MENU(self, id, self.show_welcome_panel)
553       
554        # Look for help item in plug-ins
555        for item in self.plugins:
556            if hasattr(item, "help"):
557                id = wx.NewId()
558                helpmenu.Append(id,'&%s help' % item.sub_menu, '')
559                wx.EVT_MENU(self, id, item.help)
560       
561        if config._do_aboutbox:
562            id = wx.NewId()
563            helpmenu.Append(id,'&About', 'Software information')
564            wx.EVT_MENU(self, id, self._onAbout)
565           
566        # Checking for updates needs major refactoring to work with py2exe
567        # We need to make sure it doesn't hang the application if the server
568        # is not up. We also need to make sure there's a proper executable to
569        # run if we spawn a new background process.
570        #id = wx.NewId()
571        #helpmenu.Append(id,'&Check for update', 'Check for the latest version of %s' % config.__appname__)
572        #wx.EVT_MENU(self, id, self._check_update)
573       
574        # Look for plug-in menus
575        # Add available plug-in sub-menus.
576        for item in self.plugins:
577            if hasattr(item, "populate_menu"):
578                for (self.next_id, menu, name) in item.populate_menu(self.next_id, self):
579                    menubar.Append(menu, name)
580                   
581
582        menubar.Append(helpmenu, '&Help')
583         
584        self.SetMenuBar(menubar)
585       
586       
587       
588    def _on_status_event(self, evt):
589        """
590            Display status message
591        """
592        #self.sb.clear_gauge( msg="")
593        mythread=None
594        mytype= None
595        if hasattr(evt, "curr_thread"):
596            mythread= evt.curr_thread
597        if hasattr(evt, "type"):
598            mytype= evt.type
599        self.sb.set_status( type=mytype,msg=str(evt.status),thread=mythread)
600       
601
602       
603    def _on_view(self, evt):
604        """
605            A panel was selected to be shown. If it's not already
606            shown, display it.
607            @param evt: menu event
608        """
609        self.show_panel(evt.GetId())
610       
611    def on_close_welcome_panel(self):
612        """
613            Close the welcome panel
614        """
615        if self.defaultPanel is None:
616            return 
617        self._mgr.GetPane(self.panels["default"].window_name).Hide()
618        self._mgr.Update()
619        # set a default perspective
620        self.set_default_perspective()
621       
622    def show_welcome_panel(self, event):
623        """   
624            Display the welcome panel
625        """
626        if self.defaultPanel is None:
627            return 
628        for id in self.panels.keys():
629            if self._mgr.GetPane(self.panels[id].window_name).IsShown():
630                self._mgr.GetPane(self.panels[id].window_name).Hide()
631        # Show default panel
632        if not self._mgr.GetPane(self.panels["default"].window_name).IsShown():
633            self._mgr.GetPane(self.panels["default"].window_name).Show()
634       
635        self._mgr.Update()
636       
637    def show_panel(self, uid):
638        """
639            Shows the panel with the given id
640            @param uid: unique ID number of the panel to show
641        """
642        ID = str(uid)
643        config.printEVT("show_panel: %s" % ID)
644        if ID in self.panels.keys():
645            if not self._mgr.GetPane(self.panels[ID].window_name).IsShown():
646                self._mgr.GetPane(self.panels[ID].window_name).Show()
647                # Hide default panel
648                self._mgr.GetPane(self.panels["default"].window_name).Hide()
649           
650               
651            self._mgr.Update()
652   
653    def _on_open(self, event):
654   
655        from data_loader import plot_data
656        path = self.choose_file()
657
658        if path ==None:
659            return
660        if path and os.path.isfile(path):
661            plot_data(self, path)
662           
663       
664       
665    def _onClose(self, event):
666        """
667            Store info to retrieve in xml before closing the application
668        """
669        try:
670            doc = xml.dom.minidom.Document()
671            main_node = doc.createElement("file Path")
672           
673            doc.appendChild(main_node)
674       
675            for item in self.filePathList:
676                id, menuitem_name , path, title = item
677                pt1 = doc.createElement("File")
678                pt1.setAttribute("name", menuitem_name)
679                pt2 = doc.createElement("path")
680                pt2.appendChild(doc.createTextNode(str(path)))
681                pt1.appendChild(pt2)
682                pt3 = doc.createElement("title")
683                pt3.appendChild(doc.createTextNode(str(title)))
684                pt1.appendChild(pt3)
685               
686                main_node.appendChild(pt1)
687               
688               
689            fd = open("fileOpened.xml",'w')
690            fd.write(doc.toprettyxml())
691            fd.close()
692        except:
693            pass
694       
695        import sys
696        wx.Exit()
697        sys.exit()
698                   
699                   
700    def Close(self, event=None):
701        """
702            Quit the application
703        """
704        import sys
705        wx.Frame.Close(self)
706        wx.Exit()
707        sys.exit()
708
709 
710    def _check_update(self, event=None): 
711        """
712            Check with the deployment server whether a new version
713            of the application is available.
714            A thread is started for the connecting with the server. The thread calls
715            a call-back method when the current version number has been obtained.
716        """
717        if hasattr(config, "__update_URL__"):
718            import version
719            checker = version.VersionThread(config.__update_URL__, self._process_version, baggage=event==None)
720            checker.start() 
721   
722    def _process_version(self, version, standalone=True):
723        """
724            Call-back method for the process of checking for updates.
725            This methods is called by a VersionThread object once the current
726            version number has been obtained. If the check is being done in the
727            background, the user will not be notified unless there's an update.
728           
729            @param version: version string
730            @param standalone: True of the update is being checked in the background, False otherwise.
731        """
732        try:
733            if cmp(version, config.__version__)>0:
734                self.SetStatusText("Version %s is available! See the Help menu to download it." % version)
735                if not standalone:
736                    import webbrowser
737                    webbrowser.open(config.__download_page__)
738            else:
739                if not standalone:
740                    self.SetStatusText("You have the latest version of %s" % config.__appname__)
741        except:
742            logging.error("guiframe: could not get latest application version number\n  %s" % sys.exc_value)
743            if not standalone:
744                self.SetStatusText("Could not connect to the application server. Please try again later.")
745                   
746       
747    def _onAbout(self, evt):
748        """
749            Pop up the about dialog
750            @param evt: menu event
751        """
752        if config._do_aboutbox:
753            import aboutbox 
754            dialog = aboutbox.DialogAbout(None, -1, "")
755            dialog.ShowModal()           
756           
757    def _onreloaFile(self, event): 
758        """
759            load a data previously opened
760        """
761        from data_loader import plot_data
762        for item in self.filePathList:
763            id, menuitem_name , path, title = item
764            if id == event.GetId():
765                if path and os.path.isfile(path):
766                    plot_data(self, path)
767                    break
768           
769       
770    def set_manager(self, manager):
771        """
772            Sets the application manager for this frame
773            @param manager: frame manager
774        """
775        self.app_manager = manager
776       
777    def post_init(self):
778        """
779            This initialization method is called after the GUI
780            has been created and all plug-ins loaded. It calls
781            the post_init() method of each plug-in (if it exists)
782            so that final initialization can be done.
783        """
784        for item in self.plugins:
785            if hasattr(item, "post_init"):
786                item.post_init()
787       
788    def set_default_perspective(self):
789        """
790            Choose among the plugin the first plug-in that has
791            "set_default_perspective" method and its return value is True will be
792            as a default perspective when the welcome page is closed
793        """
794        for item in self.plugins:
795            if hasattr(item, "set_default_perspective"):
796                if item.set_default_perspective():
797                    item.on_perspective(event=None)
798                    return 
799           
800    def set_perspective(self, panels):
801        """
802            Sets the perspective of the GUI.
803            Opens all the panels in the list, and closes
804            all the others.
805           
806            @param panels: list of panels
807        """
808        for item in self.panels:
809            # Check whether this is a sticky panel
810            if hasattr(self.panels[item], "ALWAYS_ON"):
811                if self.panels[item].ALWAYS_ON:
812                    continue 
813           
814            if self.panels[item].window_name in panels:
815                if not self._mgr.GetPane(self.panels[item].window_name).IsShown():
816                    self._mgr.GetPane(self.panels[item].window_name).Show()
817            else:
818                if self._mgr.GetPane(self.panels[item].window_name).IsShown():
819                    self._mgr.GetPane(self.panels[item].window_name).Hide()
820   
821        self._mgr.Update()
822       
823    def choose_file(self, path=None):
824        """
825            Functionality that belongs elsewhere
826            Should add a hook to specify the preferred file type/extension.
827        """
828        #TODO: clean this up
829        from data_loader import choose_data_file
830       
831        # Choose a file path
832        if path==None:
833            path = choose_data_file(self, self._default_save_location)
834           
835        if not path==None:
836            try:
837                self._default_save_location = os.path.dirname(path)
838               
839                #self.n_fileOpen += 1
840                if self.n_fileOpen==1:
841                    pos= self.filemenu.GetMenuItemCount()-1
842                    #self.filemenu.InsertSeparator(pos )
843               
844                id = wx.NewId()
845                filename= os.path.basename(path)
846                dir= os.path.split(self._default_save_location)[1]
847                title= str(os.path.join(dir,filename )) 
848                menuitem_name = str(self.n_fileOpen)+". "+ title
849                position= self.filemenu.GetMenuItemCount()-2
850                #self.filemenu.Insert(id=id, pos= position,text=menuitem_name,help=str(path) )
851                #self.filePathList.append(( id, menuitem_name, path, title))
852                #wx.EVT_MENU(self, id, self._onreloaFile)
853               
854                ## construct menu item for open file
855                if self.n_fileOpen == self.n_maxfileopen +1:
856                    ## reach the maximun number of path to store
857                    self.n_fileOpen = 0
858                    id, menuitem_name , path, title = self.filePathList[0]
859                    self.filemenu.Delete(id)
860                    self.filePathList.pop(0)
861                    for item in self.filePathList:
862                        id, menuitem_name , path, title = item
863                        self.n_fileOpen += 1
864                        label = str(self.n_fileOpen)+". "+ title
865                        #self.filemenu.FindItemById(id).SetItemLabel(label)
866                       
867                         
868            except:
869                raise
870                #pass
871        return path
872   
873    def load_ascii_1D(self, path):
874        from data_loader import load_ascii_1D
875        return load_ascii_1D(path)
876                 
877class DefaultPanel(wx.Panel):
878    """
879        Defines the API for a panels to work with
880        the GUI manager
881    """
882    ## Internal nickname for the window, used by the AUI manager
883    window_name = "default"
884    ## Name to appear on the window title bar
885    window_caption = "Welcome panel"
886    ## Flag to tell the AUI manager to put this panel in the center pane
887    CENTER_PANE = True
888
889 
890# Toy application to test this Frame
891class ViewApp(wx.App):
892    def OnInit(self):
893        #from gui_manager import ViewerFrame
894        self.frame = ViewerFrame(None, -1, config.__appname__)   
895        self.frame.Show(True)
896
897        if hasattr(self.frame, 'special'):
898            self.frame.special.SetCurrent()
899        self.SetTopWindow(self.frame)
900        return True
901   
902    def set_manager(self, manager):
903        """
904            Sets a reference to the application manager
905            of the GUI manager (Frame)
906        """
907        self.frame.set_manager(manager)
908       
909    def build_gui(self):
910        """
911            Build the GUI
912        """
913        self.frame.build_gui()
914        self.frame.post_init()
915       
916    def set_welcome_panel(self, panel_class):
917        """
918            Set the welcome panel
919            @param panel_class: class of the welcome panel to be instantiated
920        """
921        self.frame.set_welcome_panel(panel_class)
922       
923    def add_perspective(self, perspective):
924        """
925            Manually add a perspective to the application GUI
926        """
927        self.frame.add_perspective(perspective)
928       
929
930if __name__ == "__main__": 
931    app = ViewApp(0)
932    app.MainLoop()             
Note: See TracBrowser for help on using the repository browser.