source: sasview/guiframe/gui_manager.py @ 93fe7e2

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 93fe7e2 was 1b3a5a9, checked in by Gervaise Alina <gervyh@…>, 14 years ago

working on toolbar

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