source: sasview/guiframe/gui_manager.py @ a93f525

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 a93f525 was af47c8d, checked in by Gervaise Alina <gervyh@…>, 14 years ago

reverse guiframe

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