source: sasview/guiframe/gui_manager.py @ 9d74cf8

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 9d74cf8 was 783940c, checked in by Gervaise Alina <gervyh@…>, 14 years ago

working on the splashpage

  • Property mode set to 100644
File size: 71.6 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_APPEND_BOOKMARK
41from sans.guiframe.events import EVT_PANEL_ON_FOCUS
42from sans.guiframe.events import StatusEvent
43from sans.guiframe.events import NewPlotEvent
44from sans.guiframe.gui_style import GUIFRAME
45from sans.guiframe.gui_style import GUIFRAME_ID
46from sans.guiframe.events import NewLoadedDataEvent
47from sans.guiframe.data_panel import DataPanel
48from sans.guiframe.panel_base import PanelBase
49from sans.guiframe.gui_toolbar import GUIToolBar
50from DataLoader.loader import Loader
51
52
53PLOPANEL_WIDTH = 400
54PLOPANEL_HEIGTH = 400
55GUIFRAME_WIDTH = 1000
56GUIFRAME_HEIGHT = 800
57PROG_SPLASH_SCREEN = "images/danse_logo.png" 
58EXTENSIONS =  ['.inv', '.fitv', '.prv', '.svs']
59
60class ViewerFrame(wx.Frame):
61    """
62    Main application frame
63    """
64   
65    def __init__(self, parent, title, 
66                 size=(GUIFRAME_WIDTH, GUIFRAME_HEIGHT),
67                 gui_style=GUIFRAME.DEFAULT_STYLE, 
68                 pos=wx.DefaultPosition):
69        """
70        Initialize the Frame object
71        """
72       
73        wx.Frame.__init__(self, parent=parent, title=title, pos=pos,size=size)
74        # Preferred window size
75        self._window_width, self._window_height = size
76        self.__gui_style = gui_style
77       
78        # Logging info
79        logging.basicConfig(level=logging.DEBUG,
80                    format='%(asctime)s %(levelname)s %(message)s',
81                    filename='sans_app.log',
82                    filemode='w')       
83        path = os.path.dirname(__file__)
84        temp_path = os.path.join(path,'images')
85        ico_file = os.path.join(temp_path,'ball.ico')
86        if os.path.isfile(ico_file):
87            self.SetIcon(wx.Icon(ico_file, wx.BITMAP_TYPE_ICO))
88        else:
89            temp_path = os.path.join(os.getcwd(),'images')
90            ico_file = os.path.join(temp_path,'ball.ico')
91            if os.path.isfile(ico_file):
92                self.SetIcon(wx.Icon(ico_file, wx.BITMAP_TYPE_ICO))
93       
94        ## Application manager
95        self.app_manager = None
96        self._mgr = None
97        #add current perpsective
98        self._current_perspective = None
99        self._plotting_plugin = None
100        self._data_plugin = None
101        #Menu bar and item
102        self._menubar = None
103        self._file_menu = None
104        self._data_menu = None
105        self._window_menu = None
106        self._data_panel_menu = None
107        self._help_menu = None
108        self._tool_menu = None
109        self._applications_menu_pos = -1
110        self._applications_menu_name = None
111        self._applications_menu = None
112        self._edit_menu = None
113        self._toolbar_menu = None
114        self._save_appl_menu = None
115        #tool bar
116        self._toolbar = None
117        ## Find plug-ins
118        # Modify this so that we can specify the directory to look into
119        self.plugins = []
120        #add local plugin
121        self.plugins += self._get_local_plugins()
122        self.plugins += self._find_plugins()
123        ## List of panels
124        self.panels = {}
125
126        # Default locations
127        self._default_save_location = os.getcwd()       
128       
129        # Welcome panel
130        self.defaultPanel = None
131        #panel on focus
132        self.panel_on_focus = None
133        self.loader = Loader()   
134         #data manager
135        from data_manager import DataManager
136        self._data_manager = DataManager()
137        self._data_panel = DataPanel(parent=self)
138        if self.panel_on_focus is not None:
139            self._data_panel.set_panel_on_focus(self.panel_on_focus.window_caption)
140        # Check for update
141        #self._check_update(None)
142        # Register the close event so it calls our own method
143        wx.EVT_CLOSE(self, self.Close)
144        # Register to status events
145        self.Bind(EVT_STATUS, self._on_status_event)
146        #Register add extra data on the same panel event on load
147        self.Bind(EVT_PANEL_ON_FOCUS, self.set_panel_on_focus)
148        self.Bind(EVT_APPEND_BOOKMARK, self.append_bookmark)
149   
150    def get_data_manager(self):
151        """
152        """
153        return self._data_manager
154   
155    def get_toolbar(self):
156        """
157        """
158        return self._toolbar
159   
160    def set_panel_on_focus(self, event):
161        """
162        Store reference to the last panel on focus
163        update the toolbar if available
164        update edit menu if available
165        """
166        self.panel_on_focus = event.panel
167        panel_name = 'No panel on focus'
168        application_name = 'No Selected Application'
169        if self.panel_on_focus is not None and self._data_panel is not None:
170            panel_name = self.panel_on_focus.window_caption
171            self._data_panel.set_panel_on_focus(panel_name)
172            #update toolbar
173            self._update_toolbar_helper()
174            #update edit menu
175            self.enable_edit_menu()
176       
177    def build_gui(self):
178        """
179        """
180        # Set up the layout
181        self._setup_layout()
182        # Set up the menu
183        self._setup_menus()
184        # set tool bar
185        self._setup_tool_bar()
186        #self.Fit()
187        #self._check_update(None)
188             
189    def _setup_layout(self):
190        """
191        Set up the layout
192        """
193        # Status bar
194        from gui_statusbar import StatusBar
195        self.sb = StatusBar(self, wx.ID_ANY)
196        self.SetStatusBar(self.sb)
197        # Add panel
198        default_flag = wx.aui.AUI_MGR_DEFAULT| wx.aui.AUI_MGR_ALLOW_ACTIVE_PANE
199        self._mgr = wx.aui.AuiManager(self, flags=default_flag)
200   
201        # Load panels
202        self._load_panels()
203        self.set_default_perspective()
204        self._mgr.Update()
205       
206    def SetStatusText(self, *args, **kwds):
207        """
208        """
209        number = self.sb.get_msg_position()
210        wx.Frame.SetStatusText(number=number, *args, **kwds)
211       
212    def PopStatusText(self, *args, **kwds):
213        """
214        """
215        field = self.sb.get_msg_position()
216        wx.Frame.PopStatusText(field=field)
217       
218    def PushStatusText(self, *args, **kwds):
219        """
220        """
221        field = self.sb.get_msg_position()
222        wx.Frame.PushStatusText(self, field=field, string=string)
223
224    def add_perspective(self, plugin):
225        """
226        Add a perspective if it doesn't already
227        exist.
228        """
229        is_loaded = False
230        for item in self.plugins:
231            if plugin.__class__ == item.__class__:
232                msg = "Plugin %s already loaded" % plugin.__class__.__name__
233                logging.info(msg)
234                is_loaded = True   
235        if not is_loaded:
236            self.plugins.append(plugin)
237     
238    def _get_local_plugins(self):
239        """
240        get plugins local to guiframe and others
241        """
242        plugins = []
243        #import guiframe local plugins
244        #check if the style contain guiframe.dataloader
245        style1 = self.__gui_style & GUIFRAME.DATALOADER_ON
246        style2 = self.__gui_style & GUIFRAME.PLOTTING_ON
247        if style1 == GUIFRAME.DATALOADER_ON:
248            try:
249                from sans.guiframe.local_perspectives.data_loader import data_loader
250                self._data_plugin = data_loader.Plugin()
251                plugins.append(self._data_plugin)
252            except:
253                msg = "ViewerFrame._get_local_plugins:"
254                msg += "cannot import dataloader plugin.\n %s" % sys.exc_value
255                logging.error(msg)
256        if style2 == GUIFRAME.PLOTTING_ON:
257            try:
258                from sans.guiframe.local_perspectives.plotting import plotting
259                self._plotting_plugin = plotting.Plugin()
260                plugins.append(self._plotting_plugin)
261            except:
262                msg = "ViewerFrame._get_local_plugins:"
263                msg += "cannot import plotting plugin.\n %s" % sys.exc_value
264                logging.error(msg)
265     
266        return plugins
267   
268    def _find_plugins(self, dir="perspectives"):
269        """
270        Find available perspective plug-ins
271       
272        :param dir: directory in which to look for plug-ins
273       
274        :return: list of plug-ins
275       
276        """
277        import imp
278        plugins = []
279        # Go through files in panels directory
280        try:
281            list = os.listdir(dir)
282            ## the default panel is the panel is the last plugin added
283            for item in list:
284                toks = os.path.splitext(os.path.basename(item))
285                name = None
286                if not toks[0] == '__init__':
287                   
288                    if toks[1] == '.py' or toks[1] == '':
289                        name = toks[0]
290               
291                    path = [os.path.abspath(dir)]
292                    file = None
293                    try:
294                        if toks[1] == '':
295                            mod_path = '.'.join([dir, name])
296                            module = __import__(mod_path, globals(),
297                                                locals(), [name])
298                        else:
299                            (file, path, info) = imp.find_module(name, path)
300                            module = imp.load_module( name, file, item, info)
301                        if hasattr(module, "PLUGIN_ID"):
302                            try: 
303                                plug = module.Plugin()
304                                if plug.set_default_perspective():
305                                    self._current_perspective = plug
306                                plugins.append(plug)
307                                msg = "Found plug-in: %s" % module.PLUGIN_ID
308                                logging.info(msg)
309                            except:
310                                msg = "Error accessing PluginPanel"
311                                msg += " in %s\n  %s" % (name, sys.exc_value)
312                                config.printEVT(msg)
313                    except:
314                        print sys.exc_value
315                        msg = "ViewerFrame._find_plugins: %s" % sys.exc_value
316                        logging.error(msg)
317                    finally:
318                        if not file == None:
319                            file.close()
320        except:
321            # Should raise and catch at a higher level and
322            # display error on status bar
323            pass   
324        return plugins
325   
326    def set_welcome_panel(self, panel_class):
327        """
328        Sets the default panel as the given welcome panel
329       
330        :param panel_class: class of the welcome panel to be instantiated
331       
332        """
333        self.defaultPanel = panel_class(self, -1, style=wx.RAISED_BORDER)
334       
335    def _get_panels_size(self, p):
336        """
337        find the proper size of the current panel
338        get the proper panel width and height
339        """
340        panel_height_min = self._window_height
341        panel_width_min = self._window_width
342        style = self.__gui_style & (GUIFRAME.MANAGER_ON)
343        if self._data_panel is not None  and (p == self._data_panel):
344            panel_width_min = self._window_width * 5/25 
345            return panel_width_min, panel_height_min
346        if hasattr(p, "CENTER_PANE") and p.CENTER_PANE:
347            style = self.__gui_style & (GUIFRAME.PLOTTING_ON|GUIFRAME.MANAGER_ON)
348            if style == (GUIFRAME.PLOTTING_ON|GUIFRAME.MANAGER_ON):
349                panel_width_min = self._window_width * 15/25 
350            return panel_width_min, panel_height_min
351        return panel_width_min, panel_height_min
352   
353    def _load_panels(self):
354        """
355        Load all panels in the panels directory
356        """
357       
358        # Look for plug-in panels
359        panels = []   
360        for item in self.plugins:
361            if hasattr(item, "get_panels"):
362                ps = item.get_panels(self)
363                panels.extend(ps)
364       
365        # Show a default panel with some help information
366        # It also sets the size of the application windows
367        #TODO: Use this for slpash screen
368        if self.defaultPanel is None:
369            self.defaultPanel = DefaultPanel(self, -1, style=wx.RAISED_BORDER)
370        # add a blank default panel always present
371        self.panels["default"] = self.defaultPanel
372        self._mgr.AddPane(self.defaultPanel, wx.aui.AuiPaneInfo().
373                              Name("default").
374                              Center().
375                              CloseButton(False).
376                              MinimizeButton(False).
377                              # This is where we set the size of
378                              # the application window
379                              BestSize(wx.Size(self._window_width, 
380                                               self._window_height)).
381                              Show())
382        #add data panel
383        self.panels["data_panel"] = self._data_panel
384        w, h = self._get_panels_size(self._data_panel)
385        self._mgr.AddPane(self._data_panel, wx.aui.AuiPaneInfo().
386                              Name(self._data_panel.window_name).
387                              Left().
388                              MinimizeButton().
389                              CloseButton(False).
390                              TopDockable(False).
391                              BottomDockable(False).
392                              LeftDockable(True).
393                              RightDockable(False).
394                              BestSize(wx.Size(w, h)).
395                              Hide())
396        style = self.__gui_style & GUIFRAME.MANAGER_ON
397        if style != GUIFRAME.MANAGER_ON:
398            self._mgr.GetPane(self.panels["data_panel"].window_name).Hide()
399        else:
400            self._mgr.GetPane(self.panels["data_panel"].window_name).Show()
401           
402        # Add the panels to the AUI manager
403        for panel_class in panels:
404            p = panel_class
405            id = wx.NewId()
406            w, h = self._get_panels_size(p)
407            # Check whether we need to put this panel
408            # in the center pane
409            if hasattr(p, "CENTER_PANE") and p.CENTER_PANE:
410                if p.CENTER_PANE:
411                    self.panels[str(id)] = p
412                    self._mgr.AddPane(p, wx.aui.AuiPaneInfo().
413                                          Name(p.window_name).Caption(p.window_caption).
414                                           #CenterPane().
415                                            Center().
416                                            CloseButton(False).
417                                            MinimizeButton(False).
418                                           MinSize(wx.Size(w, h)).
419                                           Hide())
420            else:
421                self.panels[str(id)] = p
422                self._mgr.AddPane(p, wx.aui.AuiPaneInfo().
423                                  Name(p.window_name).Caption(p.window_caption).
424                                  Right().
425                                  Dock().
426                                  TopDockable().
427                                  BottomDockable().
428                                  LeftDockable().
429                                  RightDockable().
430                                  MinimizeButton().
431                                  Hide())       
432     
433    def update_data(self, prev_data, new_data):
434        """
435        """
436        prev_id, data_state = self._data_manager.update_data(prev_data=prev_data, 
437                                       new_data=new_data)
438       
439        self._data_panel.remove_by_id(prev_id)
440        self._data_panel.load_data_list(data_state)
441       
442    def update_theory(self, data_id, theory, state=None):
443        """
444        """ 
445        data_state = self._data_manager.update_theory(data_id=data_id, 
446                                         theory=theory,
447                                         state=state) 
448        self._data_panel.load_data_list(data_state)
449       
450    def onfreeze(self, theory_id):
451        """
452        """
453        data_state_list = self._data_manager.freeze(theory_id)
454        self._data_panel.load_data_list(list=data_state_list)
455        for data_state in data_state_list.values():
456            new_plot = data_state.get_data()
457           
458            wx.PostEvent(self, NewPlotEvent(plot=new_plot,
459                                             title=new_plot.title))
460       
461    def freeze(self, data_id, theory_id):
462        """
463        """
464        data_state_list = self._data_manager.freeze_theory(data_id=data_id, 
465                                                theory_id=theory_id)
466        self._data_panel.load_data_list(list=data_state_list)
467        for data_state in data_state_list.values():
468            new_plot = data_state.get_data()
469            wx.PostEvent(self, NewPlotEvent(plot=new_plot,
470                                             title=new_plot.title))
471       
472    def delete_data(self, data):
473        """
474        """
475        self._current_perspective.delete_data(data)
476       
477   
478    def get_context_menu(self, plotpanel=None):
479        """
480        Get the context menu items made available
481        by the different plug-ins.
482        This function is used by the plotting module
483        """
484        if plotpanel is None:
485            return
486        menu_list = []
487        for item in self.plugins:
488            menu_list.extend(item.get_context_menu(plotpanel=plotpanel))
489        return menu_list
490       
491    def popup_panel(self, p):
492        """
493        Add a panel object to the AUI manager
494       
495        :param p: panel object to add to the AUI manager
496       
497        :return: ID of the event associated with the new panel [int]
498       
499        """
500        ID = wx.NewId()
501        self.panels[str(ID)] = p
502        count = 0
503        for item in self.panels:
504            if self.panels[item].window_name.startswith(p.window_name): 
505                count += 1
506        windowname = p.window_name
507        caption = p.window_caption
508        if count > 0:
509            windowname += str(count+1)
510            caption += (' '+str(count))
511        p.window_name = windowname
512        p.window_caption = caption
513           
514        style1 = self.__gui_style & GUIFRAME.FIXED_PANEL
515        style2 = self.__gui_style & GUIFRAME.FLOATING_PANEL
516        if style1 == GUIFRAME.FIXED_PANEL:
517            self._mgr.AddPane(p, wx.aui.AuiPaneInfo().
518                              Name(windowname).Caption(caption).
519                              MinimizeButton().
520                              Resizable(True).
521                              # Use a large best size to make sure the AUI
522                              # manager takes all the available space
523                              BestSize(wx.Size(PLOPANEL_WIDTH, PLOPANEL_HEIGTH)))
524            self._popup_fixed_panel(p)
525   
526        elif style2 == GUIFRAME.FLOATING_PANEL:
527            self._mgr.AddPane(p, wx.aui.AuiPaneInfo().
528                              Name(windowname).Caption(caption).
529                              MinimizeButton().
530                              Resizable(True).
531                              # Use a large best size to make sure the AUI
532                              #  manager takes all the available space
533                              BestSize(wx.Size(PLOPANEL_WIDTH, PLOPANEL_HEIGTH)))
534            self._popup_floating_panel(p)
535           
536        pane = self._mgr.GetPane(windowname)
537        self._mgr.MaximizePane(pane)
538        self._mgr.RestoreMaximizedPane()
539        # Register for showing/hiding the panel
540        wx.EVT_MENU(self, ID, self._on_view)
541       
542        self._mgr.Update()
543        return ID
544       
545    def _setup_menus(self):
546        """
547        Set up the application menus
548        """
549        # Menu
550        self._menubar = wx.MenuBar()
551        self._add_menu_file()
552        self._add_menu_data()
553        self._add_menu_application()
554        self._add_menu_edit()
555        self._add_menu_tool()
556        self._add_current_plugin_menu()
557        self._add_menu_window()
558        self._add_help_menu()
559        self.SetMenuBar(self._menubar)
560       
561    def _setup_tool_bar(self):
562        """
563        add toolbar to the frame
564        """
565        #set toolbar
566        self._toolbar = GUIToolBar(self, -1)
567        self.SetToolBar(self._toolbar)
568        self._update_toolbar_helper()
569        #self._on_hide_toolbar(event=None)
570   
571    def _update_toolbar_helper(self):
572        """
573        """
574        application_name = 'No Selected Application'
575        panel_name = 'No Panel on Focus'
576        self._toolbar.update_toolbar(self.panel_on_focus)
577        if self._current_perspective is not None:
578            application_name = self._current_perspective.sub_menu
579        if self.panel_on_focus is not None:
580            panel_name = self.panel_on_focus.window_caption
581        self._toolbar.update_button(application_name=application_name, 
582                                        panel_name=panel_name)
583        self._toolbar.Realize()
584       
585    def _add_menu_tool(self):
586        """
587        Tools menu
588        Go through plug-ins and find tools to populate the tools menu
589        """
590        style = self.__gui_style & GUIFRAME.TOOL_ON
591        if style == GUIFRAME.TOOL_ON:
592            self._tool_menu = None
593            for item in self.plugins:
594                if hasattr(item, "get_tools"):
595                    for tool in item.get_tools():
596                        # Only create a menu if we have at least one tool
597                        if self._tool_menu is None:
598                            self._tool_menu = wx.Menu()
599                        id = wx.NewId()
600                        self._tool_menu.Append(id, tool[0], tool[1])
601                        wx.EVT_MENU(self, id, tool[2])
602            if self._tool_menu is not None:
603                self._menubar.Append(self._tool_menu, '&Tools')
604               
605    def _add_current_plugin_menu(self):
606        """
607        add current plugin menu
608        Look for plug-in menus
609        Add available plug-in sub-menus.
610        """
611        if (self._menubar is None) or (self._current_perspective is None):
612            return
613        #replace or add a new menu for the current plugin
614       
615        pos = self._menubar.FindMenu(str(self._applications_menu_name))
616        if pos != -1:
617            menu_list = self._current_perspective.populate_menu(self)
618            if menu_list:
619                for (menu, name) in menu_list:
620                    hidden_menu = self._menubar.Replace(pos, menu, name) 
621                    self._applications_menu_name = name
622                #self._applications_menu_pos = pos
623            else:
624                hidden_menu = self._menubar.Remove(pos)
625                self._applications_menu_name = None
626            #get the position of the menu when it first added
627            self._applications_menu_pos = pos
628           
629        else:
630            menu_list = self._current_perspective.populate_menu(self)
631            if menu_list:
632                for (menu,name) in menu_list:
633                    if self._applications_menu_pos == -1:
634                        self._menubar.Append(menu, name)
635                    else:
636                        self._menubar.Insert(self._applications_menu_pos, menu, name)
637                    self._applications_menu_name = name
638                 
639    def _add_help_menu(self):
640        """
641        add help menu
642        """
643        # Help menu
644        self._help_menu = wx.Menu()
645        style = self.__gui_style & GUIFRAME.WELCOME_PANEL_ON
646        if style == GUIFRAME.WELCOME_PANEL_ON:
647            # add the welcome panel menu item
648            if self.defaultPanel is not None:
649                id = wx.NewId()
650                self._help_menu.Append(id, '&Welcome', '')
651                self._help_menu.AppendSeparator()
652                wx.EVT_MENU(self, id, self.show_welcome_panel)
653        # Look for help item in plug-ins
654        for item in self.plugins:
655            if hasattr(item, "help"):
656                id = wx.NewId()
657                self._help_menu.Append(id,'&%s help' % item.sub_menu, '')
658                wx.EVT_MENU(self, id, item.help)
659        if config._do_aboutbox:
660            id = wx.NewId()
661            self._help_menu.Append(id,'&About', 'Software information')
662            wx.EVT_MENU(self, id, self._onAbout)
663       
664        # Checking for updates needs major refactoring to work with py2exe
665        # We need to make sure it doesn't hang the application if the server
666        # is not up. We also need to make sure there's a proper executable to
667        # run if we spawn a new background process.
668        #id = wx.NewId()
669        #self._help_menu.Append(id,'&Check for update',
670        #'Check for the latest version of %s' % config.__appname__)
671        #wx.EVT_MENU(self, id, self._check_update)
672        self._menubar.Append(self._help_menu, '&Help')
673           
674    def _add_menu_window(self):
675        """
676        add a menu window to the menu bar
677        Window menu
678        Attach a menu item for each panel in our
679        panel list that also appears in a plug-in.
680       
681        Only add the panel menu if there is only one perspective and
682        it has more than two panels.
683        Note: the first plug-in is always the plotting plug-in.
684        The first application
685        #plug-in is always the second one in the list.
686        """
687        self._window_menu = wx.Menu()
688        if self._plotting_plugin is not None:
689            for (menu, name) in self._plotting_plugin.populate_menu(self):
690                self._window_menu.AppendSubMenu(menu, name)
691        self._menubar.Append(self._window_menu, '&Window')
692     
693        style = self.__gui_style & GUIFRAME.MANAGER_ON
694        id = wx.NewId()
695        self._data_panel_menu = self._window_menu.Append(id,
696                                                '&Data Explorer ON', '')
697        wx.EVT_MENU(self, id, self.show_data_panel)
698        if style == GUIFRAME.MANAGER_ON:
699            self._data_panel_menu.SetText('Data Explorer OFF')
700        else:
701            self._data_panel_menu.SetText('Data Explorer ON')
702           
703        style = self.__gui_style & GUIFRAME.PLOTTING_ON
704        if style == GUIFRAME.PLOTTING_ON:
705            self._window_menu.AppendSeparator()
706            id = wx.NewId()
707            preferences_menu = wx.Menu()
708            hint = "Plot panels will floating"
709            preferences_menu.Append(id, '&Floating Plot Panel', hint)
710            wx.EVT_MENU(self, id, self.set_plotpanel_floating)
711            id = wx.NewId()
712            hint = "Plot panels will displayed within the frame"
713            preferences_menu.Append(id, '&Fixed Plot Panel', hint)
714            wx.EVT_MENU(self, id, self.set_plotpanel_fixed)
715            id = wx.NewId()
716            style1 = self.__gui_style & GUIFRAME.MULTIPLE_APPLICATIONS
717            if style1 == GUIFRAME.MULTIPLE_APPLICATIONS:
718                id = wx.NewId()
719                self._toolbar_menu = preferences_menu.Append(id,'&Hide Toolbar', '')
720                wx.EVT_MENU(self, id, self._on_hide_toolbar)
721            self._window_menu.AppendSubMenu(preferences_menu,'&Preferences')
722        if self._window_menu.GetMenuItemCount() == 0:
723            pos = self._menubar.FindMenu('Window')
724            self._menubar.Remove(pos)
725        #wx.EVT_MENU(self, id, self.show_preferences_panel)   
726        """
727        if len(self.plugins) == 2:
728            plug = self.plugins[1]
729            pers = plug.get_perspective()
730       
731            if len(pers) > 1:
732                self._window_menu = wx.Menu()
733                for item in self.panels:
734                    if item == 'default':
735                        continue
736                    panel = self.panels[item]
737                    if panel.window_name in pers:
738                        self._window_menu.Append(int(item),
739                                                  panel.window_caption,
740                                        "Show %s window" % panel.window_caption)
741                        wx.EVT_MENU(self, int(item), self._on_view)
742                self._menubar.Append(self._window_menu, '&Window')
743                """
744               
745    def _add_menu_application(self):
746        """
747       
748        # Attach a menu item for each defined perspective or application.
749        # Only add the perspective menu if there are more than one perspectives
750        add menu application
751        """
752        style = self.__gui_style & GUIFRAME.MULTIPLE_APPLICATIONS
753        if style == GUIFRAME.MULTIPLE_APPLICATIONS:
754            plug_data_count = False
755            plug_no_data_count = False
756            self._applications_menu = wx.Menu()
757            separator = self._applications_menu.AppendSeparator()
758            for plug in self.plugins:
759                if len(plug.get_perspective()) > 0:
760                    id = wx.NewId()
761                    if plug.use_data():
762                        self._applications_menu.InsertCheckItem(0, id, plug.sub_menu,
763                                      "Switch to application: %s" % plug.sub_menu)
764                        plug_data_count = True
765                    else:
766                        plug_no_data_count = True
767                        self._applications_menu.AppendCheckItem(id, plug.sub_menu,
768                                      "Switch to application: %s" % plug.sub_menu)
769                    wx.EVT_MENU(self, id, plug.on_perspective)
770            if not (plug_data_count and  plug_no_data_count):
771                self._applications_menu.RemoveItem(separator)
772            self._menubar.Append(self._applications_menu, '&Applications')
773            self._check_applications_menu()
774           
775    def _add_menu_file(self):
776        """
777        add menu file
778        """
779       
780         # File menu
781        self._file_menu = wx.Menu()
782        style = self.__gui_style & GUIFRAME.DATALOADER_ON
783        if style == GUIFRAME.DATALOADER_ON:
784            # some menu of plugin to be seen under file menu
785            hint_load_file = "Read state's files and load"
786            hint_load_file += " them into the application"
787            id = wx.NewId()
788            self._save_appl_menu = self._file_menu.Append(id, 
789                                    '&Open State from File', hint_load_file)
790            wx.EVT_MENU(self, id, self._on_open_state)
791            id = wx.NewId()
792            self._save_appl_menu = self._file_menu.Append(id, 
793                                                          '&Save Application',
794                                 'Save state of the current active application')
795            wx.EVT_MENU(self, id, self._on_save_application)
796            id = wx.NewId()
797            self._file_menu.Append(id, '&Save Project',
798                                 'Save the state of the whole application')
799            wx.EVT_MENU(self, id, self._on_save_project)
800            self._file_menu.AppendSeparator()
801       
802        id = wx.NewId()
803        self._file_menu.Append(id, '&Quit', 'Exit') 
804        wx.EVT_MENU(self, id, self.Close)
805        # Add sub menus
806        self._menubar.Append(self._file_menu, '&File')
807       
808    def _add_menu_edit(self):
809        """
810        add menu edit
811        """
812        # Edit Menu
813        self._edit_menu = wx.Menu()
814        self._edit_menu.Append(GUIFRAME_ID.UNDO_ID, '&Undo', 
815                               'Undo the previous action')
816        wx.EVT_MENU(self, GUIFRAME_ID.UNDO_ID, self.on_undo_panel)
817        self._edit_menu.Append(GUIFRAME_ID.REDO_ID, '&Redo', 
818                               'Redo the previous action')
819        wx.EVT_MENU(self, GUIFRAME_ID.REDO_ID, self.on_redo_panel)
820        self._edit_menu.AppendSeparator()
821        self._edit_menu.Append(GUIFRAME_ID.PREVIEW_ID, '&Report',
822                               'Preview current panel')
823        wx.EVT_MENU(self, GUIFRAME_ID.PREVIEW_ID, self.on_preview_panel)
824        self._edit_menu.Append(GUIFRAME_ID.PRINT_ID, '&Print',
825                               'Print current panel')
826        wx.EVT_MENU(self, GUIFRAME_ID.PRINT_ID, self.on_print_panel)
827        self._edit_menu.Append(GUIFRAME_ID.RESET_ID, '&Reset', 
828                               'Reset current panel')
829        wx.EVT_MENU(self, GUIFRAME_ID.RESET_ID, self.on_reset_panel)
830        self._menubar.Append(self._edit_menu,  '&Edit')
831        self.enable_edit_menu()
832       
833    def get_style(self):
834        """
835        """
836        return  self.__gui_style
837   
838    def _add_menu_data(self):
839        """
840        Add menu item item data to menu bar
841        """
842        if self._data_plugin is not None:
843            menu_list = self._data_plugin.populate_menu(self)
844            if menu_list:
845                for (menu, name) in menu_list:
846                    self._menubar.Append(menu, name)
847           
848    def _on_hide_toolbar(self, event=None):
849        """
850        hide or show toolbar
851        """
852        if self._toolbar is None:
853            return
854        if self._toolbar.IsShown():
855            if self._toolbar_menu is not None:
856                self._toolbar_menu.SetItemLabel('Show Toolbar')
857            self._toolbar.Hide()
858        else:
859            if self._toolbar_menu is not None:
860                self._toolbar_menu.SetItemLabel('Hide Toolbar')
861            self._toolbar.Show()
862        self._toolbar.Realize()
863       
864    def _on_status_event(self, evt):
865        """
866        Display status message
867        """
868        self.sb.set_status(event=evt)
869       
870    def _on_view(self, evt):
871        """
872        A panel was selected to be shown. If it's not already
873        shown, display it.
874       
875        :param evt: menu event
876       
877        """
878        self.show_panel(evt.GetId())
879       
880    def on_close_welcome_panel(self):
881        """
882        Close the welcome panel
883        """
884        if self.defaultPanel is None:
885            return 
886        self._mgr.GetPane(self.panels["default"].window_name).Hide()
887        self._mgr.Update()
888        # set a default perspective
889        self.set_default_perspective()
890       
891    def show_welcome_panel(self, event):
892        """   
893        Display the welcome panel
894        """
895        if self.defaultPanel is None:
896            return 
897        for id in self.panels.keys():
898            if id  ==  'default':
899                # Show default panel
900                if not self._mgr.GetPane(self.panels["default"].window_name).IsShown():
901                    self._mgr.GetPane(self.panels["default"].window_name).Show(True)
902            elif id == "data_panel":
903                flag = self._mgr.GetPane(self.panels["data_panel"].window_name).IsShown()
904                self._mgr.GetPane(self.panels["data_panel"].window_name).Show(flag)
905            else:
906                self._mgr.GetPane(self.panels[id].window_name).IsShown()
907                self._mgr.GetPane(self.panels[id].window_name).Hide()
908        self._mgr.Update()
909       
910    def show_panel(self, uid):
911        """
912        Shows the panel with the given id
913       
914        :param uid: unique ID number of the panel to show
915       
916        """
917        ID = str(uid)
918        config.printEVT("show_panel: %s" % ID)
919        if ID in self.panels.keys():
920            if not self._mgr.GetPane(self.panels[ID].window_name).IsShown():
921                self._mgr.GetPane(self.panels[ID].window_name).Show()
922                # Hide default panel
923                self._mgr.GetPane(self.panels["default"].window_name).Hide()
924            self._mgr.Update()
925           
926    def hide_panel(self, uid):
927        """
928        hide panel
929        """
930        ID = str(uid)
931        config.printEVT("hide_panel: %s" % ID)
932        if ID in self.panels.keys():
933            if self._mgr.GetPane(self.panels[ID].window_name).IsShown():
934                self._mgr.GetPane(self.panels[ID].window_name).Hide()
935                # Hide default panel
936                self._mgr.GetPane(self.panels["default"].window_name).Hide()
937            self._mgr.Update()
938           
939    def delete_panel(self, uid):
940        """
941        delete panel given uid
942        """
943        ID = str(uid)
944        config.printEVT("delete_panel: %s" % ID)
945       
946        if ID in self.panels.keys():
947            panel = self.panels[ID]
948            self._plotting_plugin.delete_panel(panel.group_id)
949            self._mgr.DetachPane(panel)
950            panel.Destroy()
951            del self.panels[ID]
952            self._mgr.Update()
953     
954    def clear_panel(self):
955        """
956        """
957        for item in self.panels:
958            try:
959                self.panels[item].clear_panel()
960            except:
961                pass
962           
963    def create_gui_data(self, data, path=None):
964        """
965        """
966        return self._data_manager.create_gui_data(data, path)
967   
968    def get_data(self, path):
969        """
970        """
971        message = ""
972        log_msg = ''
973        output = []
974        error_message = ""
975        basename  = os.path.basename(path)
976        root, extension = os.path.splitext(basename)
977        if extension.lower() not in EXTENSIONS:
978            log_msg = "File Loader cannot "
979            log_msg += "load: %s\n" % str(basename)
980            log_msg += "Try Data opening...."
981            logging.info(log_msg)
982            self.load_complete(output=output, error_message=error_message,
983                   message=log_msg, path=path)   
984            return
985       
986        #reading a state file
987        for plug in self.plugins:
988            reader, ext = plug.get_extensions()
989            if reader is not None:
990                #read the state of the single plugin
991                if extension == ext:
992                    reader.read(path)
993                    return
994                elif extension == '.svs':
995                    reader.read(path)
996       
997        style = self.__gui_style & GUIFRAME.MANAGER_ON
998        if style == GUIFRAME.MANAGER_ON:
999            if self._data_panel is not None:
1000                data_state = self._data_manager.get_selected_data()
1001                self._data_panel.load_data_list(data_state)
1002                self._mgr.GetPane(self._data_panel.window_name).Show(True)
1003                       
1004    def _on_open_state(self, event):
1005        """
1006        """
1007        path = None
1008        if self._default_save_location == None:
1009            self._default_save_location = os.getcwd()
1010 
1011        wlist = ['SansView files (*.svs)|*.svs',
1012                  'P(r) files (*.prv)|*.prv',
1013                  'Fitting files (*.fitv)|*.fitv',
1014                  'Invariant files (*.inv)|*.inv']
1015        wlist = '|'.join(wlist)
1016        dlg = wx.FileDialog(self, 
1017                            "Choose a file", 
1018                            self._default_save_location, "",
1019                             wlist)
1020        if dlg.ShowModal() == wx.ID_OK:
1021            path = dlg.GetPath()
1022            if path is not None:
1023                self._default_save_location = os.path.dirname(path)
1024        dlg.Destroy()
1025        if path and os.path.isfile(path):
1026            basename  = os.path.basename(path)
1027            if  basename.endswith('.svs'):
1028                #remove panels for new states
1029                for plug in self.plugins:
1030                    plug.clear_panel()
1031                    self.panel_on_focus = None
1032               
1033            self.get_data(path)
1034               
1035        if self.defaultPanel is not None and \
1036            self._mgr.GetPane(self.panels["default"].window_name).IsShown():
1037            self.on_close_welcome_panel()
1038   
1039    def _on_save_application(self, event):
1040        """
1041        save the state of the current active application
1042        """
1043        if self.panel_on_focus is not None:
1044            self.panel_on_focus.on_save(event)
1045           
1046    def _on_save_project(self, event):
1047        """
1048        save the state of the current active application
1049        """
1050        ## Default file location for save
1051        self._default_save_location = os.getcwd()
1052        if self._current_perspective is  None:
1053            return
1054        reader, ext = self._current_perspective.get_extensions()
1055        path = None
1056        dlg = wx.FileDialog(self, "Save Project file",
1057                            self._default_save_location, "", '.svs', wx.SAVE)
1058        if dlg.ShowModal() == wx.ID_OK:
1059            path = dlg.GetPath()
1060            self._default_save_location = os.path.dirname(path)
1061        else:
1062            return None
1063        dlg.Destroy()
1064        if path is None:
1065            return
1066        # default cansas xml doc
1067        doc = None
1068        for panel in self.panels.values():
1069            doc = self.on_save_helper(doc, reader, panel, path)
1070       
1071           
1072    def on_save_helper(self, doc, reader, panel, path):
1073        """
1074        Save state into a file
1075        """
1076        try:
1077            data = panel.get_data()
1078            state = panel.get_state()
1079            if reader is not None:
1080                if data is not None:
1081                    new_doc = reader.write_toXML(data, state)
1082                    if hasattr(doc, "firstChild"):
1083                        child = new_doc.firstChild.firstChild
1084                        doc.firstChild.appendChild(child) 
1085                    else:
1086                        doc = new_doc
1087        except: 
1088            raise
1089            #pass
1090        # Write the XML document
1091        if doc != None:
1092            fd = open(path, 'w')
1093            fd.write(doc.toprettyxml())
1094            fd.close()
1095        else:
1096            raise
1097            #print "Nothing to save..."
1098            #raise RuntimeError, "%s is not a SansView (.svs) file..." % path
1099        return doc
1100
1101    def quit_guiframe(self):
1102        """
1103        Pop up message to make sure the user wants to quit the application
1104        """
1105        message = "Do you really want to quit \n"
1106        message += "this application?"
1107        dial = wx.MessageDialog(self, message, 'Question',
1108                           wx.YES_NO|wx.YES_DEFAULT|wx.ICON_QUESTION)
1109        if dial.ShowModal() == wx.ID_YES:
1110            return True
1111        else:
1112            return False   
1113       
1114    def Close(self, event=None):
1115        """
1116        Quit the application
1117        """
1118        #flag = self.quit_guiframe()
1119        if True:
1120            wx.Exit()
1121            sys.exit()
1122
1123    def _check_update(self, event=None): 
1124        """
1125        Check with the deployment server whether a new version
1126        of the application is available.
1127        A thread is started for the connecting with the server. The thread calls
1128        a call-back method when the current version number has been obtained.
1129        """
1130        if hasattr(config, "__update_URL__"):
1131            import version
1132            checker = version.VersionThread(config.__update_URL__,
1133                                            self._process_version,
1134                                            baggage=event==None)
1135            checker.start() 
1136   
1137    def _process_version(self, version, standalone=True):
1138        """
1139        Call-back method for the process of checking for updates.
1140        This methods is called by a VersionThread object once the current
1141        version number has been obtained. If the check is being done in the
1142        background, the user will not be notified unless there's an update.
1143       
1144        :param version: version string
1145        :param standalone: True of the update is being checked in
1146           the background, False otherwise.
1147           
1148        """
1149        try:
1150            if cmp(version, config.__version__) > 0:
1151                msg = "Version %s is available! See the Help "
1152                msg += "menu to download it." % version
1153                self.SetStatusText(msg)
1154                if not standalone:
1155                    import webbrowser
1156                    webbrowser.open(config.__download_page__)
1157            else:
1158                if not standalone:
1159                    msg = "You have the latest version"
1160                    msg += " of %s" % config.__appname__
1161                    self.SetStatusText(msg)
1162        except:
1163            msg = "guiframe: could not get latest application"
1164            msg += " version number\n  %s" % sys.exc_value
1165            logging.error(msg)
1166            if not standalone:
1167                msg = "Could not connect to the application server."
1168                msg += " Please try again later."
1169                self.SetStatusText(msg)
1170                   
1171    def _onAbout(self, evt):
1172        """
1173        Pop up the about dialog
1174       
1175        :param evt: menu event
1176       
1177        """
1178        if config._do_aboutbox:
1179            import aboutbox 
1180            dialog = aboutbox.DialogAbout(None, -1, "")
1181            dialog.ShowModal()           
1182           
1183    def set_manager(self, manager):
1184        """
1185        Sets the application manager for this frame
1186       
1187        :param manager: frame manager
1188        """
1189        self.app_manager = manager
1190       
1191    def post_init(self):
1192        """
1193        This initialization method is called after the GUI
1194        has been created and all plug-ins loaded. It calls
1195        the post_init() method of each plug-in (if it exists)
1196        so that final initialization can be done.
1197        """
1198        for item in self.plugins:
1199            if hasattr(item, "post_init"):
1200                item.post_init()
1201       
1202    def set_default_perspective(self):
1203        """
1204        Choose among the plugin the first plug-in that has
1205        "set_default_perspective" method and its return value is True will be
1206        as a default perspective when the welcome page is closed
1207        """
1208        for item in self.plugins:
1209            if hasattr(item, "set_default_perspective"):
1210                if item.set_default_perspective():
1211                    item.on_perspective(event=None)
1212                    return 
1213       
1214    def set_perspective(self, panels):
1215        """
1216        Sets the perspective of the GUI.
1217        Opens all the panels in the list, and closes
1218        all the others.
1219       
1220        :param panels: list of panels
1221        """
1222        for item in self.panels:
1223            # Check whether this is a sticky panel
1224            if hasattr(self.panels[item], "ALWAYS_ON"):
1225                if self.panels[item].ALWAYS_ON:
1226                    continue 
1227            if self.panels[item].window_name in panels:
1228                if not self._mgr.GetPane(self.panels[item].window_name).IsShown():
1229                    self._mgr.GetPane(self.panels[item].window_name).Show()
1230            else:
1231                # always show the data panel if enable
1232                style = self.__gui_style & GUIFRAME.MANAGER_ON
1233                if (style == GUIFRAME.MANAGER_ON) and self.panels[item] == self._data_panel:
1234                    if 'data_panel' in self.panels.keys():
1235                        flag = self._mgr.GetPane(self.panels['data_panel'].window_name).IsShown()
1236                        self._mgr.GetPane(self.panels['data_panel'].window_name).Show(flag)
1237                else:
1238                    if self._mgr.GetPane(self.panels[item].window_name).IsShown():
1239                        self._mgr.GetPane(self.panels[item].window_name).Hide()
1240        self._mgr.Update()
1241       
1242    def show_data_panel(self, event=None):
1243        """
1244        show the data panel
1245        """
1246        label = self._data_panel_menu.GetText()
1247        if label == 'Data Explorer ON':
1248            pane = self._mgr.GetPane(self.panels["data_panel"].window_name)
1249            #if not pane.IsShown():
1250            pane.Show(True)
1251            self._mgr.Update()
1252            self.__gui_style = self.__gui_style | GUIFRAME.MANAGER_ON
1253           
1254            self._data_panel_menu.SetText('Data Explorer OFF')
1255        else:
1256            pane = self._mgr.GetPane(self.panels["data_panel"].window_name)
1257            #if not pane.IsShown():
1258            pane.Show(False)
1259            self._mgr.Update()
1260            self.__gui_style = self.__gui_style & (~GUIFRAME.MANAGER_ON)
1261            self._data_panel_menu.SetText('Data Explorer ON')
1262   
1263    def add_data_helper(self, data_list):
1264        """
1265        """
1266        if self._data_manager is not None:
1267            self._data_manager.add_data(data_list)
1268       
1269    def add_data(self, data_list):
1270        """
1271        receive a dictionary of data from loader
1272        store them its data manager if possible
1273        send to data the current active perspective if the data panel
1274        is not active.
1275        :param data_list: dictionary of data's ID and value Data
1276        """
1277        #Store data into manager
1278        self.add_data_helper(data_list)
1279        # set data in the data panel
1280        if self._data_panel is not None:
1281            data_state = self._data_manager.get_data_state(data_list.keys())
1282            self._data_panel.load_data_list(data_state)
1283        #if the data panel is shown wait for the user to press a button
1284        #to send data to the current perspective. if the panel is not
1285        #show  automatically send the data to the current perspective
1286        style = self.__gui_style & GUIFRAME.MANAGER_ON
1287        if style == GUIFRAME.MANAGER_ON:
1288            #wait for button press from the data panel to set_data
1289            if self._data_panel is not None:
1290                self._mgr.GetPane(self._data_panel.window_name).Show(True)
1291                self._mgr.Update() 
1292        else:
1293            #automatically send that to the current perspective
1294            self.set_data(data_id=data_list.keys())
1295       
1296    def set_data(self, data_id): 
1297        """
1298        set data to current perspective
1299        """
1300        list_data, _ = self._data_manager.get_by_id(data_id)
1301        if self._current_perspective is not None:
1302            self._current_perspective.set_data(list_data.values())
1303        else:
1304            msg = "Guiframe does not have a current perspective"
1305            logging.info(msg)
1306           
1307    def set_theory(self, state_id, theory_id=None):
1308        """
1309        """
1310        _, list_theory = self._data_manager.get_by_id(theory_id)
1311        if self._current_perspective is not None:
1312            try:
1313                self._current_perspective.set_theory(list_theory.values())
1314            except:
1315                msg = "Guiframe set_theory: \n" + str(sys.exc_value)
1316                logging.info(msg)
1317                wx.PostEvent(self, StatusEvent(status=msg, info="error"))
1318        else:
1319            msg = "Guiframe does not have a current perspective"
1320            logging.info(msg)
1321           
1322    def plot_data(self,  state_id, data_id=None,
1323                  theory_id=None, append=False):
1324        """
1325        send a list of data to plot
1326        """
1327        total_plot_list = []
1328        data_list, _ = self._data_manager.get_by_id(data_id)
1329        _, temp_list_theory = self._data_manager.get_by_id(theory_id)
1330        total_plot_list = data_list.values()
1331        for item in temp_list_theory.values():
1332            theory_data, theory_state = item
1333            total_plot_list.append(theory_data)
1334        GROUP_ID = wx.NewId()
1335        for new_plot in total_plot_list:
1336            if append:
1337                if self.panel_on_focus is None:
1338                    message = "cannot append plot. No plot panel on focus!"
1339                    message += "please click on any available plot to set focus"
1340                    wx.PostEvent(self, StatusEvent(status=message, 
1341                                                   info='warning'))
1342                    return 
1343                else:
1344                    if self.enable_add_data(new_plot):
1345                        new_plot.group_id = self.panel_on_focus.group_id
1346                    else:
1347                        message = "Only 1D Data can be append to plot panel\n"
1348                        message += "%s will be plot separetly\n" %str(new_plot.name)
1349                        wx.PostEvent(self, StatusEvent(status=message, 
1350                                                   info='warning'))
1351            else:
1352                #if not append then new plot
1353                new_plot.group_id = GROUP_ID
1354            title = "PLOT " + str(new_plot.title)
1355            wx.PostEvent(self, NewPlotEvent(plot=new_plot,
1356                                                  title=title))
1357           
1358    def remove_data(self, data_id, theory_id=None):
1359        """
1360        Delete data state if data_id is provide
1361        delete theory created with data of id data_id if theory_id is provide
1362        if delete all true: delete the all state
1363        else delete theory
1364        """
1365        for plug in self.plugins:
1366            plug.delete_data(data_id)
1367        total_plot_list = []
1368        data_list, _ = self._data_manager.get_by_id(data_id)
1369        _, temp_list_theory = self._data_manager.get_by_id(theory_id)
1370        total_plot_list = data_list.values()
1371        for item in temp_list_theory.values():
1372            theory_data, theory_state = item
1373            total_plot_list.append(theory_data)
1374        for new_plot in total_plot_list:
1375            id = new_plot.id
1376            for group_id in new_plot.list_group_id:
1377                wx.PostEvent(self, NewPlotEvent(id=id,
1378                                                   group_id=group_id,
1379                                                   action='remove'))
1380        self._data_manager.delete_data(data_id=data_id, 
1381                                       theory_id=theory_id)
1382           
1383       
1384    def set_current_perspective(self, perspective):
1385        """
1386        set the current active perspective
1387        """
1388        self._current_perspective = perspective
1389        name = "No current Application selected"
1390        if self._current_perspective is not None:
1391            self._add_current_plugin_menu()
1392            for panel in self.panels.values():
1393                if hasattr(panel, 'CENTER_PANE') and panel.CENTER_PANE:
1394                    for name in self._current_perspective.get_perspective():
1395                        if name == panel.window_name:
1396                            panel.on_set_focus(event=None)
1397                            break
1398                           
1399            name = self._current_perspective.sub_menu
1400            if self._data_panel is not None:
1401                self._data_panel.set_active_perspective(name)
1402                self._check_applications_menu()
1403 
1404    def _check_applications_menu(self):
1405        """
1406        check the menu of the current application
1407        """
1408        if self._applications_menu is not None:
1409            for menu in self._applications_menu.GetMenuItems():
1410                if self._current_perspective is not None:
1411                    name = self._current_perspective.sub_menu
1412                    if menu.IsCheckable():
1413                        if menu.GetLabel() == name:
1414                            menu.Check(True)
1415                        else:
1416                             menu.Check(False) 
1417           
1418    def set_plotpanel_floating(self, event=None):
1419        """
1420        make the plot panel floatable
1421        """
1422        self.__gui_style &= (~GUIFRAME.FIXED_PANEL)
1423        self.__gui_style |= GUIFRAME.FLOATING_PANEL
1424        for p in self.panels.values():
1425            plot_panel = self._plotting_plugin.plot_panels.values()
1426            for p in self.panels.values():
1427                if p in plot_panel:
1428                    self._popup_floating_panel(p)
1429       
1430    def set_plotpanel_fixed(self, event=None):
1431        """
1432        make the plot panel fixed
1433        """
1434        self.__gui_style &= (~GUIFRAME.FLOATING_PANEL)
1435        self.__gui_style |= GUIFRAME.FIXED_PANEL
1436        plot_panel = []
1437        if self._plotting_plugin is not None:
1438            plot_panel = self._plotting_plugin.plot_panels.values()
1439            for p in self.panels.values():
1440                if p in plot_panel:
1441                    self._popup_fixed_panel(p)
1442                   
1443    def _popup_fixed_panel(self, p):
1444        """
1445        """
1446        style = self.__gui_style & GUIFRAME.FIXED_PANEL
1447        if style == GUIFRAME.FIXED_PANEL:
1448            self._mgr.GetPane(p.window_name).Floatable()
1449            self._mgr.GetPane(p.window_name).Right()
1450            self._mgr.GetPane(p.window_name).TopDockable(False)
1451            self._mgr.GetPane(p.window_name).BottomDockable(False)
1452            self._mgr.GetPane(p.window_name).LeftDockable(False)
1453            self._mgr.GetPane(p.window_name).RightDockable(True)
1454            flag = self._mgr.GetPane(p.window_name).IsShown()
1455            self._mgr.GetPane(p.window_name).Show(flag)
1456            self._mgr.Update()
1457           
1458    def _popup_floating_panel(self, p):
1459        """
1460        """
1461        style = self.__gui_style &  GUIFRAME.FLOATING_PANEL
1462        if style == GUIFRAME.FLOATING_PANEL: 
1463            self._mgr.GetPane(p.window_name).Floatable(True)
1464            self._mgr.GetPane(p.window_name).Float()
1465            self._mgr.GetPane(p.window_name).Dockable(False)
1466            flag = self._mgr.GetPane(p.window_name).IsShown()
1467            self._mgr.GetPane(p.window_name).Show(flag)
1468            self._mgr.Update()
1469           
1470    def enable_add_data(self, new_plot):
1471        """
1472        Enable append data on a plot panel
1473        """
1474        if self.panel_on_focus not in self._plotting_plugin.plot_panels.values():
1475            return
1476        is_theory = len(self.panel_on_focus.plots) <= 1 and \
1477            self.panel_on_focus.plots.values()[0].__class__.__name__ == "Theory1D"
1478           
1479        is_data2d = hasattr(new_plot, 'data')
1480        is_data1d = self.panel_on_focus.__class__.__name__ == "ModelPanel1D"\
1481            and self.panel_on_focus.group_id is not None
1482        has_meta_data = hasattr(new_plot, 'meta_data')
1483       
1484        #disable_add_data if the data is being recovered from  a saved state file.
1485        is_state_data = False
1486        if has_meta_data:
1487            if 'invstate' in new_plot.meta_data: is_state_data = True
1488            if  'prstate' in new_plot.meta_data: is_state_data = True
1489            if  'fitstate' in new_plot.meta_data: is_state_data = True
1490   
1491        return is_data1d and not is_data2d and not is_theory and not is_state_data
1492   
1493    def enable_edit_menu(self):
1494        """
1495        enable menu item under edit menu depending on the panel on focus
1496        """
1497        if self.panel_on_focus is not None and self._edit_menu is not None:
1498            flag = self.panel_on_focus.get_undo_flag()
1499            self._edit_menu.Enable(GUIFRAME_ID.UNDO_ID, flag)
1500            flag = self.panel_on_focus.get_redo_flag()
1501            self._edit_menu.Enable(GUIFRAME_ID.REDO_ID, flag)
1502            flag = self.panel_on_focus.get_print_flag()
1503            self._edit_menu.Enable(GUIFRAME_ID.PRINT_ID, flag)
1504            flag = self.panel_on_focus.get_preview_flag()
1505            self._edit_menu.Enable(GUIFRAME_ID.PREVIEW_ID, flag)
1506            flag = self.panel_on_focus.get_reset_flag()
1507            self._edit_menu.Enable(GUIFRAME_ID.RESET_ID, flag)
1508        else:
1509            flag = False
1510            self._edit_menu.Enable(GUIFRAME_ID.UNDO_ID, flag)
1511            self._edit_menu.Enable(GUIFRAME_ID.REDO_ID, flag)
1512            self._edit_menu.Enable(GUIFRAME_ID.PRINT_ID, flag)
1513            self._edit_menu.Enable(GUIFRAME_ID.PREVIEW_ID, flag)
1514            self._edit_menu.Enable(GUIFRAME_ID.RESET_ID, flag)
1515           
1516    def on_undo_panel(self, event=None):
1517        """
1518        undo previous action of the last panel on focus if possible
1519        """
1520        if self.panel_on_focus is not None:
1521            self.panel_on_focus.on_undo(event)
1522           
1523    def on_redo_panel(self, event=None):
1524        """
1525        redo the last cancel action done on the last panel on focus
1526        """
1527        if self.panel_on_focus is not None:
1528            self.panel_on_focus.on_redo(event)
1529           
1530    def on_bookmark_panel(self, event=None):
1531        """
1532        bookmark panel
1533        """
1534        if self.panel_on_focus is not None:
1535            self.panel_on_focus.on_bookmark(event)
1536           
1537    def append_bookmark(self, event=None):
1538        """
1539        Bookmark available information of the panel on focus
1540        """
1541        self._toolbar.append_bookmark(event)
1542           
1543    def on_save_panel(self, event=None):
1544        """
1545        save possible information on the current panel
1546        """
1547        if self.panel_on_focus is not None:
1548            self.panel_on_focus.on_save(event)
1549           
1550    def on_preview_panel(self, event=None):
1551        """
1552        preview information on the panel on focus
1553        """
1554        if self.panel_on_focus is not None:
1555            self.panel_on_focus.on_preview(event)
1556           
1557    def on_print_panel(self, event=None):
1558        """
1559        print available information on the last panel on focus
1560        """
1561        if self.panel_on_focus is not None:
1562            self.panel_on_focus.on_print(event)
1563           
1564    def on_zoom_panel(self, event=None):
1565        """
1566        zoom on the current panel if possible
1567        """
1568        if self.panel_on_focus is not None:
1569            self.panel_on_focus.on_zoom(event)
1570           
1571    def on_zoom_in_panel(self, event=None):
1572        """
1573        zoom in of the panel on focus
1574        """
1575        if self.panel_on_focus is not None:
1576            self.panel_on_focus.on_zoom_in(event)
1577           
1578    def on_zoom_out_panel(self, event=None):
1579        """
1580        zoom out on the panel on focus
1581        """
1582        if self.panel_on_focus is not None:
1583            self.panel_on_focus.on_zoom_out(event)
1584           
1585    def on_drag_panel(self, event=None):
1586        """
1587        drag apply to the panel on focus
1588        """
1589        if self.panel_on_focus is not None:
1590            self.panel_on_focus.on_drag(event)
1591           
1592    def on_reset_panel(self, event=None):
1593        """
1594        reset the current panel
1595        """
1596        if self.panel_on_focus is not None:
1597            self.panel_on_focus.on_reset(event)
1598           
1599    def enable_undo(self):
1600        """
1601        enable undo related control
1602        """
1603        if self.panel_on_focus is not None:
1604            self._toolbar.enable_undo(self.panel_on_focus)
1605           
1606    def enable_redo(self):
1607        """
1608        enable redo
1609        """
1610        if self.panel_on_focus is not None:
1611            self._toolbar.enable_redo(self.panel_on_focus)
1612           
1613    def enable_bookmark(self):
1614        """
1615        Bookmark
1616        """
1617        if self.panel_on_focus is not None:
1618            self._toolbar.enable_bookmark(self.panel_on_focus)
1619           
1620    def enable_save(self):
1621        """
1622        save
1623        """
1624        if self.panel_on_focus is not None:
1625            self._toolbar.enable_save(self.panel_on_focus)
1626           
1627    def enable_preview(self):
1628        """
1629        preview
1630        """
1631        if self.panel_on_focus is not None:
1632            self._toolbar.enable_preview(self.panel_on_focus)
1633           
1634    def enable_print(self):
1635        """
1636        print
1637        """
1638        if self.panel_on_focus is not None:
1639            self._toolbar.enable_print(self.panel_on_focus)
1640           
1641    def enable_zoom(self):
1642        """
1643        zoom
1644        """
1645        if self.panel_on_focus is not None:
1646            self._toolbar.enable_zoom(self.panel_on_focus)
1647           
1648    def enable_zoom_in(self):
1649        """
1650        zoom in
1651        """
1652        if self.panel_on_focus is not None:
1653            self._toolbar.enable_zoom_in(self.panel_on_focus)
1654           
1655    def enable_zoom_out(self):
1656        """
1657        zoom out
1658        """
1659        if self.panel_on_focus is not None:
1660            self._toolbar.enable_zoom_out(self.panel_on_focus)
1661           
1662    def enable_drag(self, event=None):
1663        """
1664        drag
1665        """
1666        if self.panel_on_focus is not None:
1667            self._toolbar.enable_drag(self.panel_on_focus)
1668           
1669    def enable_reset(self):
1670        """
1671        reset the current panel
1672        """
1673        if self.panel_on_focus is not None:
1674            self._toolbar.enable_reset(self.panel_on_focus)
1675       
1676class DefaultPanel(wx.Panel, PanelBase):
1677    """
1678    Defines the API for a panels to work with
1679    the GUI manager
1680    """
1681    ## Internal nickname for the window, used by the AUI manager
1682    window_name = "default"
1683    ## Name to appear on the window title bar
1684    window_caption = "Welcome panel"
1685    ## Flag to tell the AUI manager to put this panel in the center pane
1686    CENTER_PANE = True
1687    def __init__(self, parent, *args, **kwds):
1688        wx.Panel.__init__(self, parent, *args, **kwds)
1689        PanelBase.__init__(self, parent)
1690   
1691
1692
1693# Toy application to test this Frame
1694class ViewApp(wx.App):
1695    """
1696    """
1697    SIZE = (GUIFRAME_WIDTH,GUIFRAME_HEIGHT)
1698    TITLE = config.__appname__
1699    PROG_SPLASH_PATH = PROG_SPLASH_SCREEN
1700    STYLE = GUIFRAME.SINGLE_APPLICATION
1701    SPLASH_WIDTH = 500
1702    SPLASH_HEIGHT = 300
1703    SPLASH_MAX_DISPLAY_TIME = 3000 #3 sec
1704   
1705    def OnInit(self):
1706        """
1707        """
1708        pos, size = self.window_placement(self.SIZE)
1709        self.frame = ViewerFrame(parent=None, 
1710                                 title=self.TITLE, 
1711                                 pos=pos, 
1712                                 gui_style = self.STYLE,
1713                                 size=size) 
1714         # Display a splash screen on top of the frame.
1715        if len(sys.argv) > 1 and '--time' in sys.argv[1:]:
1716            log_time("Starting to display the splash screen")
1717        if self.PROG_SPLASH_PATH is not None and \
1718            os.path.isfile(self.PROG_SPLASH_PATH):
1719            try:
1720                s_screen = self.display_splash_screen(parent=self.frame, path=self.PROG_SPLASH_PATH)   
1721            except:
1722                try: 
1723                    self.frame.Show()
1724                except:
1725                   
1726                    msg = "Cannot display splash screen\n"
1727                    msg += str (sys.exc_value)
1728                    #raise
1729                    logging.error(msg)
1730        else:
1731            self.frame.Show()
1732       
1733
1734        if hasattr(self.frame, 'special'):
1735            self.frame.special.SetCurrent()
1736        self.SetTopWindow(self.frame)
1737        import time
1738       
1739        return True
1740   
1741    def set_manager(self, manager):
1742        """
1743        Sets a reference to the application manager
1744        of the GUI manager (Frame)
1745        """
1746        self.frame.set_manager(manager)
1747       
1748    def build_gui(self):
1749        """
1750        Build the GUI
1751        """
1752        self.frame.build_gui()
1753        self.frame.post_init()
1754       
1755    def set_welcome_panel(self, panel_class):
1756        """
1757        Set the welcome panel
1758       
1759        :param panel_class: class of the welcome panel to be instantiated
1760       
1761        """
1762        self.frame.set_welcome_panel(panel_class)
1763       
1764    def add_perspective(self, perspective):
1765        """
1766        Manually add a perspective to the application GUI
1767        """
1768        self.frame.add_perspective(perspective)
1769   
1770    def window_placement(self, size):
1771        """
1772        Determines the position and size of the application frame such that it
1773        fits on the user's screen without obstructing (or being obstructed by)
1774        the Windows task bar.  The maximum initial size in pixels is bounded by
1775        WIDTH x HEIGHT.  For most monitors, the application
1776        will be centered on the screen; for very large monitors it will be
1777        placed on the left side of the screen.
1778        """
1779        window_width, window_height = size
1780        screen_size = wx.GetDisplaySize()
1781        window_height = window_height if screen_size[1]>window_height else screen_size[1]-50
1782        window_width  = window_width if screen_size[0]> window_width else screen_size[0]-50
1783        xpos = ypos = 0
1784
1785        # Note that when running Linux and using an Xming (X11) server on a PC
1786        # with a dual  monitor configuration, the reported display size may be
1787        # that of both monitors combined with an incorrect display count of 1.
1788        # To avoid displaying this app across both monitors, we check for
1789        # screen 'too big'.  If so, we assume a smaller width which means the
1790        # application will be placed towards the left hand side of the screen.
1791
1792        _, _, x, y = wx.Display().GetClientArea() # size excludes task bar
1793        if len(sys.argv) > 1 and '--platform' in sys.argv[1:]:
1794            w, h = wx.DisplaySize()  # size includes task bar area
1795        if x > 1920: x = 1280  # display on left side, not centered on screen
1796        if x > window_width:  xpos = (x - window_width)/2
1797        if y > window_height: ypos = (y - window_height)/2
1798
1799        # Return the suggested position and size for the application frame.
1800        return (xpos, ypos), (min(x, window_width), min(y, window_height))
1801   
1802    def display_splash_screen(self, parent, 
1803                              path=PROG_SPLASH_SCREEN):
1804        """Displays the splash screen.  It will exactly cover the main frame."""
1805
1806        # Prepare the picture.  On a 2GHz intel cpu, this takes about a second.
1807        x, y = parent.GetSizeTuple()
1808        image = wx.Image(path, wx.BITMAP_TYPE_PNG)
1809        image.Rescale(self.SPLASH_WIDTH, self.SPLASH_HEIGHT, wx.IMAGE_QUALITY_HIGH)
1810        bm = image.ConvertToBitmap()
1811
1812        # Create and show the splash screen.  It will disappear only when the
1813        # program has entered the event loop AND either the timeout has expired
1814        # or the user has left clicked on the screen.  Thus any processing
1815        # performed in this routine (including sleeping) or processing in the
1816        # calling routine (including doing imports) will prevent the splash
1817        # screen from disappearing.
1818        #
1819        # Note that on Linux, the timeout appears to occur immediately in which
1820        # case the splash screen disappears upon entering the event loop.
1821        s_screen = wx.SplashScreen(bitmap=bm,
1822                         splashStyle=(wx.SPLASH_TIMEOUT|
1823                                              wx.SPLASH_CENTRE_ON_SCREEN),
1824                                 style=(wx.SIMPLE_BORDER|
1825                                        wx.FRAME_NO_TASKBAR|
1826                                        wx.STAY_ON_TOP),
1827                                       
1828                        milliseconds=self.SPLASH_MAX_DISPLAY_TIME,
1829                        parent=parent,
1830                        id=wx.ID_ANY)
1831
1832        s_screen.Bind(wx.EVT_CLOSE, self.on_close_splash_screen)
1833        s_screen.Show()
1834        return s_screen
1835       
1836       
1837    def on_close_splash_screen(self, event):
1838        """
1839        """
1840        self.frame.Show(True)
1841        event.Skip()
1842     
1843     
1844
1845       
1846
1847if __name__ == "__main__": 
1848    app = ViewApp(0)
1849    app.MainLoop()
1850
1851             
Note: See TracBrowser for help on using the repository browser.