source: sasview/guiframe/gui_manager.py @ 52b8b74

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

working on guiframe

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