source: sasview/guiframe/gui_manager.py @ b1a65b6

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

remove other type of data into sansview

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