source: sasview/guiframe/gui_manager.py @ b2d9826

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

working 1D/2D toggle

  • Property mode set to 100644
File size: 72.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_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 append_theory(self, data_id, theory, state=None):
434        """
435        """
436        data_state = self._data_manager.append_theory(data_id=data_id, 
437                                                      theory=theory,
438                                                      state=state)
439        self._data_panel.load_data_list(data_state)
440       
441    def update_data(self, prev_data, new_data):
442        """
443        """
444        prev_id, data_state = self._data_manager.update_data(prev_data=prev_data, 
445                                       new_data=new_data)
446        self._data_panel.remove_by_id(prev_id)
447        self._data_panel.load_data_list(data_state)
448       
449       
450    def freeze(self, data_id, theory_id):
451        """
452        """
453        data_state_list = self._data_manager.freeze_theory(data_id=data_id, 
454                                                theory_id=theory_id)
455       
456        self._data_panel.load_data_list(list=data_state_list)
457        for data_state in data_state_list:
458            theory_list = data_state.get_theory()
459            for new_plot in theory_list:
460                wx.PostEvent(self, NewplotEvent(plot=new_plot,
461                                             title=new_plot.title))
462       
463    def delete_data(self, data):
464        """
465        """
466        self._current_perspective.delete_data(data)
467       
468   
469    def get_context_menu(self, plotpanel=None):
470        """
471        Get the context menu items made available
472        by the different plug-ins.
473        This function is used by the plotting module
474        """
475        if plotpanel is None:
476            return
477        menu_list = []
478        for item in self.plugins:
479            menu_list.extend(item.get_context_menu(plotpanel=plotpanel))
480        return menu_list
481       
482    def popup_panel(self, p):
483        """
484        Add a panel object to the AUI manager
485       
486        :param p: panel object to add to the AUI manager
487       
488        :return: ID of the event associated with the new panel [int]
489       
490        """
491        ID = wx.NewId()
492        self.panels[str(ID)] = p
493        count = 0
494        for item in self.panels:
495            if self.panels[item].window_name.startswith(p.window_name): 
496                count += 1
497        windowname = p.window_name
498        caption = p.window_caption
499        if count > 0:
500            windowname += str(count+1)
501            caption += (' '+str(count))
502        p.window_name = windowname
503        p.window_caption = caption
504           
505        style1 = self.__gui_style & GUIFRAME.FIXED_PANEL
506        style2 = self.__gui_style & GUIFRAME.FLOATING_PANEL
507        if style1 == GUIFRAME.FIXED_PANEL:
508            self._mgr.AddPane(p, wx.aui.AuiPaneInfo().
509                              Name(windowname).Caption(caption).
510                              MinimizeButton().
511                              Resizable(True).
512                              # Use a large best size to make sure the AUI
513                              # manager takes all the available space
514                              BestSize(wx.Size(PLOPANEL_WIDTH, PLOPANEL_HEIGTH)))
515            self._popup_fixed_panel(p)
516   
517        elif style2 == GUIFRAME.FLOATING_PANEL:
518            self._mgr.AddPane(p, wx.aui.AuiPaneInfo().
519                              Name(windowname).Caption(caption).
520                              MinimizeButton().
521                              Resizable(True).
522                              # Use a large best size to make sure the AUI
523                              #  manager takes all the available space
524                              BestSize(wx.Size(PLOPANEL_WIDTH, PLOPANEL_HEIGTH)))
525            self._popup_floating_panel(p)
526           
527        pane = self._mgr.GetPane(windowname)
528        self._mgr.MaximizePane(pane)
529        self._mgr.RestoreMaximizedPane()
530        # Register for showing/hiding the panel
531        wx.EVT_MENU(self, ID, self._on_view)
532       
533        self._mgr.Update()
534        return ID
535       
536    def _setup_menus(self):
537        """
538        Set up the application menus
539        """
540        # Menu
541        self._menubar = wx.MenuBar()
542        self._add_menu_file()
543        self._add_menu_data()
544        self._add_menu_application()
545        self._add_menu_edit()
546        self._add_menu_tool()
547        self._add_current_plugin_menu()
548        self._add_menu_window()
549        self._add_help_menu()
550        self.SetMenuBar(self._menubar)
551       
552    def _setup_tool_bar(self):
553        """
554        add toolbar to the frame
555        """
556        #set toolbar
557        self._toolbar = GUIToolBar(self, -1)
558        self.SetToolBar(self._toolbar)
559        self._update_toolbar_helper()
560        #self._on_hide_toolbar(event=None)
561   
562    def _update_toolbar_helper(self):
563        """
564        """
565        application_name = 'No Selected Application'
566        panel_name = 'No Panel on Focus'
567        self._toolbar.update_toolbar(self.panel_on_focus)
568        if self._current_perspective is not None:
569            application_name = self._current_perspective.sub_menu
570        if self.panel_on_focus is not None:
571            panel_name = self.panel_on_focus.window_caption
572        self._toolbar.update_button(application_name=application_name, 
573                                        panel_name=panel_name)
574        self._toolbar.Realize()
575       
576    def _add_menu_tool(self):
577        """
578        Tools menu
579        Go through plug-ins and find tools to populate the tools menu
580        """
581        style = self.__gui_style & GUIFRAME.TOOL_ON
582        if style == GUIFRAME.TOOL_ON:
583            self._tool_menu = None
584            for item in self.plugins:
585                if hasattr(item, "get_tools"):
586                    for tool in item.get_tools():
587                        # Only create a menu if we have at least one tool
588                        if self._tool_menu is None:
589                            self._tool_menu = wx.Menu()
590                        id = wx.NewId()
591                        self._tool_menu.Append(id, tool[0], tool[1])
592                        wx.EVT_MENU(self, id, tool[2])
593            if self._tool_menu is not None:
594                self._menubar.Append(self._tool_menu, '&Tools')
595               
596    def _add_current_plugin_menu(self):
597        """
598        add current plugin menu
599        Look for plug-in menus
600        Add available plug-in sub-menus.
601        """
602        if (self._menubar is None) or (self._current_perspective is None):
603            return
604        #replace or add a new menu for the current plugin
605       
606        pos = self._menubar.FindMenu(str(self._applications_menu_name))
607        if pos != -1:
608            menu_list = self._current_perspective.populate_menu(self)
609            if menu_list:
610                for (menu, name) in menu_list:
611                    hidden_menu = self._menubar.Replace(pos, menu, name) 
612                    self._applications_menu_name = name
613                #self._applications_menu_pos = pos
614            else:
615                hidden_menu = self._menubar.Remove(pos)
616                self._applications_menu_name = None
617            #get the position of the menu when it first added
618            self._applications_menu_pos = pos
619           
620        else:
621            menu_list = self._current_perspective.populate_menu(self)
622            if menu_list:
623                for (menu,name) in menu_list:
624                    if self._applications_menu_pos == -1:
625                        self._menubar.Append(menu, name)
626                    else:
627                        self._menubar.Insert(self._applications_menu_pos, menu, name)
628                    self._applications_menu_name = name
629                 
630    def _add_help_menu(self):
631        """
632        add help menu
633        """
634        # Help menu
635        self._help_menu = wx.Menu()
636        style = self.__gui_style & GUIFRAME.WELCOME_PANEL_ON
637        if style == GUIFRAME.WELCOME_PANEL_ON:
638            # add the welcome panel menu item
639            if self.defaultPanel is not None:
640                id = wx.NewId()
641                self._help_menu.Append(id, '&Welcome', '')
642                self._help_menu.AppendSeparator()
643                wx.EVT_MENU(self, id, self.show_welcome_panel)
644        # Look for help item in plug-ins
645        for item in self.plugins:
646            if hasattr(item, "help"):
647                id = wx.NewId()
648                self._help_menu.Append(id,'&%s help' % item.sub_menu, '')
649                wx.EVT_MENU(self, id, item.help)
650        if config._do_aboutbox:
651            id = wx.NewId()
652            self._help_menu.Append(id,'&About', 'Software information')
653            wx.EVT_MENU(self, id, self._onAbout)
654       
655        # Checking for updates needs major refactoring to work with py2exe
656        # We need to make sure it doesn't hang the application if the server
657        # is not up. We also need to make sure there's a proper executable to
658        # run if we spawn a new background process.
659        #id = wx.NewId()
660        #self._help_menu.Append(id,'&Check for update',
661        #'Check for the latest version of %s' % config.__appname__)
662        #wx.EVT_MENU(self, id, self._check_update)
663        self._menubar.Append(self._help_menu, '&Help')
664           
665    def _add_menu_window(self):
666        """
667        add a menu window to the menu bar
668        Window menu
669        Attach a menu item for each panel in our
670        panel list that also appears in a plug-in.
671       
672        Only add the panel menu if there is only one perspective and
673        it has more than two panels.
674        Note: the first plug-in is always the plotting plug-in.
675        The first application
676        #plug-in is always the second one in the list.
677        """
678        self._window_menu = wx.Menu()
679        if self._plotting_plugin is not None:
680            for (menu, name) in self._plotting_plugin.populate_menu(self):
681                self._window_menu.AppendSubMenu(menu, name)
682        self._menubar.Append(self._window_menu, '&Window')
683     
684        style = self.__gui_style & GUIFRAME.MANAGER_ON
685        id = wx.NewId()
686        self._data_panel_menu = self._window_menu.Append(id,
687                                                '&Data Explorer ON', '')
688        wx.EVT_MENU(self, id, self.show_data_panel)
689        if style == GUIFRAME.MANAGER_ON:
690            self._data_panel_menu.SetText('Data Explorer OFF')
691        else:
692            self._data_panel_menu.SetText('Data Explorer ON')
693           
694        style = self.__gui_style & GUIFRAME.PLOTTING_ON
695        if style == GUIFRAME.PLOTTING_ON:
696            self._window_menu.AppendSeparator()
697            id = wx.NewId()
698            preferences_menu = wx.Menu()
699            hint = "Plot panels will floating"
700            preferences_menu.Append(id, '&Floating Plot Panel', hint)
701            wx.EVT_MENU(self, id, self.set_plotpanel_floating)
702            id = wx.NewId()
703            hint = "Plot panels will displayed within the frame"
704            preferences_menu.Append(id, '&Fixed Plot Panel', hint)
705            wx.EVT_MENU(self, id, self.set_plotpanel_fixed)
706            id = wx.NewId()
707            style1 = self.__gui_style & GUIFRAME.MULTIPLE_APPLICATIONS
708            if style1 == GUIFRAME.MULTIPLE_APPLICATIONS:
709                id = wx.NewId()
710                self._toolbar_menu = preferences_menu.Append(id,'&Hide Toolbar', '')
711                wx.EVT_MENU(self, id, self._on_hide_toolbar)
712            self._window_menu.AppendSubMenu(preferences_menu,'&Preferences')
713        if self._window_menu.GetMenuItemCount() == 0:
714            pos = self._menubar.FindMenu('Window')
715            self._menubar.Remove(pos)
716        #wx.EVT_MENU(self, id, self.show_preferences_panel)   
717        """
718        if len(self.plugins) == 2:
719            plug = self.plugins[1]
720            pers = plug.get_perspective()
721       
722            if len(pers) > 1:
723                self._window_menu = wx.Menu()
724                for item in self.panels:
725                    if item == 'default':
726                        continue
727                    panel = self.panels[item]
728                    if panel.window_name in pers:
729                        self._window_menu.Append(int(item),
730                                                  panel.window_caption,
731                                        "Show %s window" % panel.window_caption)
732                        wx.EVT_MENU(self, int(item), self._on_view)
733                self._menubar.Append(self._window_menu, '&Window')
734                """
735               
736    def _add_menu_application(self):
737        """
738       
739        # Attach a menu item for each defined perspective or application.
740        # Only add the perspective menu if there are more than one perspectives
741        add menu application
742        """
743        style = self.__gui_style & GUIFRAME.MULTIPLE_APPLICATIONS
744        if style == GUIFRAME.MULTIPLE_APPLICATIONS:
745            plug_data_count = False
746            plug_no_data_count = False
747            self._applications_menu = wx.Menu()
748            separator = self._applications_menu.AppendSeparator()
749            for plug in self.plugins:
750                if len(plug.get_perspective()) > 0:
751                    id = wx.NewId()
752                    if plug.use_data():
753                        self._applications_menu.InsertCheckItem(0, id, plug.sub_menu,
754                                      "Switch to application: %s" % plug.sub_menu)
755                        plug_data_count = True
756                    else:
757                        plug_no_data_count = True
758                        self._applications_menu.AppendCheckItem(id, plug.sub_menu,
759                                      "Switch to application: %s" % plug.sub_menu)
760                    wx.EVT_MENU(self, id, plug.on_perspective)
761            if not (plug_data_count and  plug_no_data_count):
762                self._applications_menu.RemoveItem(separator)
763            self._menubar.Append(self._applications_menu, '&Applications')
764            self._check_applications_menu()
765           
766    def _add_menu_file(self):
767        """
768        add menu file
769        """
770       
771         # File menu
772        self._file_menu = wx.Menu()
773        style = self.__gui_style & GUIFRAME.DATALOADER_ON
774        if style == GUIFRAME.DATALOADER_ON:
775            # some menu of plugin to be seen under file menu
776            hint_load_file = "Read state's files and load"
777            hint_load_file += " them into the application"
778            id = wx.NewId()
779            self._save_appl_menu = self._file_menu.Append(id, 
780                                    '&Open State from File', hint_load_file)
781            wx.EVT_MENU(self, id, self._on_open_state)
782            id = wx.NewId()
783            self._save_appl_menu = self._file_menu.Append(id, 
784                                                          '&Save Application',
785                                 'Save state of the current active application')
786            wx.EVT_MENU(self, id, self._on_save_application)
787            id = wx.NewId()
788            self._file_menu.Append(id, '&Save Project',
789                                 'Save the state of the whole application')
790            wx.EVT_MENU(self, id, self._on_save_project)
791            self._file_menu.AppendSeparator()
792       
793        id = wx.NewId()
794        self._file_menu.Append(id, '&Quit', 'Exit') 
795        wx.EVT_MENU(self, id, self.Close)
796        # Add sub menus
797        self._menubar.Append(self._file_menu, '&File')
798       
799    def _add_menu_edit(self):
800        """
801        add menu edit
802        """
803        # Edit Menu
804        self._edit_menu = wx.Menu()
805        self._edit_menu.Append(GUIFRAME_ID.UNDO_ID, '&Undo', 
806                               'Undo the previous action')
807        wx.EVT_MENU(self, GUIFRAME_ID.UNDO_ID, self.on_undo_panel)
808        self._edit_menu.Append(GUIFRAME_ID.REDO_ID, '&Redo', 
809                               'Redo the previous action')
810        wx.EVT_MENU(self, GUIFRAME_ID.REDO_ID, self.on_redo_panel)
811        #self._edit_menu.AppendSeparator()
812        #self._edit_menu.Append(GUIFRAME_ID.BOOKMARK_ID, '&Bookmark',
813        #                       'bookmark current panel')
814        #wx.EVT_MENU(self, GUIFRAME_ID.BOOKMARK_ID, self.append_bookmark)
815        self._edit_menu.Append(GUIFRAME_ID.SAVE_ID, '&Save As', 
816                               'Save current panel into file')
817        wx.EVT_MENU(self, GUIFRAME_ID.SAVE_ID, self.on_save_panel)
818        self._edit_menu.AppendSeparator()
819        self._edit_menu.Append(GUIFRAME_ID.PREVIEW_ID, '&Print Preview',
820                               'Preview current panel')
821        wx.EVT_MENU(self, GUIFRAME_ID.PREVIEW_ID, self.on_preview_panel)
822        self._edit_menu.Append(GUIFRAME_ID.PRINT_ID, '&Print',
823                               'Print current panel')
824        wx.EVT_MENU(self, GUIFRAME_ID.PRINT_ID, self.on_print_panel)
825        self._edit_menu.AppendSeparator()
826        self._edit_menu.Append(GUIFRAME_ID.ZOOM_ID, '&Zoom',
827                               'Zoom current panel')
828        wx.EVT_MENU(self, GUIFRAME_ID.ZOOM_ID, self.on_zoom_panel)
829        self._edit_menu.Append(GUIFRAME_ID.ZOOM_IN_ID, '&Zoom In',
830                               'Zoom in current panel')
831        wx.EVT_MENU(self, GUIFRAME_ID.ZOOM_IN_ID, self.on_zoom_in_panel)
832        self._edit_menu.Append(GUIFRAME_ID.ZOOM_OUT_ID, '&Zoom Out', 
833                               'Zoom out current panel')
834        wx.EVT_MENU(self, GUIFRAME_ID.ZOOM_OUT_ID, self.on_zoom_out_panel)
835        self._edit_menu.Append(GUIFRAME_ID.DRAG_ID, '&Drag',
836                               'Drag current panel')
837        wx.EVT_MENU(self, GUIFRAME_ID.DRAG_ID, self.on_drag_panel)
838        self._edit_menu.Append(GUIFRAME_ID.RESET_ID, '&Reset', 
839                               'Reset current panel')
840        wx.EVT_MENU(self, GUIFRAME_ID.RESET_ID, self.on_reset_panel)
841        self._menubar.Append(self._edit_menu,  '&Edit')
842        self.enable_edit_menu()
843       
844    def get_style(self):
845        """
846        """
847        return  self.__gui_style
848   
849    def _add_menu_data(self):
850        """
851        Add menu item item data to menu bar
852        """
853        if self._data_plugin is not None:
854            menu_list = self._data_plugin.populate_menu(self)
855            if menu_list:
856                for (menu, name) in menu_list:
857                    self._menubar.Append(menu, name)
858           
859    def _on_hide_toolbar(self, event=None):
860        """
861        hide or show toolbar
862        """
863        if self._toolbar is None:
864            return
865        if self._toolbar.IsShown():
866            if self._toolbar_menu is not None:
867                self._toolbar_menu.SetItemLabel('Show Toolbar')
868            self._toolbar.Hide()
869        else:
870            if self._toolbar_menu is not None:
871                self._toolbar_menu.SetItemLabel('Hide Toolbar')
872            self._toolbar.Show()
873        self._toolbar.Realize()
874       
875    def _on_status_event(self, evt):
876        """
877        Display status message
878        """
879        self.sb.set_status(event=evt)
880       
881    def _on_view(self, evt):
882        """
883        A panel was selected to be shown. If it's not already
884        shown, display it.
885       
886        :param evt: menu event
887       
888        """
889        self.show_panel(evt.GetId())
890       
891    def on_close_welcome_panel(self):
892        """
893        Close the welcome panel
894        """
895        if self.defaultPanel is None:
896            return 
897        self._mgr.GetPane(self.panels["default"].window_name).Hide()
898        self._mgr.Update()
899        # set a default perspective
900        self.set_default_perspective()
901       
902    def show_welcome_panel(self, event):
903        """   
904        Display the welcome panel
905        """
906        if self.defaultPanel is None:
907            return 
908        for id in self.panels.keys():
909            if id  ==  'default':
910                # Show default panel
911                if not self._mgr.GetPane(self.panels["default"].window_name).IsShown():
912                    self._mgr.GetPane(self.panels["default"].window_name).Show(True)
913            elif id == "data_panel":
914                flag = self._mgr.GetPane(self.panels["data_panel"].window_name).IsShown()
915                self._mgr.GetPane(self.panels["data_panel"].window_name).Show(flag)
916            else:
917                self._mgr.GetPane(self.panels[id].window_name).IsShown()
918                self._mgr.GetPane(self.panels[id].window_name).Hide()
919        self._mgr.Update()
920       
921    def show_panel(self, uid):
922        """
923        Shows the panel with the given id
924       
925        :param uid: unique ID number of the panel to show
926       
927        """
928        ID = str(uid)
929        config.printEVT("show_panel: %s" % ID)
930        if ID in self.panels.keys():
931            if not self._mgr.GetPane(self.panels[ID].window_name).IsShown():
932                self._mgr.GetPane(self.panels[ID].window_name).Show()
933                # Hide default panel
934                self._mgr.GetPane(self.panels["default"].window_name).Hide()
935            self._mgr.Update()
936           
937    def hide_panel(self, uid):
938        """
939        hide panel
940        """
941        ID = str(uid)
942        config.printEVT("hide_panel: %s" % ID)
943        if ID in self.panels.keys():
944            if self._mgr.GetPane(self.panels[ID].window_name).IsShown():
945                self._mgr.GetPane(self.panels[ID].window_name).Hide()
946                # Hide default panel
947                self._mgr.GetPane(self.panels["default"].window_name).Hide()
948            self._mgr.Update()
949           
950    def delete_panel(self, uid):
951        """
952        delete panel given uid
953        """
954        ID = str(uid)
955        config.printEVT("delete_panel: %s" % ID)
956        if ID in self.panels.keys():
957            self._mgr.DetachPane(self.panels[ID])
958            del self.panels[ID]
959            self._mgr.Update()
960     
961    def clear_panel(self):
962        """
963        """
964        for item in self.panels:
965            try:
966                self.panels[item].clear_panel()
967            except:
968                pass
969           
970    def create_gui_data(self, data, path=None):
971        """
972        """
973        return self._data_manager.create_gui_data(data, path)
974   
975    def get_data(self, path):
976        """
977        """
978        message = ""
979        log_msg = ''
980        output = []
981        error_message = ""
982        basename  = os.path.basename(path)
983        root, extension = os.path.splitext(basename)
984        if extension.lower() not in EXTENSIONS:
985            log_msg = "File Loader cannot "
986            log_msg += "load: %s\n" % str(basename)
987            log_msg += "Try Data opening...."
988            logging.info(log_msg)
989            self.load_complete(output=output, error_message=error_message,
990                   message=log_msg, path=path)   
991            return
992       
993        #reading a state file
994        for plug in self.plugins:
995            reader, ext = plug.get_extensions()
996            if reader is not None:
997                #read the state of the single plugin
998                if extension == ext:
999                    reader.read(path)
1000                    return
1001                elif extension == '.svs':
1002                    reader.read(path)
1003       
1004        style = self.__gui_style & GUIFRAME.MANAGER_ON
1005        if style == GUIFRAME.MANAGER_ON:
1006            if self._data_panel is not None:
1007                data_state = self._data_manager.get_selected_data()
1008                self._data_panel.load_data_list(data_state)
1009                self._mgr.GetPane(self._data_panel.window_name).Show(True)
1010                       
1011    def _on_open_state(self, event):
1012        """
1013        """
1014        path = None
1015        if self._default_save_location == None:
1016            self._default_save_location = os.getcwd()
1017 
1018        wlist = ['SansView files (*.svs)|*.svs',
1019                  'P(r) files (*.prv)|*.prv',
1020                  'Fitting files (*.fitv)|*.fitv',
1021                  'Invariant files (*.inv)|*.inv']
1022        wlist = '|'.join(wlist)
1023        dlg = wx.FileDialog(self, 
1024                            "Choose a file", 
1025                            self._default_save_location, "",
1026                             wlist)
1027        if dlg.ShowModal() == wx.ID_OK:
1028            path = dlg.GetPath()
1029            if path is not None:
1030                self._default_save_location = os.path.dirname(path)
1031        dlg.Destroy()
1032        if path and os.path.isfile(path):
1033            basename  = os.path.basename(path)
1034            if  basename.endswith('.svs'):
1035                #remove panels for new states
1036                for plug in self.plugins:
1037                    plug.clear_panel()
1038                    self.panel_on_focus = None
1039               
1040            self.get_data(path)
1041               
1042        if self.defaultPanel is not None and \
1043            self._mgr.GetPane(self.panels["default"].window_name).IsShown():
1044            self.on_close_welcome_panel()
1045   
1046    def _on_save_application(self, event):
1047        """
1048        save the state of the current active application
1049        """
1050        if self.panel_on_focus is not None:
1051            self.panel_on_focus.on_save(event)
1052           
1053    def _on_save_project(self, event):
1054        """
1055        save the state of the current active application
1056        """
1057        ## Default file location for save
1058        self._default_save_location = os.getcwd()
1059        if self._current_perspective is  None:
1060            return
1061        reader, ext = self._current_perspective.get_extensions()
1062        path = None
1063        dlg = wx.FileDialog(self, "Save Project file",
1064                            self._default_save_location, "", '.svs', wx.SAVE)
1065        if dlg.ShowModal() == wx.ID_OK:
1066            path = dlg.GetPath()
1067            self._default_save_location = os.path.dirname(path)
1068        else:
1069            return None
1070        dlg.Destroy()
1071        if path is None:
1072            return
1073        # default cansas xml doc
1074        doc = None
1075        for panel in self.panels.values():
1076            doc = self.on_save_helper(doc, reader, panel, path)
1077       
1078           
1079    def on_save_helper(self, doc, reader, panel, path):
1080        """
1081        Save state into a file
1082        """
1083        try:
1084            data = panel.get_data()
1085            state = panel.get_state()
1086            if reader is not None:
1087                if data is not None:
1088                    new_doc = reader.write_toXML(data, state)
1089                    if hasattr(doc, "firstChild"):
1090                        child = new_doc.firstChild.firstChild
1091                        doc.firstChild.appendChild(child) 
1092                    else:
1093                        doc = new_doc
1094        except: 
1095            raise
1096            #pass
1097        # Write the XML document
1098        if doc != None:
1099            fd = open(path, 'w')
1100            fd.write(doc.toprettyxml())
1101            fd.close()
1102        else:
1103            raise
1104            #print "Nothing to save..."
1105            #raise RuntimeError, "%s is not a SansView (.svs) file..." % path
1106        return doc
1107
1108    def quit_guiframe(self):
1109        """
1110        Pop up message to make sure the user wants to quit the application
1111        """
1112        message = "Do you really want to quit \n"
1113        message += "this application?"
1114        dial = wx.MessageDialog(self, message, 'Question',
1115                           wx.YES_NO|wx.YES_DEFAULT|wx.ICON_QUESTION)
1116        if dial.ShowModal() == wx.ID_YES:
1117            return True
1118        else:
1119            return False   
1120       
1121    def Close(self, event=None):
1122        """
1123        Quit the application
1124        """
1125        #flag = self.quit_guiframe()
1126        if True:
1127            wx.Exit()
1128            sys.exit()
1129
1130    def _check_update(self, event=None): 
1131        """
1132        Check with the deployment server whether a new version
1133        of the application is available.
1134        A thread is started for the connecting with the server. The thread calls
1135        a call-back method when the current version number has been obtained.
1136        """
1137        if hasattr(config, "__update_URL__"):
1138            import version
1139            checker = version.VersionThread(config.__update_URL__,
1140                                            self._process_version,
1141                                            baggage=event==None)
1142            checker.start() 
1143   
1144    def _process_version(self, version, standalone=True):
1145        """
1146        Call-back method for the process of checking for updates.
1147        This methods is called by a VersionThread object once the current
1148        version number has been obtained. If the check is being done in the
1149        background, the user will not be notified unless there's an update.
1150       
1151        :param version: version string
1152        :param standalone: True of the update is being checked in
1153           the background, False otherwise.
1154           
1155        """
1156        try:
1157            if cmp(version, config.__version__) > 0:
1158                msg = "Version %s is available! See the Help "
1159                msg += "menu to download it." % version
1160                self.SetStatusText(msg)
1161                if not standalone:
1162                    import webbrowser
1163                    webbrowser.open(config.__download_page__)
1164            else:
1165                if not standalone:
1166                    msg = "You have the latest version"
1167                    msg += " of %s" % config.__appname__
1168                    self.SetStatusText(msg)
1169        except:
1170            msg = "guiframe: could not get latest application"
1171            msg += " version number\n  %s" % sys.exc_value
1172            logging.error(msg)
1173            if not standalone:
1174                msg = "Could not connect to the application server."
1175                msg += " Please try again later."
1176                self.SetStatusText(msg)
1177                   
1178    def _onAbout(self, evt):
1179        """
1180        Pop up the about dialog
1181       
1182        :param evt: menu event
1183       
1184        """
1185        if config._do_aboutbox:
1186            import aboutbox 
1187            dialog = aboutbox.DialogAbout(None, -1, "")
1188            dialog.ShowModal()           
1189           
1190    def set_manager(self, manager):
1191        """
1192        Sets the application manager for this frame
1193       
1194        :param manager: frame manager
1195        """
1196        self.app_manager = manager
1197       
1198    def post_init(self):
1199        """
1200        This initialization method is called after the GUI
1201        has been created and all plug-ins loaded. It calls
1202        the post_init() method of each plug-in (if it exists)
1203        so that final initialization can be done.
1204        """
1205        for item in self.plugins:
1206            if hasattr(item, "post_init"):
1207                item.post_init()
1208       
1209    def set_default_perspective(self):
1210        """
1211        Choose among the plugin the first plug-in that has
1212        "set_default_perspective" method and its return value is True will be
1213        as a default perspective when the welcome page is closed
1214        """
1215        for item in self.plugins:
1216            if hasattr(item, "set_default_perspective"):
1217                if item.set_default_perspective():
1218                    item.on_perspective(event=None)
1219                    return 
1220       
1221    def set_perspective(self, panels):
1222        """
1223        Sets the perspective of the GUI.
1224        Opens all the panels in the list, and closes
1225        all the others.
1226       
1227        :param panels: list of panels
1228        """
1229        for item in self.panels:
1230            # Check whether this is a sticky panel
1231            if hasattr(self.panels[item], "ALWAYS_ON"):
1232                if self.panels[item].ALWAYS_ON:
1233                    continue 
1234            if self.panels[item].window_name in panels:
1235                if not self._mgr.GetPane(self.panels[item].window_name).IsShown():
1236                    self._mgr.GetPane(self.panels[item].window_name).Show()
1237            else:
1238                # always show the data panel if enable
1239                style = self.__gui_style & GUIFRAME.MANAGER_ON
1240                if (style == GUIFRAME.MANAGER_ON) and self.panels[item] == self._data_panel:
1241                    if 'data_panel' in self.panels.keys():
1242                        flag = self._mgr.GetPane(self.panels['data_panel'].window_name).IsShown()
1243                        self._mgr.GetPane(self.panels['data_panel'].window_name).Show(flag)
1244                else:
1245                    if self._mgr.GetPane(self.panels[item].window_name).IsShown():
1246                        self._mgr.GetPane(self.panels[item].window_name).Hide()
1247        self._mgr.Update()
1248       
1249    def show_data_panel(self, event=None):
1250        """
1251        show the data panel
1252        """
1253        label = self._data_panel_menu.GetText()
1254        if label == 'Data Explorer ON':
1255            pane = self._mgr.GetPane(self.panels["data_panel"].window_name)
1256            #if not pane.IsShown():
1257            pane.Show(True)
1258            self._mgr.Update()
1259            self.__gui_style = self.__gui_style | GUIFRAME.MANAGER_ON
1260           
1261            self._data_panel_menu.SetText('Data Explorer OFF')
1262        else:
1263            pane = self._mgr.GetPane(self.panels["data_panel"].window_name)
1264            #if not pane.IsShown():
1265            pane.Show(False)
1266            self._mgr.Update()
1267            self.__gui_style = self.__gui_style & (~GUIFRAME.MANAGER_ON)
1268            self._data_panel_menu.SetText('Data Explorer ON')
1269   
1270    def add_data_helper(self, data_list):
1271        """
1272        """
1273        self._data_manager.add_data(data_list)
1274       
1275    def add_data(self, data_list):
1276        """
1277        receive a list of data . store them its data manager if possible
1278        determine if data was be plot of send to data perspectives
1279        """
1280        #send a list of available data to plotting plugin
1281        avalaible_data = []
1282        theory_list = []
1283        if self._data_manager is not None:
1284            self._data_manager.add_data(data_list)
1285            avalaible_data = self._data_manager.get_all_data()
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_list)
1295       
1296         # set data in the data panel
1297        if self._data_panel is not None:
1298            data_state = self._data_manager.get_selected_data()
1299            self._data_panel.load_data_list(data_state)
1300           
1301    def get_data_from_panel(self, data_id, plot=False,append=False):
1302        """
1303        receive a list of data key retreive the data from data manager and set
1304        then to the current perspective
1305        """
1306        data_dict = self._data_manager.get_by_id(data_id)
1307        data_list = []
1308        for data_state in data_dict.values():
1309            data_list.append(data_state.data)
1310        if plot:
1311            self.plot_data(data_list, append=append)
1312        else:
1313            #sent data to active application
1314            self.set_data(data_list=data_list)
1315       
1316       
1317    def set_data(self, data_list):
1318        """
1319        set data to current perspective
1320        """
1321        if self._current_perspective is not None:
1322            try:
1323                self._current_perspective.set_data(data_list)
1324            except:
1325                msg = str(sys.exc_value)
1326                wx.PostEvent(self, StatusEvent(status=msg, info="error"))
1327        else:
1328            msg = "Guiframe does not have a current perspective"
1329            logging.info(msg)
1330           
1331    def plot_data(self, data_list, append=False):
1332        """
1333        send a list of data to plot
1334        """
1335        if not data_list:
1336            message = "Please check data to plot or append"
1337            wx.PostEvent(self, StatusEvent(status=message, info='warning'))
1338            return 
1339        for new_plot in data_list:
1340            if append:
1341                if self.panel_on_focus is None or \
1342                    not self.enable_add_data(new_plot):
1343                    message = "cannot append plot. No plot panel on focus!"
1344                    message += "please click on any available plot to set focus"
1345                    wx.PostEvent(self, StatusEvent(status=message, 
1346                                                   info='warning'))
1347                    return 
1348                else:
1349                    if self.enable_add_data(new_plot) and \
1350                    hasattr(self.panel_on_focus, 'group_id'):
1351                        new_plot.group_id.append(self.panel_on_focus.group_id)
1352            else:
1353                #if not append then new plot
1354                new_plot.group_id.append(wx.NewId())
1355            wx.PostEvent(self, NewPlotEvent(plot=new_plot,
1356                                                  title=str(new_plot.title)))
1357           
1358 
1359               
1360    def remove_data(self, data_id, theory_id=None, delete_all=True):
1361        """
1362        Delete data state if data_id is provide
1363        delete theory created with data of id data_id if theory_id is provide
1364        if delete all true: delete the all state
1365        else delete theory
1366        """
1367        self._data_manager.delete_data(data_id=data_id, 
1368                                       theory_id=theory_id, 
1369                                       delete_all=delete_all)
1370        for plug in self.plugins:
1371            plug.delete_data(data_id)
1372           
1373       
1374    def set_current_perspective(self, perspective):
1375        """
1376        set the current active perspective
1377        """
1378        self._current_perspective = perspective
1379        name = "No current Application selected"
1380        if self._current_perspective is not None:
1381            self._add_current_plugin_menu()
1382            for panel in self.panels.values():
1383                if hasattr(panel, 'CENTER_PANE') and panel.CENTER_PANE:
1384                    for name in self._current_perspective.get_perspective():
1385                        if name == panel.window_name:
1386                            panel.on_set_focus(event=None)
1387                            break
1388                           
1389            name = self._current_perspective.sub_menu
1390            if self._data_panel is not None:
1391                self._data_panel.set_active_perspective(name)
1392                self._check_applications_menu()
1393 
1394    def _check_applications_menu(self):
1395        """
1396        check the menu of the current application
1397        """
1398        if self._applications_menu is not None:
1399            for menu in self._applications_menu.GetMenuItems():
1400                if self._current_perspective is not None:
1401                    name = self._current_perspective.sub_menu
1402                    if menu.IsCheckable():
1403                        if menu.GetLabel() == name:
1404                            menu.Check(True)
1405                        else:
1406                             menu.Check(False) 
1407           
1408    def set_plotpanel_floating(self, event=None):
1409        """
1410        make the plot panel floatable
1411        """
1412        self.__gui_style &= (~GUIFRAME.FIXED_PANEL)
1413        self.__gui_style |= GUIFRAME.FLOATING_PANEL
1414        for p in self.panels.values():
1415            plot_panel = self._plotting_plugin.plot_panels.values()
1416            for p in self.panels.values():
1417                if p in plot_panel:
1418                    self._popup_floating_panel(p)
1419       
1420    def set_plotpanel_fixed(self, event=None):
1421        """
1422        make the plot panel fixed
1423        """
1424        self.__gui_style &= (~GUIFRAME.FLOATING_PANEL)
1425        self.__gui_style |= GUIFRAME.FIXED_PANEL
1426        plot_panel = []
1427        if self._plotting_plugin is not None:
1428            plot_panel = self._plotting_plugin.plot_panels.values()
1429            for p in self.panels.values():
1430                if p in plot_panel:
1431                    self._popup_fixed_panel(p)
1432                   
1433    def _popup_fixed_panel(self, p):
1434        """
1435        """
1436        style = self.__gui_style & GUIFRAME.FIXED_PANEL
1437        if style == GUIFRAME.FIXED_PANEL:
1438            self._mgr.GetPane(p.window_name).Floatable()
1439            self._mgr.GetPane(p.window_name).Right()
1440            self._mgr.GetPane(p.window_name).TopDockable(False)
1441            self._mgr.GetPane(p.window_name).BottomDockable(False)
1442            self._mgr.GetPane(p.window_name).LeftDockable(False)
1443            self._mgr.GetPane(p.window_name).RightDockable(True)
1444            flag = self._mgr.GetPane(p.window_name).IsShown()
1445            self._mgr.GetPane(p.window_name).Show(flag)
1446            self._mgr.Update()
1447           
1448    def _popup_floating_panel(self, p):
1449        """
1450        """
1451        style = self.__gui_style &  GUIFRAME.FLOATING_PANEL
1452        if style == GUIFRAME.FLOATING_PANEL: 
1453            self._mgr.GetPane(p.window_name).Floatable(True)
1454            self._mgr.GetPane(p.window_name).Float()
1455            self._mgr.GetPane(p.window_name).Dockable(False)
1456            flag = self._mgr.GetPane(p.window_name).IsShown()
1457            self._mgr.GetPane(p.window_name).Show(flag)
1458            self._mgr.Update()
1459           
1460    def enable_add_data(self, new_plot):
1461        """
1462        Enable append data on a plot panel
1463        """
1464        is_theory = len(self.panel_on_focus.plots) <= 1 and \
1465            self.panel_on_focus.plots.values()[0].__class__.__name__ == "Theory1D"
1466           
1467        is_data2d = hasattr(new_plot, 'data')
1468        is_data1d = self.panel_on_focus.__class__.__name__ == "ModelPanel1D"\
1469            and self.panel_on_focus.group_id is not None
1470        has_meta_data = hasattr(new_plot, 'meta_data')
1471       
1472        #disable_add_data if the data is being recovered from  a saved state file.
1473        is_state_data = False
1474        if has_meta_data:
1475            if 'invstate' in new_plot.meta_data: is_state_data = True
1476            if  'prstate' in new_plot.meta_data: is_state_data = True
1477            if  'fitstate' in new_plot.meta_data: is_state_data = True
1478   
1479        return is_data1d and not is_data2d and not is_theory and not is_state_data
1480   
1481    def enable_edit_menu(self):
1482        """
1483        enable menu item under edit menu depending on the panel on focus
1484        """
1485        if self.panel_on_focus is not None and self._edit_menu is not None:
1486            flag = self.panel_on_focus.get_undo_flag()
1487            self._edit_menu.Enable(GUIFRAME_ID.UNDO_ID, flag)
1488            flag = self.panel_on_focus.get_redo_flag()
1489            self._edit_menu.Enable(GUIFRAME_ID.REDO_ID, flag)
1490            #flag = self.panel_on_focus.get_bookmark_flag()
1491            #self._edit_menu.Enable(GUIFRAME_ID.BOOKMARK_ID, flag)
1492            flag = self.panel_on_focus.get_save_flag()
1493            self._edit_menu.Enable(GUIFRAME_ID.SAVE_ID, flag)
1494            flag = self.panel_on_focus.get_print_flag()
1495            self._edit_menu.Enable(GUIFRAME_ID.PRINT_ID, flag)
1496            flag = self.panel_on_focus.get_preview_flag()
1497            self._edit_menu.Enable(GUIFRAME_ID.PREVIEW_ID, flag)
1498            flag = self.panel_on_focus.get_zoom_flag()
1499            self._edit_menu.Enable(GUIFRAME_ID.ZOOM_ID, flag)
1500            flag = self.panel_on_focus.get_zoom_in_flag()
1501            self._edit_menu.Enable(GUIFRAME_ID.ZOOM_IN_ID, flag)
1502            flag = self.panel_on_focus.get_zoom_out_flag()
1503            self._edit_menu.Enable(GUIFRAME_ID.ZOOM_OUT_ID, flag)
1504            flag = self.panel_on_focus.get_drag_flag()
1505            self._edit_menu.Enable(GUIFRAME_ID.DRAG_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.BOOKMARK_ID, flag)
1513            self._edit_menu.Enable(GUIFRAME_ID.SAVE_ID, flag)
1514            self._edit_menu.Enable(GUIFRAME_ID.PRINT_ID, flag)
1515            self._edit_menu.Enable(GUIFRAME_ID.PREVIEW_ID, flag)
1516            self._edit_menu.Enable(GUIFRAME_ID.ZOOM_ID, flag)
1517            self._edit_menu.Enable(GUIFRAME_ID.ZOOM_IN_ID, flag)
1518            self._edit_menu.Enable(GUIFRAME_ID.ZOOM_OUT_ID, flag)
1519            self._edit_menu.Enable(GUIFRAME_ID.DRAG_ID, flag)
1520            self._edit_menu.Enable(GUIFRAME_ID.RESET_ID, flag)
1521           
1522    def on_undo_panel(self, event=None):
1523        """
1524        undo previous action of the last panel on focus if possible
1525        """
1526        if self.panel_on_focus is not None:
1527            self.panel_on_focus.on_undo(event)
1528           
1529    def on_redo_panel(self, event=None):
1530        """
1531        redo the last cancel action done on the last panel on focus
1532        """
1533        if self.panel_on_focus is not None:
1534            self.panel_on_focus.on_redo(event)
1535           
1536    def on_bookmark_panel(self, event=None):
1537        """
1538        bookmark panel
1539        """
1540        if self.panel_on_focus is not None:
1541            self.panel_on_focus.on_bookmark(event)
1542           
1543    def append_bookmark(self, event=None):
1544        """
1545        Bookmark available information of the panel on focus
1546        """
1547        self._toolbar.append_bookmark(event)
1548           
1549    def on_save_panel(self, event=None):
1550        """
1551        save possible information on the current panel
1552        """
1553        if self.panel_on_focus is not None:
1554            self.panel_on_focus.on_save(event)
1555           
1556    def on_preview_panel(self, event=None):
1557        """
1558        preview information on the panel on focus
1559        """
1560        if self.panel_on_focus is not None:
1561            self.panel_on_focus.on_preview(event)
1562           
1563    def on_print_panel(self, event=None):
1564        """
1565        print available information on the last panel on focus
1566        """
1567        if self.panel_on_focus is not None:
1568            self.panel_on_focus.on_print(event)
1569           
1570    def on_zoom_panel(self, event=None):
1571        """
1572        zoom on the current panel if possible
1573        """
1574        if self.panel_on_focus is not None:
1575            self.panel_on_focus.on_zoom(event)
1576           
1577    def on_zoom_in_panel(self, event=None):
1578        """
1579        zoom in of the panel on focus
1580        """
1581        if self.panel_on_focus is not None:
1582            self.panel_on_focus.on_zoom_in(event)
1583           
1584    def on_zoom_out_panel(self, event=None):
1585        """
1586        zoom out on the panel on focus
1587        """
1588        if self.panel_on_focus is not None:
1589            self.panel_on_focus.on_zoom_out(event)
1590           
1591    def on_drag_panel(self, event=None):
1592        """
1593        drag apply to the panel on focus
1594        """
1595        if self.panel_on_focus is not None:
1596            self.panel_on_focus.on_drag(event)
1597           
1598    def on_reset_panel(self, event=None):
1599        """
1600        reset the current panel
1601        """
1602        if self.panel_on_focus is not None:
1603            self.panel_on_focus.on_reset(event)
1604           
1605    def enable_undo(self):
1606        """
1607        enable undo related control
1608        """
1609        if self.panel_on_focus is not None:
1610            self._toolbar.enable_undo(self.panel_on_focus)
1611           
1612    def enable_redo(self):
1613        """
1614        enable redo
1615        """
1616        if self.panel_on_focus is not None:
1617            self._toolbar.enable_redo(self.panel_on_focus)
1618           
1619    def enable_bookmark(self):
1620        """
1621        Bookmark
1622        """
1623        if self.panel_on_focus is not None:
1624            self._toolbar.enable_bookmark(self.panel_on_focus)
1625           
1626    def enable_save(self):
1627        """
1628        save
1629        """
1630        if self.panel_on_focus is not None:
1631            self._toolbar.enable_save(self.panel_on_focus)
1632           
1633    def enable_preview(self):
1634        """
1635        preview
1636        """
1637        if self.panel_on_focus is not None:
1638            self._toolbar.enable_preview(self.panel_on_focus)
1639           
1640    def enable_print(self):
1641        """
1642        print
1643        """
1644        if self.panel_on_focus is not None:
1645            self._toolbar.enable_print(self.panel_on_focus)
1646           
1647    def enable_zoom(self):
1648        """
1649        zoom
1650        """
1651        if self.panel_on_focus is not None:
1652            self._toolbar.enable_zoom(self.panel_on_focus)
1653           
1654    def enable_zoom_in(self):
1655        """
1656        zoom in
1657        """
1658        if self.panel_on_focus is not None:
1659            self._toolbar.enable_zoom_in(self.panel_on_focus)
1660           
1661    def enable_zoom_out(self):
1662        """
1663        zoom out
1664        """
1665        if self.panel_on_focus is not None:
1666            self._toolbar.enable_zoom_out(self.panel_on_focus)
1667           
1668    def enable_drag(self, event=None):
1669        """
1670        drag
1671        """
1672        if self.panel_on_focus is not None:
1673            self._toolbar.enable_drag(self.panel_on_focus)
1674           
1675    def enable_reset(self):
1676        """
1677        reset the current panel
1678        """
1679        if self.panel_on_focus is not None:
1680            self._toolbar.enable_reset(self.panel_on_focus)
1681       
1682class DefaultPanel(wx.Panel, PanelBase):
1683    """
1684    Defines the API for a panels to work with
1685    the GUI manager
1686    """
1687    ## Internal nickname for the window, used by the AUI manager
1688    window_name = "default"
1689    ## Name to appear on the window title bar
1690    window_caption = "Welcome panel"
1691    ## Flag to tell the AUI manager to put this panel in the center pane
1692    CENTER_PANE = True
1693    def __init__(self, parent, *args, **kwds):
1694        wx.Panel.__init__(self, parent, *args, **kwds)
1695        PanelBase.__init__(self, parent)
1696   
1697
1698
1699# Toy application to test this Frame
1700class ViewApp(wx.App):
1701    """
1702    """
1703    SIZE = (GUIFRAME_WIDTH,GUIFRAME_HEIGHT)
1704    TITLE = config.__appname__
1705    PROG_SPLASH_PATH = PROG_SPLASH_SCREEN
1706    STYLE = GUIFRAME.SINGLE_APPLICATION
1707    def OnInit(self):
1708        """
1709        """
1710        pos, size = self.window_placement(self.SIZE)
1711        self.frame = ViewerFrame(parent=None, 
1712                                 title=self.TITLE, 
1713                                 pos=pos, 
1714                                 gui_style = self.STYLE,
1715                                 size=size) 
1716         # Display a splash screen on top of the frame.
1717        if len(sys.argv) > 1 and '--time' in sys.argv[1:]:
1718            log_time("Starting to display the splash screen")
1719        if self.PROG_SPLASH_PATH is not None and \
1720            os.path.isfile(self.PROG_SPLASH_PATH):
1721            try:
1722                self.display_splash_screen(parent=self.frame, path=self.PROG_SPLASH_PATH)   
1723            except:
1724                msg = "Cannot display splash screen\n"
1725                msg += str (sys.exc_value)
1726                logging.error(msg)
1727        self.frame.Show(True)
1728
1729        if hasattr(self.frame, 'special'):
1730            self.frame.special.SetCurrent()
1731        self.SetTopWindow(self.frame)
1732        return True
1733   
1734    def set_manager(self, manager):
1735        """
1736        Sets a reference to the application manager
1737        of the GUI manager (Frame)
1738        """
1739        self.frame.set_manager(manager)
1740       
1741    def build_gui(self):
1742        """
1743        Build the GUI
1744        """
1745        self.frame.build_gui()
1746        self.frame.post_init()
1747       
1748    def set_welcome_panel(self, panel_class):
1749        """
1750        Set the welcome panel
1751       
1752        :param panel_class: class of the welcome panel to be instantiated
1753       
1754        """
1755        self.frame.set_welcome_panel(panel_class)
1756       
1757    def add_perspective(self, perspective):
1758        """
1759        Manually add a perspective to the application GUI
1760        """
1761        self.frame.add_perspective(perspective)
1762   
1763    def window_placement(self, size):
1764        """
1765        Determines the position and size of the application frame such that it
1766        fits on the user's screen without obstructing (or being obstructed by)
1767        the Windows task bar.  The maximum initial size in pixels is bounded by
1768        WIDTH x HEIGHT.  For most monitors, the application
1769        will be centered on the screen; for very large monitors it will be
1770        placed on the left side of the screen.
1771        """
1772        window_width, window_height = size
1773        screen_size = wx.GetDisplaySize()
1774        window_height = window_height if screen_size[1]>window_height else screen_size[1]-50
1775        window_width  = window_width if screen_size[0]> window_width else screen_size[0]-50
1776        xpos = ypos = 0
1777
1778        # Note that when running Linux and using an Xming (X11) server on a PC
1779        # with a dual  monitor configuration, the reported display size may be
1780        # that of both monitors combined with an incorrect display count of 1.
1781        # To avoid displaying this app across both monitors, we check for
1782        # screen 'too big'.  If so, we assume a smaller width which means the
1783        # application will be placed towards the left hand side of the screen.
1784
1785        _, _, x, y = wx.Display().GetClientArea() # size excludes task bar
1786        if len(sys.argv) > 1 and '--platform' in sys.argv[1:]:
1787            w, h = wx.DisplaySize()  # size includes task bar area
1788        if x > 1920: x = 1280  # display on left side, not centered on screen
1789        if x > window_width:  xpos = (x - window_width)/2
1790        if y > window_height: ypos = (y - window_height)/2
1791
1792        # Return the suggested position and size for the application frame.
1793        return (xpos, ypos), (min(x, window_width), min(y, window_height))
1794   
1795    def display_splash_screen(self, parent, path=PROG_SPLASH_SCREEN):
1796        """Displays the splash screen.  It will exactly cover the main frame."""
1797
1798        # Prepare the picture.  On a 2GHz intel cpu, this takes about a second.
1799        x, y = parent.GetSizeTuple()
1800        image = wx.Image(path, wx.BITMAP_TYPE_PNG)
1801        image.Rescale(x, y, wx.IMAGE_QUALITY_HIGH)
1802        bm = image.ConvertToBitmap()
1803
1804        # Create and show the splash screen.  It will disappear only when the
1805        # program has entered the event loop AND either the timeout has expired
1806        # or the user has left clicked on the screen.  Thus any processing
1807        # performed in this routine (including sleeping) or processing in the
1808        # calling routine (including doing imports) will prevent the splash
1809        # screen from disappearing.
1810        #
1811        # Note that on Linux, the timeout appears to occur immediately in which
1812        # case the splash screen disappears upon entering the event loop.
1813        wx.SplashScreen(bitmap=bm,
1814                        splashStyle=(wx.SPLASH_CENTRE_ON_PARENT|
1815                                     wx.SPLASH_TIMEOUT|
1816                                     wx.STAY_ON_TOP),
1817                        milliseconds=4000,
1818                        parent=parent,
1819                        id=wx.ID_ANY)
1820
1821        # Keep the splash screen up a minimum amount of time for non-Windows
1822        # systems.  This is a workaround for Linux and possibly MacOS that
1823        # appear to ignore the splash screen timeout option.
1824        if '__WXMSW__' not in wx.PlatformInfo:
1825            if len(sys.argv) > 1 and '--time' in sys.argv[1:]:
1826                log_time("Starting sleep of 2 secs")
1827            time.sleep(2)
1828
1829        # A call to wx.Yield does not appear to be required.  If used on
1830        # Windows, the cursor changes from 'busy' to 'ready' before the event
1831        # loop is reached which is not desirable.  On Linux it seems to have
1832        # no effect.
1833        #wx.Yield()
1834
1835       
1836
1837if __name__ == "__main__": 
1838    app = ViewApp(0)
1839    app.MainLoop()
1840
1841             
Note: See TracBrowser for help on using the repository browser.