source: sasview/guiframe/gui_manager.py @ 7609f1a

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 7609f1a was b91c736, checked in by Gervaise Alina <gervyh@…>, 15 years ago

append more than one dat into the panel on focus

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