source: sasview/guiframe/gui_manager.py @ fd68aa9

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 fd68aa9 was fd68aa9, checked in by Mathieu Doucet <doucetm@…>, 16 years ago

fixed bug

  • Property mode set to 100644
File size: 20.1 KB
Line 
1"""
2This software was developed by the University of Tennessee as part of the
3Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
4project funded by the US National Science Foundation.
5
6See the license text in license.txt
7
8copyright 2008, University of Tennessee
9"""
10import wx
11import wx.aui
12import os, sys
13try:
14    # Try to find a local config
15    import imp
16    path = os.getcwd()
17    if(os.path.isfile("%s/%s.py" % (path, 'config'))) or \
18      (os.path.isfile("%s/%s.pyc" % (path, 'config'))):
19            fObj, path, descr = imp.find_module('config', [path])
20            config = imp.load_module('config', fObj, path, descr) 
21    else:
22        raise RuntimeError, "Look for default config"   
23except:
24    # Didn't find local config, load the default
25    import config
26from sans.guicomm.events import EVT_STATUS
27
28import warnings
29warnings.simplefilter("ignore")
30
31
32class ViewerFrame(wx.Frame):
33    """
34        Main application frame
35    """
36    def __init__(self, parent, id, title):
37        """
38            Initialize the Frame object
39        """
40        from local_perspectives.plotting import plotting
41        wx.Frame.__init__(self, parent, id, title, wx.DefaultPosition, size=(1000, 1000))
42       
43        path = os.path.dirname(__file__)
44        ico_file = os.path.join(path,'images/ball.ico')
45        if os.path.isfile(ico_file):
46            self.SetIcon(wx.Icon(ico_file, wx.BITMAP_TYPE_ICO))
47       
48        ## Application manager
49        self.app_manager = None
50       
51        ## Find plug-ins
52        # Modify this so that we can specify the directory to look into
53        self.plugins = self._find_plugins()
54        self.plugins.append(plotting.Plugin())
55
56        ## List of panels
57        self.panels = {}
58
59        ## Next available ID for wx gui events
60        self.next_id = 20000
61
62        ## Default welcome panel
63        self.defaultPanel    = DefaultPanel(self, -1, style=wx.RAISED_BORDER)
64
65        # self.build_gui()
66       
67        # Register the close event so it calls our own method
68        wx.EVT_CLOSE(self, self._onClose)
69        # Register to status events
70        self.Bind(EVT_STATUS, self._on_status_event)
71             
72    def build_gui(self):
73        # Set up the layout
74        self._setup_layout()
75       
76        # Set up the menu
77        self._setup_menus()
78       
79        self.Fit()
80             
81    def _setup_layout(self):
82        """
83            Set up the layout
84        """
85        # Status bar
86        self.sb = self.CreateStatusBar()
87        self.SetStatusText("")
88       
89        # Add panel
90        self._mgr = wx.aui.AuiManager(self)
91       
92        # Load panels
93        self._load_panels()
94       
95        self._mgr.Update()
96
97    def add_perspective(self, plugin):
98        """
99            Add a perspective if it doesn't already
100            exist.
101        """
102        is_loaded = False
103        for item in self.plugins:
104             if plugin.__class__==item.__class__:
105                 print "Plugin %s already loaded" % plugin.__class__.__name__
106                 is_loaded = True
107                 
108        if not is_loaded:
109            self.plugins.append(plugin)
110     
111    def _find_plugins(self, dir="perspectives"):
112        """
113            Find available perspective plug-ins
114            @param dir: directory in which to look for plug-ins
115            @return: list of plug-ins
116        """
117        import imp
118        print "Looking for plug-ins in %s" % dir
119        # List of plug-in objects
120       
121        #path_exe = os.getcwd()
122        #path_plugs = os.path.join(path_exe, dir)
123        f = open("load.log",'w') 
124        f.write(os.getcwd()+'\n\n')
125        #f.write(str(os.listdir(dir))+'\n')
126       
127       
128        plugins = []
129        # Go through files in panels directory
130        try:
131            list = os.listdir(dir)
132            for item in list:
133                print item
134                toks = os.path.splitext(os.path.basename(item))
135                name = None
136                if not toks[0] == '__init__':
137                   
138                    if toks[1]=='.py' or toks[1]=='':
139                        name = toks[0]
140               
141                    path = [os.path.abspath(dir)]
142                    file = None
143                    try:
144                        if toks[1]=='':
145                            f.write("trying to import \n")
146                            mod_path = '.'.join([dir, name])
147                            f.write("mod_path= %s\n" % mod_path)
148                            module = __import__(mod_path, globals(), locals(), [name])
149                            f.write(str(module)+'\n')
150                        else:
151                            (file, path, info) = imp.find_module(name, path)
152                            print path
153                            module = imp.load_module( name, file, item, info )
154                        if hasattr(module, "PLUGIN_ID"):
155                            try:
156                                plugins.append(module.Plugin())
157                                print "Found plug-in: %s" % module.PLUGIN_ID
158                            except:
159                                config.printEVT("Error accessing PluginPanel in %s\n  %s" % (name, sys.exc_value))
160                       
161                    except:
162                        print sys.exc_value
163                        f.write(str(sys.exc_value)+'\n')
164                    finally:
165                        if not file==None:
166                            file.close()
167        except:
168            # Should raise and catch at a higher level and display error on status bar
169            pass   
170        f.write(str(plugins)+'\n')
171        f.close()
172        return plugins
173   
174       
175     
176    def _load_panels(self):
177        """
178            Load all panels in the panels directory
179        """
180       
181        # Look for plug-in panels
182        panels = []       
183        for item in self.plugins:
184            if hasattr(item, "get_panels"):
185                ps = item.get_panels(self)
186                panels.extend(ps)
187
188        # Show a default panel with some help information
189        # It also sets the size of the application windows
190        self.panels["default"] = self.defaultPanel
191        self._mgr.AddPane(self.defaultPanel, wx.aui.AuiPaneInfo().
192                              Name("default").
193                              CenterPane().
194                              BestSize(wx.Size(900,800)).
195                              MinSize(wx.Size(900,800)).
196                              Show())
197
198        # Add the panels to the AUI manager
199        for panel_class in panels:
200            p = panel_class
201            id = wx.NewId()
202           
203            # Check whether we need to put this panel
204            # in the center pane
205            if hasattr(p, "CENTER_PANE"):
206                if p.CENTER_PANE:
207                    self.panels[str(id)] = p
208                    self._mgr.AddPane(p, wx.aui.AuiPaneInfo().
209                                          Name(p.window_name).Caption(p.window_caption).
210                                          CenterPane().
211                                          BestSize(wx.Size(600,600)).
212                                          MinSize(wx.Size(600,600)).
213                                          Hide())
214               
215            else:
216                self.panels[str(id)] = p
217                self._mgr.AddPane(p, wx.aui.AuiPaneInfo().
218                                  Name(p.window_name).Caption(p.window_caption).
219                                  #Floatable().
220                                  #Float().
221                                  Right().
222                                  Dock().
223                                  TopDockable().
224                                  BottomDockable().
225                                  LeftDockable().
226                                  RightDockable().
227                                  MinimizeButton().
228                                  Hide().
229                                  #Show().
230                                  BestSize(wx.Size(400,400)).
231                                  MinSize(wx.Size(100,100)))
232               
233       
234    def get_context_menu(self):
235        """
236            Get the context menu items made available
237            by the different plug-ins.
238            This function is used by the plotting module
239        """
240        menu_list = []
241        for item in self.plugins:
242            if hasattr(item, "get_context_menu"):
243                menu_list.extend(item.get_context_menu())
244           
245        return menu_list
246       
247    def popup_panel(self, p):
248        """
249            Add a panel object to the AUI manager
250            @param p: panel object to add to the AUI manager
251            @return: ID of the event associated with the new panel [int]
252        """
253       
254        ID = wx.NewId()
255        self.panels[str(ID)] = p
256       
257        count = 0
258        for item in self.panels:
259            if self.panels[item].window_name.startswith(p.window_name): 
260                count += 1
261               
262        windowname = p.window_name
263        caption = p.window_caption
264        if count>0:
265            windowname += str(count+1)
266            caption += (' '+str(count))
267           
268        p.window_name = windowname
269        p.window_caption = caption
270           
271        self._mgr.AddPane(p, wx.aui.AuiPaneInfo().
272                          Name(windowname).Caption(caption).
273                          Floatable().
274                          #Float().
275                          Right().
276                          Dock().
277                          TopDockable().
278                          BottomDockable().
279                          LeftDockable().
280                          RightDockable().
281                          MinimizeButton().
282                          #Hide().
283                          #Show().
284                          BestSize(wx.Size(400,400)).
285                          MinSize(wx.Size(200,200)))
286       
287        # Register for showing/hiding the panel
288        wx.EVT_MENU(self, ID, self._on_view)
289       
290        self._mgr.Update()
291        return ID
292       
293    def _setup_menus(self):
294        """
295            Set up the application menus
296        """
297        # Menu
298        menubar = wx.MenuBar()
299       
300        # File menu
301        filemenu = wx.Menu()
302        filemenu.Append(101,'&Quit', 'Exit') 
303       
304        # Add sub menus
305        menubar.Append(filemenu,  '&File')
306       
307        # Plot menu
308        # Attach a menu item for each panel in our
309        # panel list that also appears in a plug-in.
310        # TODO: clean this up. We should just identify
311        # plug-in panels and add them all.
312       
313        # Only add the panel menu if there is more than one panel
314        n_panels = 0
315        for plug in self.plugins:
316            pers = plug.get_perspective()
317            if len(pers)>0:
318                n_panels += 1
319       
320        if n_panels>1:
321            viewmenu = wx.Menu()
322            for plug in self.plugins:
323                plugmenu = wx.Menu()
324                pers = plug.get_perspective()
325                if len(pers)>0:
326                    for item in self.panels:
327                        if item == 'default':
328                            continue
329                        panel = self.panels[item]
330                        if panel.window_name in pers:
331                            plugmenu.Append(int(item), panel.window_caption, "Show %s window" % panel.window_caption)
332                            wx.EVT_MENU(self, int(item), self._on_view)
333                   
334                    viewmenu.AppendMenu(wx.NewId(), plug.sub_menu, plugmenu, plug.sub_menu)
335               
336            menubar.Append(viewmenu, '&Panel')
337
338        # Perspective
339        # Attach a menu item for each defined perspective.
340        # Only add the perspective menu if there are more than one perspectves
341        n_perspectives = 0
342        for plug in self.plugins:
343            if len(plug.get_perspective()) > 0:
344                n_perspectives += 1
345       
346        if n_perspectives>1:
347            p_menu = wx.Menu()
348            for plug in self.plugins:
349                if len(plug.get_perspective()) > 0:
350                    id = wx.NewId()
351                    p_menu.Append(id, plug.sub_menu, "Switch to %s perspective" % plug.sub_menu)
352                    wx.EVT_MENU(self, id, plug.on_perspective)
353            menubar.Append(p_menu,   '&Perspective')
354 
355        # Help menu
356        helpmenu = wx.Menu()
357
358        # Look for help item in plug-ins
359        for item in self.plugins:
360            if hasattr(item, "help"):
361                id = wx.NewId()
362                helpmenu.Append(id,'&%s help' % item.sub_menu, '')
363                wx.EVT_MENU(self, id, item.help)
364       
365        if config._do_aboutbox:
366            id = wx.NewId()
367            helpmenu.Append(id,'&About', 'Software information')
368            wx.EVT_MENU(self, id, self._onAbout)
369        id = wx.NewId()
370        helpmenu.Append(id,'&Check for update', 'Check for the latest version of %s' % config.__appname__)
371        wx.EVT_MENU(self, id, self._check_update)
372       
373       
374       
375       
376        # Look for plug-in menus
377        # Add available plug-in sub-menus.
378        for item in self.plugins:
379            if hasattr(item, "populate_menu"):
380                for (self.next_id, menu, name) in item.populate_menu(self.next_id, self):
381                    menubar.Append(menu, name)
382       
383
384        menubar.Append(helpmenu, '&Help')
385         
386        self.SetMenuBar(menubar)
387       
388        # Bind handlers       
389        wx.EVT_MENU(self, 101, self.Close)
390       
391    def _on_status_event(self, evt):
392        """
393            Display status message
394        """
395        self.SetStatusText(str(evt.status))
396
397       
398    def _on_view(self, evt):
399        """
400            A panel was selected to be shown. If it's not already
401            shown, display it.
402            @param evt: menu event
403        """
404        self.show_panel(evt.GetId())
405
406    def show_panel(self, uid):
407        """
408            Shows the panel with the given id
409            @param uid: unique ID number of the panel to show
410        """
411        ID = str(uid)
412        config.printEVT("show_panel: %s" % ID)
413        if ID in self.panels.keys():
414            if not self._mgr.GetPane(self.panels[ID].window_name).IsShown():
415                self._mgr.GetPane(self.panels[ID].window_name).Show()
416                # Hide default panel
417                self._mgr.GetPane(self.panels["default"].window_name).Hide()
418               
419               
420            self._mgr.Update()
421       
422
423    def _onClose(self, event):
424        import sys
425        wx.Exit()
426        sys.exit()
427                   
428    def Close(self, event=None):
429        """
430            Quit the application
431        """
432        import sys
433        wx.Frame.Close(self)
434        wx.Exit()
435        sys.exit()
436
437 
438    def _check_update(self, event=None): 
439        """
440            Check with the deployment server whether a new version
441            of the application is available
442        """
443        import urllib
444        try: 
445            h = urllib.urlopen(config.__update_URL__)
446            lines = h.readlines()
447            line = ''
448            if len(lines)>0:
449                line = lines[0]
450               
451                toks = line.lstrip().rstrip().split('.')
452                toks_current = config.__version__.split('.')
453                update_available = False
454                for i in range(len(toks)):
455                    if int(toks[i])>int(toks_current[i]):
456                        update_available = True
457                if update_available:
458                    #print "Version %s is available" % line.rstrip().lstrip()
459                    self.SetStatusText("Version %s is available! See the Help menu to download it." % line.rstrip().lstrip())
460                    if event != None:
461                        import webbrowser
462                        webbrowser.open(config.__download_page__)
463                else:
464                    self.SetStatusText("You have the latest version of %s" % config.__appname__)
465                    #print "Server version = %s"  % line.rstrip().lstrip()
466        except:
467            self.SetStatusText("You have the latest version of %s" % config.__appname__)
468           
469           
470    def _onAbout(self, evt):
471        """
472            Pop up the about dialog
473            @param evt: menu event
474        """
475        if config._do_aboutbox:
476            import aboutbox 
477            dialog = aboutbox.DialogAbout(None, -1, "")
478            dialog.ShowModal()
479           
480    def set_manager(self, manager):
481        """
482            Sets the application manager for this frame
483            @param manager: frame manager
484        """
485        self.app_manager = manager
486       
487    def post_init(self):
488        """
489            This initialization method is called after the GUI
490            has been created and all plug-ins loaded. It calls
491            the post_init() method of each plug-in (if it exists)
492            so that final initialization can be done.
493        """
494        for item in self.plugins:
495            if hasattr(item, "post_init"):
496                item.post_init()
497       
498    def set_perspective(self, panels):
499        """
500            Sets the perspective of the GUI.
501            Opens all the panels in the list, and closes
502            all the others.
503           
504            @param panels: list of panels
505        """
506        print "gui_mng.set_perspective"
507        for item in self.panels:
508            # Check whether this is a sticky panel
509            if hasattr(self.panels[item], "ALWAYS_ON"):
510                if self.panels[item].ALWAYS_ON:
511                    continue 
512           
513            if self.panels[item].window_name in panels:
514                if not self._mgr.GetPane(self.panels[item].window_name).IsShown():
515                    self._mgr.GetPane(self.panels[item].window_name).Show()
516            else:
517                if self._mgr.GetPane(self.panels[item].window_name).IsShown():
518                    self._mgr.GetPane(self.panels[item].window_name).Hide()
519                 
520        self._mgr.Update()
521       
522    def choose_file(self):
523        """
524            Functionality that belongs elsewhere
525            Should add a hook to specify the preferred file type/extension.
526        """
527        #TODO: clean this up
528        from data_loader import choose_data_file
529        return choose_data_file(self)
530                 
531class DefaultPanel(wx.Panel):
532    """
533        Defines the API for a panels to work with
534        the GUI manager
535    """
536    ## Internal nickname for the window, used by the AUI manager
537    window_name = "default"
538    ## Name to appear on the window title bar
539    window_caption = "Welcome panel"
540    ## Flag to tell the AUI manager to put this panel in the center pane
541    CENTER_PANE = True
542
543 
544# Toy application to test this Frame
545class ViewApp(wx.App):
546    def OnInit(self):
547        #from gui_manager import ViewerFrame
548        self.frame = ViewerFrame(None, -1, config.__appname__)   
549        self.frame.Show(True)
550
551        if hasattr(self.frame, 'special'):
552            print "Special?", self.frame.special.__class__.__name__
553            self.frame.special.SetCurrent()
554        self.SetTopWindow(self.frame)
555        return True
556   
557    def set_manager(self, manager):
558        """
559            Sets a reference to the application manager
560            of the GUI manager (Frame)
561        """
562        self.frame.set_manager(manager)
563       
564    def build_gui(self):
565        """
566            Build the GUI
567        """
568        self.frame.build_gui()
569        self.frame.post_init()
570       
571    def add_perspective(self, perspective):
572        """
573            Manually add a perspective to the application GUI
574        """
575        self.frame.add_perspective(perspective)
576       
577
578if __name__ == "__main__": 
579    app = ViewApp(0)
580    app.MainLoop()             
Note: See TracBrowser for help on using the repository browser.