source: sasview/guiframe/gui_manager.py @ 6bbeacd4

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 6bbeacd4 was 4c0572f, checked in by Gervaise Alina <gervyh@…>, 14 years ago

modify menu plugin name

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