source: sasview/guiframe/gui_manager.py @ 261b864

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

working on statusbar

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