source: sasview/guiframe/gui_manager.py @ 3f0351c6

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

working on toolbar

  • Property mode set to 100644
File size: 66.7 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        #tool bar
114        self._toolbar = None
115        ## Find plug-ins
116        # Modify this so that we can specify the directory to look into
117        self.plugins = []
118        #add local plugin
119        self.plugins += self._get_local_plugins()
120        self.plugins += self._find_plugins()
121        ## List of panels
122        self.panels = {}
123
124        # Default locations
125        self._default_save_location = os.getcwd()       
126       
127        # Welcome panel
128        self.defaultPanel = None
129        #panel on focus
130        self.panel_on_focus = None
131         #data manager
132        from data_manager import DataManager
133        self._data_manager = DataManager()
134        self._data_panel = DataPanel(parent=self)
135        if self.panel_on_focus is not None:
136            self._data_panel.set_panel_on_focus(self.panel_on_focus.window_caption)
137        # Check for update
138        #self._check_update(None)
139        # Register the close event so it calls our own method
140        wx.EVT_CLOSE(self, self.Close)
141        # Register to status events
142        self.Bind(EVT_STATUS, self._on_status_event)
143        #Register add extra data on the same panel event on load
144        self.Bind(EVT_PANEL_ON_FOCUS, self.set_panel_on_focus)
145       
146    def set_panel_on_focus(self, event):
147        """
148        Store reference to the last panel on focus
149        update the toolbar if available
150        update edit menu if available
151        """
152        self.panel_on_focus = event.panel
153        panel_name = 'No panel on focus'
154        application_name = 'No Selected Application'
155        if self.panel_on_focus is not None and self._data_panel is not None:
156            panel_name = self.panel_on_focus.window_caption
157            self._data_panel.set_panel_on_focus(panel_name)
158        #update toolbar
159        self._update_toolbar_helper()
160        #update edit menu
161        self.enable_edit_menu()
162        print "set_panel_on_focus", event.panel.window_caption
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._file_menu.Append(id, '&Save Application',
728                                 'Save state of the current active application')
729            wx.EVT_MENU(self, id, self._on_save_application)
730            id = wx.NewId()
731            self._file_menu.Append(id, '&Save Project',
732                                 'Save the state of the whole application')
733            wx.EVT_MENU(self, id, self._on_save_project)
734            self._file_menu.AppendSeparator()
735       
736        id = wx.NewId()
737        self._file_menu.Append(id, '&Quit', 'Exit') 
738        wx.EVT_MENU(self, id, self.Close)
739        # Add sub menus
740        self._menubar.Append(self._file_menu, '&File')
741       
742    def _add_menu_edit(self):
743        """
744        add menu edit
745        """
746        # Edit Menu
747        self._edit_menu = wx.Menu()
748        self._edit_menu.Append(GUIFRAME_ID.UNDO_ID, '&Undo', 
749                               'Undo the previous action')
750        wx.EVT_MENU(self, GUIFRAME_ID.UNDO_ID, self.on_undo_panel)
751        self._edit_menu.Append(GUIFRAME_ID.REDO_ID, '&Redo', 
752                               'Redo the previous action')
753        wx.EVT_MENU(self, GUIFRAME_ID.REDO_ID, self.on_redo_panel)
754        self._edit_menu.AppendSeparator()
755        self._edit_menu.Append(GUIFRAME_ID.BOOKMARK_ID, '&Bookmark', 
756                               'bookmark current panel')
757        wx.EVT_MENU(self, GUIFRAME_ID.BOOKMARK_ID, self.on_bookmark_panel)
758        self._edit_menu.Append(GUIFRAME_ID.SAVE_ID, '&Save As', 
759                               'Save current panel into file')
760        wx.EVT_MENU(self, GUIFRAME_ID.SAVE_ID, self.on_save_panel)
761        self._edit_menu.AppendSeparator()
762        self._edit_menu.Append(GUIFRAME_ID.PREVIEW_ID, '&Print Preview',
763                               'Preview current panel')
764        wx.EVT_MENU(self, GUIFRAME_ID.PREVIEW_ID, self.on_preview_panel)
765        self._edit_menu.Append(GUIFRAME_ID.PRINT_ID, '&Print',
766                               'Print current panel')
767        wx.EVT_MENU(self, GUIFRAME_ID.PRINT_ID, self.on_print_panel)
768        self._edit_menu.AppendSeparator()
769        self._edit_menu.Append(GUIFRAME_ID.ZOOM_ID, '&Zoom',
770                               'Zoom current panel')
771        wx.EVT_MENU(self, GUIFRAME_ID.ZOOM_ID, self.on_zoom_panel)
772        self._edit_menu.Append(GUIFRAME_ID.ZOOM_IN_ID, '&Zoom In',
773                               'Zoom in current panel')
774        wx.EVT_MENU(self, GUIFRAME_ID.ZOOM_IN_ID, self.on_zoom_in_panel)
775        self._edit_menu.Append(GUIFRAME_ID.ZOOM_OUT_ID, '&Zoom Out', 
776                               'Zoom out current panel')
777        wx.EVT_MENU(self, GUIFRAME_ID.ZOOM_OUT_ID, self.on_zoom_out_panel)
778        self._edit_menu.Append(GUIFRAME_ID.DRAG_ID, '&Drag',
779                               'Drag current panel')
780        wx.EVT_MENU(self, GUIFRAME_ID.DRAG_ID, self.on_drag_panel)
781        self._edit_menu.Append(GUIFRAME_ID.RESET_ID, '&Reset', 
782                               'Reset current panel')
783        wx.EVT_MENU(self, GUIFRAME_ID.RESET_ID, self.on_reset_panel)
784        self._menubar.Append(self._edit_menu,  '&Edit')
785        self.enable_edit_menu()
786       
787    def _add_menu_data(self):
788        """
789        Add menu item item data to menu bar
790        """
791        # Add menu data
792        self._data_menu = wx.Menu()
793        #menu for data files
794        data_file_id = wx.NewId()
795        data_file_hint = "load one or more data in the application"
796        self._data_menu.Append(data_file_id, 
797                         '&Load Data File(s)', data_file_hint)
798        wx.EVT_MENU(self, data_file_id, self._load_data)
799        style = self.__gui_style & GUIFRAME.MULTIPLE_APPLICATIONS
800        style1 = self.__gui_style & GUIFRAME.DATALOADER_ON
801        if style == GUIFRAME.MULTIPLE_APPLICATIONS:
802            #menu for data from folder
803            data_folder_id = wx.NewId()
804            data_folder_hint = "load multiple data in the application"
805            self._data_menu.Append(data_folder_id, 
806                             '&Load Data Folder', data_folder_hint)
807            wx.EVT_MENU(self, data_folder_id, self._load_folder)
808            self._menubar.Append(self._data_menu, '&Data')
809        elif style1 == GUIFRAME.DATALOADER_ON:
810            self._menubar.Append(self._data_menu, '&Data')
811       
812    def _load_data(self, event):
813        """
814        connect menu item load data with the first plugin that can load data
815        """
816        for plug in self.plugins:
817            if plug.can_load_data():
818                plug.load_data(event)
819        style = self.__gui_style & GUIFRAME.MANAGER_ON
820        if style == GUIFRAME.MANAGER_ON:
821            self.show_data_panel(event=None)
822       
823    def _load_folder(self, event):
824        """
825        connect menu item load data with the first plugin that can load data and
826        folder
827        """
828        for plug in self.plugins:
829            if plug.can_load_data():
830                plug.load_folder(event)
831        style = self.__gui_style & GUIFRAME.MANAGER_ON
832        if style == GUIFRAME.MANAGER_ON:
833            self.show_data_panel(event=None)
834               
835    def _on_hide_toolbar(self, event=None):
836        """
837        hide or show toolbar
838        """
839        if self._toolbar is None:
840            return
841        if self._toolbar.IsShown():
842            if self._toolbar_menu is not None:
843                self._toolbar_menu.SetItemLabel('Show Toolbar')
844            self._toolbar.Hide()
845        else:
846            if self._toolbar_menu is not None:
847                self._toolbar_menu.SetItemLabel('Hide Toolbar')
848            self._toolbar.Show()
849        self._toolbar.Realize()
850       
851    def _on_status_event(self, evt):
852        """
853        Display status message
854        """
855        self.sb.set_status(event=evt)
856       
857    def _on_view(self, evt):
858        """
859        A panel was selected to be shown. If it's not already
860        shown, display it.
861       
862        :param evt: menu event
863       
864        """
865        self.show_panel(evt.GetId())
866       
867    def on_close_welcome_panel(self):
868        """
869        Close the welcome panel
870        """
871        if self.defaultPanel is None:
872            return 
873        self._mgr.GetPane(self.panels["default"].window_name).Hide()
874        self._mgr.Update()
875        # set a default perspective
876        self.set_default_perspective()
877       
878    def show_welcome_panel(self, event):
879        """   
880        Display the welcome panel
881        """
882        if self.defaultPanel is None:
883            return 
884        for id in self.panels.keys():
885            if id  ==  'default':
886                # Show default panel
887                if not self._mgr.GetPane(self.panels["default"].window_name).IsShown():
888                    self._mgr.GetPane(self.panels["default"].window_name).Show(True)
889            elif id == "data_panel":
890                flag = self._mgr.GetPane(self.panels["data_panel"].window_name).IsShown()
891                self._mgr.GetPane(self.panels["data_panel"].window_name).Show(flag)
892            else:
893                self._mgr.GetPane(self.panels[id].window_name).IsShown()
894                self._mgr.GetPane(self.panels[id].window_name).Hide()
895        self._mgr.Update()
896       
897    def show_panel(self, uid):
898        """
899        Shows the panel with the given id
900       
901        :param uid: unique ID number of the panel to show
902       
903        """
904        ID = str(uid)
905        config.printEVT("show_panel: %s" % ID)
906        if ID in self.panels.keys():
907            if not self._mgr.GetPane(self.panels[ID].window_name).IsShown():
908                self._mgr.GetPane(self.panels[ID].window_name).Show()
909                # Hide default panel
910                self._mgr.GetPane(self.panels["default"].window_name).Hide()
911            self._mgr.Update()
912   
913    def _on_open(self, event):
914        """
915        """
916        path = self.choose_file()
917        if path is None:
918            return
919
920        if path and os.path.isfile(path):
921            basename  = os.path.basename(path)
922            if  basename.endswith('.svs'):
923                #remove panels for new states
924                for item in self.panels:
925                    try:
926                        self.panels[item].clear_panel()
927                    except:
928                        pass
929                #reset states and plot data
930                for item in STATE_FILE_EXT:
931                    exec "plot_data(self, path,'%s')" % str(item)
932            else:
933                plot_data(self, path)
934        if self.defaultPanel is not None and \
935            self._mgr.GetPane(self.panels["default"].window_name).IsShown():
936            self.on_close_welcome_panel()
937           
938    def _on_save_application(self, event):
939        """
940        save the state of the current active application
941        """
942        ## Default file location for save
943        self._default_save_location = os.getcwd()
944        if self._current_perspective is  None:
945            return
946        reader, ext = self._current_perspective.get_extensions()
947        path = None
948        dlg = wx.FileDialog(self, "Choose a file",
949                            self._default_save_location, "", ext, wx.SAVE)
950        if dlg.ShowModal() == wx.ID_OK:
951            path = dlg.GetPath()
952            self._default_save_location = os.path.dirname(path)
953        else:
954            return None
955        dlg.Destroy()
956        if path is None:
957            return
958        # default cansas xml doc
959        doc = None
960        for panel in self._current_perspective.get_perspective():
961            doc = on_save_helper(doc, reader, panel, path)
962           
963    def _on_save_project(self, event):
964        """
965        save the state of the current active application
966        """
967        ## Default file location for save
968        self._default_save_location = os.getcwd()
969        if self._current_perspective is  None:
970            return
971        reader, ext = self._current_perspective.get_extensions()
972        path = None
973        dlg = wx.FileDialog(self, "Choose a file",
974                            self._default_save_location, "", '.svs', wx.SAVE)
975        if dlg.ShowModal() == wx.ID_OK:
976            path = dlg.GetPath()
977            self._default_save_location = os.path.dirname(path)
978        else:
979            return None
980        dlg.Destroy()
981        if path is None:
982            return
983        # default cansas xml doc
984        doc = None
985        for panel in self.panels.values():
986            doc = self.on_save_helper(doc, reader, panel, path)
987       
988           
989    def on_save_helper(self, doc, reader, panel, path):
990        """
991        Save state into a file
992        """
993        try:
994            data = panel.get_data()
995            state = panel.get_state()
996            if reader is not None:
997                if data is not None:
998                    new_doc = reader.write_toXML(data, state)
999                    if hasattr(doc, "firstChild"):
1000                        child = new_doc.firstChild.firstChild
1001                        doc.firstChild.appendChild(child) 
1002                    else:
1003                        doc = new_doc
1004        except: 
1005            raise
1006            #pass
1007        # Write the XML document
1008        if doc != None:
1009            fd = open(path, 'w')
1010            fd.write(doc.toprettyxml())
1011            fd.close()
1012        else:
1013            raise
1014            #print "Nothing to save..."
1015            #raise RuntimeError, "%s is not a SansView (.svs) file..." % path
1016        return doc
1017
1018    def quit_guiframe(self):
1019        """
1020        Pop up message to make sure the user wants to quit the application
1021        """
1022        message = "Do you really want to quit \n"
1023        message += "this application?"
1024        dial = wx.MessageDialog(self, message, 'Question',
1025                           wx.YES_NO|wx.YES_DEFAULT|wx.ICON_QUESTION)
1026        if dial.ShowModal() == wx.ID_YES:
1027            return True
1028        else:
1029            return False   
1030       
1031    def Close(self, event=None):
1032        """
1033        Quit the application
1034        """
1035        #flag = self.quit_guiframe()
1036        if True:
1037            wx.Exit()
1038            sys.exit()
1039
1040    def _check_update(self, event=None): 
1041        """
1042        Check with the deployment server whether a new version
1043        of the application is available.
1044        A thread is started for the connecting with the server. The thread calls
1045        a call-back method when the current version number has been obtained.
1046        """
1047        if hasattr(config, "__update_URL__"):
1048            import version
1049            checker = version.VersionThread(config.__update_URL__,
1050                                            self._process_version,
1051                                            baggage=event==None)
1052            checker.start() 
1053   
1054    def _process_version(self, version, standalone=True):
1055        """
1056        Call-back method for the process of checking for updates.
1057        This methods is called by a VersionThread object once the current
1058        version number has been obtained. If the check is being done in the
1059        background, the user will not be notified unless there's an update.
1060       
1061        :param version: version string
1062        :param standalone: True of the update is being checked in
1063           the background, False otherwise.
1064           
1065        """
1066        try:
1067            if cmp(version, config.__version__) > 0:
1068                msg = "Version %s is available! See the Help "
1069                msg += "menu to download it." % version
1070                self.SetStatusText(msg)
1071                if not standalone:
1072                    import webbrowser
1073                    webbrowser.open(config.__download_page__)
1074            else:
1075                if not standalone:
1076                    msg = "You have the latest version"
1077                    msg += " of %s" % config.__appname__
1078                    self.SetStatusText(msg)
1079        except:
1080            msg = "guiframe: could not get latest application"
1081            msg += " version number\n  %s" % sys.exc_value
1082            logging.error(msg)
1083            if not standalone:
1084                msg = "Could not connect to the application server."
1085                msg += " Please try again later."
1086                self.SetStatusText(msg)
1087                   
1088    def _onAbout(self, evt):
1089        """
1090        Pop up the about dialog
1091       
1092        :param evt: menu event
1093       
1094        """
1095        if config._do_aboutbox:
1096            import aboutbox 
1097            dialog = aboutbox.DialogAbout(None, -1, "")
1098            dialog.ShowModal()           
1099           
1100    def set_manager(self, manager):
1101        """
1102        Sets the application manager for this frame
1103       
1104        :param manager: frame manager
1105        """
1106        self.app_manager = manager
1107       
1108    def post_init(self):
1109        """
1110        This initialization method is called after the GUI
1111        has been created and all plug-ins loaded. It calls
1112        the post_init() method of each plug-in (if it exists)
1113        so that final initialization can be done.
1114        """
1115        for item in self.plugins:
1116            if hasattr(item, "post_init"):
1117                item.post_init()
1118       
1119    def set_default_perspective(self):
1120        """
1121        Choose among the plugin the first plug-in that has
1122        "set_default_perspective" method and its return value is True will be
1123        as a default perspective when the welcome page is closed
1124        """
1125        for item in self.plugins:
1126            if hasattr(item, "set_default_perspective"):
1127                if item.set_default_perspective():
1128                    item.on_perspective(event=None)
1129                    return 
1130       
1131    def set_perspective(self, panels):
1132        """
1133        Sets the perspective of the GUI.
1134        Opens all the panels in the list, and closes
1135        all the others.
1136       
1137        :param panels: list of panels
1138        """
1139        for item in self.panels:
1140            # Check whether this is a sticky panel
1141            if hasattr(self.panels[item], "ALWAYS_ON"):
1142                if self.panels[item].ALWAYS_ON:
1143                    continue 
1144            if self.panels[item].window_name in panels:
1145                if not self._mgr.GetPane(self.panels[item].window_name).IsShown():
1146                    self._mgr.GetPane(self.panels[item].window_name).Show()
1147            else:
1148                # always show the data panel if enable
1149                style = self.__gui_style & GUIFRAME.MANAGER_ON
1150                if (style == GUIFRAME.MANAGER_ON) and self.panels[item] == self._data_panel:
1151                    if 'data_panel' in self.panels.keys():
1152                        flag = self._mgr.GetPane(self.panels['data_panel'].window_name).IsShown()
1153                        self._mgr.GetPane(self.panels['data_panel'].window_name).Show(flag)
1154                else:
1155                    if self._mgr.GetPane(self.panels[item].window_name).IsShown():
1156                        self._mgr.GetPane(self.panels[item].window_name).Hide()
1157        self._mgr.Update()
1158       
1159    def show_data_panel(self, event=None):
1160        """
1161        show the data panel
1162        """
1163        pane = self._mgr.GetPane(self.panels["data_panel"].window_name)
1164        #if not pane.IsShown():
1165        pane.Show(True)
1166        self._mgr.Update()
1167 
1168    def add_data(self, data_list, flag=False):
1169        """
1170        receive a list of data . store them its data manager if possible
1171        determine if data was be plot of send to data perspectives
1172        """
1173        #send a list of available data to plotting plugin
1174        avalaible_data = []
1175        if self._data_manager is not None:
1176            self._data_manager.add_data(data_list)
1177            avalaible_data = self._data_manager.get_all_data()
1178           
1179        if True:
1180            #reading a state file
1181            for plug in self.plugins:
1182                plug.on_set_state_helper(event=None)
1183        style = self.__gui_style & GUIFRAME.MANAGER_ON
1184        if style == GUIFRAME.MANAGER_ON:
1185            if self._data_panel is not None:
1186                data_state = self._data_manager.get_selected_data()
1187                self._data_panel.load_data_list(data_state)
1188                self._mgr.GetPane(self._data_panel.window_name).Show(True)
1189                #wait for button press from the data panel to send data
1190        else:
1191            #automatically send that to the current perspective
1192            style = self.__gui_style & GUIFRAME.SINGLE_APPLICATION
1193            if style == GUIFRAME.SINGLE_APPLICATION:
1194                self.set_data(data_list)
1195               
1196    def get_data_from_panel(self, data_id, plot=False,append=False):
1197        """
1198        receive a list of data key retreive the data from data manager and set
1199        then to the current perspective
1200        """
1201        data_dict = self._data_manager.get_by_id(data_id)
1202        data_list = []
1203        for data_state in data_dict.values():
1204            data_list.append(data_state.data)
1205        if plot:
1206            self.plot_data(data_list, append=append)
1207        else:
1208            #sent data to active application
1209            self.set_data(data_list=data_list)
1210       
1211       
1212    def set_data(self, data_list):
1213        """
1214        set data to current perspective
1215        """
1216        if self._current_perspective is not None:
1217            try:
1218                self._current_perspective.set_data(data_list)
1219            except:
1220                msg = str(sys.exc_value)
1221                wx.PostEvent(self, StatusEvent(status=msg, info="error"))
1222        else:
1223            msg = "Guiframe does not have a current perspective"
1224            logging.info(msg)
1225           
1226    def plot_data(self, data_list, append=False):
1227        """
1228        send a list of data to plot
1229        """
1230        if not data_list:
1231            message = "Please check data to plot or append"
1232            wx.PostEvent(self, StatusEvent(status=message, info='warning'))
1233            return 
1234        for new_plot in data_list:
1235            if append:
1236                if self.panel_on_focus is None or \
1237                    not self.enable_add_data(new_plot):
1238                    message = "cannot append plot. No plot panel on focus!"
1239                    message += "please click on any available plot to set focus"
1240                    wx.PostEvent(self, StatusEvent(status=message, 
1241                                                   info='warning'))
1242                    return 
1243                else:
1244                    if self.enable_add_data(new_plot) and \
1245                    hasattr(self.panel_on_focus, 'group_id'):
1246                        new_plot.group_id = self.panel_on_focus.group_id
1247            wx.PostEvent(self, NewPlotEvent(plot=new_plot,
1248                                                  title=str(new_plot.title)))
1249           
1250    def add_theory(self, data_id, theory):
1251        """
1252        """
1253        self._data_manager.append_theory(data_id, theory)
1254        style = self.__gui_style & GUIFRAME.MANAGER_ON
1255        if style == GUIFRAME.MANAGER_ON:
1256            if self._data_panel is not None:
1257                data_state = self._data_manager.get_by_id([data_id])
1258                self._data_panel.load_data_list(data_state)
1259               
1260    def delete_data(self, data_id, theory_id=None, delete_all=True):
1261        """
1262        Delete data state if data_id is provide
1263        delete theory created with data of id data_id if theory_id is provide
1264        if delete all true: delete the all state
1265        else delete theory
1266        """
1267        self._data_manager.delete_data(data_id=data_id, 
1268                                       theory_id=theory_id, 
1269                                       delete_all=delete_all)
1270        for plug in self.plugins:
1271            plug.delete_data(data_id)
1272           
1273       
1274    def set_current_perspective(self, perspective):
1275        """
1276        set the current active perspective
1277        """
1278       
1279        self._current_perspective = perspective
1280        name = "No current Application selected"
1281        if self._current_perspective is not None:
1282            self._add_current_plugin_menu()
1283            for panel in self.panels.values():
1284                if hasattr(panel, 'CENTER_PANE') and panel.CENTER_PANE:
1285                    for name in self._current_perspective.get_perspective():
1286                        print "current",name.lower(),panel.window_name.lower(), name == panel.window_name
1287                        if name == panel.window_name:
1288                            panel.on_set_focus(event=None)
1289                            print "panel", name,  panel.window_name,  panel.window_caption
1290                            break
1291                           
1292            name = self._current_perspective.sub_menu
1293            if self._data_panel is not None:
1294                self._data_panel.set_active_perspective(name)
1295                self._check_applications_menu()
1296            ##update tool bar
1297            #if self._toolbar is not None:
1298            #    self._update_toolbar_helper()
1299               
1300    def _check_applications_menu(self):
1301        """
1302        check the menu of the current application
1303        """
1304        if self._applications_menu is not None:
1305            for menu in self._applications_menu.GetMenuItems():
1306                if self._current_perspective is not None:
1307                    name = self._current_perspective.sub_menu
1308                    if menu.IsCheckable():
1309                        if menu.GetLabel() == name:
1310                            menu.Check(True)
1311                        else:
1312                             menu.Check(False) 
1313           
1314    def set_plotpanel_floating(self, event=None):
1315        """
1316        make the plot panel floatable
1317        """
1318        self.__gui_style &= (~GUIFRAME.FIXED_PANEL)
1319        self.__gui_style |= GUIFRAME.FLOATING_PANEL
1320        for p in self.panels.values():
1321            plot_panel = self._plotting_plugin.plot_panels
1322            for p in self.panels.values():
1323                if p in plot_panel:
1324                    self._popup_floating_panel(p)
1325       
1326    def set_plotpanel_fixed(self, event=None):
1327        """
1328        make the plot panel fixed
1329        """
1330        self.__gui_style &= (~GUIFRAME.FLOATING_PANEL)
1331        self.__gui_style |= GUIFRAME.FIXED_PANEL
1332        plot_panel = []
1333        if self._plotting_plugin is not None:
1334            plot_panel = self._plotting_plugin.plot_panels
1335            for p in self.panels.values():
1336                if p in plot_panel:
1337                    self._popup_fixed_panel(p)
1338                   
1339    def _popup_fixed_panel(self, p):
1340        """
1341        """
1342        style = self.__gui_style & GUIFRAME.FIXED_PANEL
1343        if style == GUIFRAME.FIXED_PANEL:
1344            self._mgr.GetPane(p.window_name).Floatable()
1345            self._mgr.GetPane(p.window_name).Right()
1346            self._mgr.GetPane(p.window_name).TopDockable(False)
1347            self._mgr.GetPane(p.window_name).BottomDockable(False)
1348            self._mgr.GetPane(p.window_name).LeftDockable(False)
1349            self._mgr.GetPane(p.window_name).RightDockable(True)
1350            flag = self._mgr.GetPane(p.window_name).IsShown()
1351            self._mgr.GetPane(p.window_name).Show(flag)
1352            self._mgr.Update()
1353           
1354    def _popup_floating_panel(self, p):
1355        """
1356        """
1357        style = self.__gui_style &  GUIFRAME.FLOATING_PANEL
1358        if style == GUIFRAME.FLOATING_PANEL: 
1359            self._mgr.GetPane(p.window_name).Floatable(True)
1360            self._mgr.GetPane(p.window_name).Float()
1361            self._mgr.GetPane(p.window_name).Dockable(False)
1362            flag = self._mgr.GetPane(p.window_name).IsShown()
1363            self._mgr.GetPane(p.window_name).Show(flag)
1364            self._mgr.Update()
1365           
1366    def enable_add_data(self, new_plot):
1367        """
1368        Enable append data on a plot panel
1369        """
1370        is_theory = len(self.panel_on_focus.plots) <= 1 and \
1371            self.panel_on_focus.plots.values()[0].__class__.__name__ == "Theory1D"
1372           
1373        is_data2d = hasattr(new_plot, 'data')
1374        is_data1d = self.panel_on_focus.__class__.__name__ == "ModelPanel1D"\
1375            and self.panel_on_focus.group_id is not None
1376        has_meta_data = hasattr(new_plot, 'meta_data')
1377       
1378        #disable_add_data if the data is being recovered from  a saved state file.
1379        is_state_data = False
1380        if has_meta_data:
1381            if 'invstate' in new_plot.meta_data: is_state_data = True
1382            if  'prstate' in new_plot.meta_data: is_state_data = True
1383            if  'fitstate' in new_plot.meta_data: is_state_data = True
1384   
1385        return is_data1d and not is_data2d and not is_theory and not is_state_data
1386   
1387    def enable_edit_menu(self):
1388        """
1389        enable menu item under edit menu depending on the panel on focus
1390        """
1391        if self.panel_on_focus is not None and self._edit_menu is not None:
1392            flag = self.panel_on_focus.get_undo_flag()
1393            self._edit_menu.Enable(GUIFRAME_ID.UNDO_ID, flag)
1394            flag = self.panel_on_focus.get_redo_flag()
1395            self._edit_menu.Enable(GUIFRAME_ID.REDO_ID, flag)
1396            flag = self.panel_on_focus.get_bookmark_flag()
1397            self._edit_menu.Enable(GUIFRAME_ID.BOOKMARK_ID, flag)
1398            flag = self.panel_on_focus.get_save_flag()
1399            self._edit_menu.Enable(GUIFRAME_ID.SAVE_ID, flag)
1400            flag = self.panel_on_focus.get_print_flag()
1401            self._edit_menu.Enable(GUIFRAME_ID.PRINT_ID, flag)
1402            flag = self.panel_on_focus.get_preview_flag()
1403            self._edit_menu.Enable(GUIFRAME_ID.PREVIEW_ID, flag)
1404            flag = self.panel_on_focus.get_zoom_flag()
1405            self._edit_menu.Enable(GUIFRAME_ID.ZOOM_ID, flag)
1406            flag = self.panel_on_focus.get_zoom_in_flag()
1407            self._edit_menu.Enable(GUIFRAME_ID.ZOOM_IN_ID, flag)
1408            flag = self.panel_on_focus.get_zoom_out_flag()
1409            self._edit_menu.Enable(GUIFRAME_ID.ZOOM_OUT_ID, flag)
1410            flag = self.panel_on_focus.get_drag_flag()
1411            self._edit_menu.Enable(GUIFRAME_ID.DRAG_ID, flag)
1412            flag = self.panel_on_focus.get_reset_flag()
1413            self._edit_menu.Enable(GUIFRAME_ID.RESET_ID, flag)
1414        else:
1415            flag = False
1416            self._edit_menu.Enable(GUIFRAME_ID.UNDO_ID, flag)
1417            self._edit_menu.Enable(GUIFRAME_ID.REDO_ID, flag)
1418            self._edit_menu.Enable(GUIFRAME_ID.BOOKMARK_ID, flag)
1419            self._edit_menu.Enable(GUIFRAME_ID.SAVE_ID, flag)
1420            self._edit_menu.Enable(GUIFRAME_ID.PRINT_ID, flag)
1421            self._edit_menu.Enable(GUIFRAME_ID.PREVIEW_ID, flag)
1422            self._edit_menu.Enable(GUIFRAME_ID.ZOOM_ID, flag)
1423            self._edit_menu.Enable(GUIFRAME_ID.ZOOM_IN_ID, flag)
1424            self._edit_menu.Enable(GUIFRAME_ID.ZOOM_OUT_ID, flag)
1425            self._edit_menu.Enable(GUIFRAME_ID.DRAG_ID, flag)
1426            self._edit_menu.Enable(GUIFRAME_ID.RESET_ID, flag)
1427           
1428    def on_undo_panel(self, event=None):
1429        """
1430        undo previous action of the last panel on focus if possible
1431        """
1432        if self.panel_on_focus is not None:
1433            self.panel_on_focus.on_undo(event)
1434           
1435    def on_redo_panel(self, event=None):
1436        """
1437        redo the last cancel action done on the last panel on focus
1438        """
1439        if self.panel_on_focus is not None:
1440            self.panel_on_focus.on_redo(event)
1441           
1442    def on_bookmark_panel(self, event=None):
1443        """
1444        Bookmark available information of the panel on focus
1445        """
1446        if self.panel_on_focus is not None:
1447            self.panel_on_focus.on_bookmark(event)
1448           
1449    def on_save_panel(self, event=None):
1450        """
1451        save possible information on the current panel
1452        """
1453        if self.panel_on_focus is not None:
1454            self.panel_on_focus.on_save(event)
1455           
1456    def on_preview_panel(self, event=None):
1457        """
1458        preview information on the panel on focus
1459        """
1460        if self.panel_on_focus is not None:
1461            self.panel_on_focus.on_preview(event)
1462           
1463    def on_print_panel(self, event=None):
1464        """
1465        print available information on the last panel on focus
1466        """
1467        if self.panel_on_focus is not None:
1468            self.panel_on_focus.on_print(event)
1469           
1470    def on_zoom_panel(self, event=None):
1471        """
1472        zoom on the current panel if possible
1473        """
1474        if self.panel_on_focus is not None:
1475            self.panel_on_focus.on_zoom(event)
1476           
1477    def on_zoom_in_panel(self, event=None):
1478        """
1479        zoom in of the panel on focus
1480        """
1481        if self.panel_on_focus is not None:
1482            self.panel_on_focus.on_zoom_in(event)
1483           
1484    def on_zoom_out_panel(self, event=None):
1485        """
1486        zoom out on the panel on focus
1487        """
1488        if self.panel_on_focus is not None:
1489            self.panel_on_focus.on_zoom_out(event)
1490           
1491    def on_drag_panel(self, event=None):
1492        """
1493        drag apply to the panel on focus
1494        """
1495        if self.panel_on_focus is not None:
1496            self.panel_on_focus.on_drag(event)
1497           
1498    def on_reset_panel(self, event=None):
1499        """
1500        reset the current panel
1501        """
1502        if self.panel_on_focus is not None:
1503            self.panel_on_focus.on_reset(event)
1504       
1505class DefaultPanel(wx.Panel, PanelBase):
1506    """
1507    Defines the API for a panels to work with
1508    the GUI manager
1509    """
1510    ## Internal nickname for the window, used by the AUI manager
1511    window_name = "default"
1512    ## Name to appear on the window title bar
1513    window_caption = "Welcome panel"
1514    ## Flag to tell the AUI manager to put this panel in the center pane
1515    CENTER_PANE = True
1516   
1517
1518
1519# Toy application to test this Frame
1520class ViewApp(wx.App):
1521    """
1522    """
1523    SIZE = (GUIFRAME_WIDTH,GUIFRAME_HEIGHT)
1524    TITLE = config.__appname__
1525    PROG_SPLASH_PATH = PROG_SPLASH_SCREEN
1526    STYLE = GUIFRAME.SINGLE_APPLICATION
1527    def OnInit(self):
1528        """
1529        """
1530        pos, size = self.window_placement(self.SIZE)
1531        self.frame = ViewerFrame(parent=None, 
1532                                 title=self.TITLE, 
1533                                 pos=pos, 
1534                                 gui_style = self.STYLE,
1535                                 size=size) 
1536         # Display a splash screen on top of the frame.
1537        if len(sys.argv) > 1 and '--time' in sys.argv[1:]:
1538            log_time("Starting to display the splash screen")
1539        if self.PROG_SPLASH_PATH is not None and \
1540            os.path.isfile(self.PROG_SPLASH_PATH):
1541            try:
1542                self.display_splash_screen(parent=self.frame, path=self.PROG_SPLASH_PATH)   
1543            except:
1544                msg = "Cannot display splash screen\n"
1545                msg += str (sys.exc_value)
1546                logging.error(msg)
1547        self.frame.Show(True)
1548
1549        if hasattr(self.frame, 'special'):
1550            self.frame.special.SetCurrent()
1551        self.SetTopWindow(self.frame)
1552        return True
1553   
1554    def set_manager(self, manager):
1555        """
1556        Sets a reference to the application manager
1557        of the GUI manager (Frame)
1558        """
1559        self.frame.set_manager(manager)
1560       
1561    def build_gui(self):
1562        """
1563        Build the GUI
1564        """
1565        self.frame.build_gui()
1566        self.frame.post_init()
1567       
1568    def set_welcome_panel(self, panel_class):
1569        """
1570        Set the welcome panel
1571       
1572        :param panel_class: class of the welcome panel to be instantiated
1573       
1574        """
1575        self.frame.set_welcome_panel(panel_class)
1576       
1577    def add_perspective(self, perspective):
1578        """
1579        Manually add a perspective to the application GUI
1580        """
1581        self.frame.add_perspective(perspective)
1582   
1583    def window_placement(self, size):
1584        """
1585        Determines the position and size of the application frame such that it
1586        fits on the user's screen without obstructing (or being obstructed by)
1587        the Windows task bar.  The maximum initial size in pixels is bounded by
1588        WIDTH x HEIGHT.  For most monitors, the application
1589        will be centered on the screen; for very large monitors it will be
1590        placed on the left side of the screen.
1591        """
1592        window_width, window_height = size
1593        screen_size = wx.GetDisplaySize()
1594        window_height = window_height if screen_size[1]>window_height else screen_size[1]-50
1595        window_width  = window_width if screen_size[0]> window_width else screen_size[0]-50
1596        xpos = ypos = 0
1597
1598        # Note that when running Linux and using an Xming (X11) server on a PC
1599        # with a dual  monitor configuration, the reported display size may be
1600        # that of both monitors combined with an incorrect display count of 1.
1601        # To avoid displaying this app across both monitors, we check for
1602        # screen 'too big'.  If so, we assume a smaller width which means the
1603        # application will be placed towards the left hand side of the screen.
1604
1605        _, _, x, y = wx.Display().GetClientArea() # size excludes task bar
1606        if len(sys.argv) > 1 and '--platform' in sys.argv[1:]:
1607            w, h = wx.DisplaySize()  # size includes task bar area
1608            print "*** Reported screen size including taskbar is %d x %d"%(w, h)
1609            print "*** Reported screen size excluding taskbar is %d x %d"%(x, y)
1610
1611        if x > 1920: x = 1280  # display on left side, not centered on screen
1612        if x > window_width:  xpos = (x - window_width)/2
1613        if y > window_height: ypos = (y - window_height)/2
1614
1615        # Return the suggested position and size for the application frame.
1616        return (xpos, ypos), (min(x, window_width), min(y, window_height))
1617   
1618    def display_splash_screen(self, parent, path=PROG_SPLASH_SCREEN):
1619        """Displays the splash screen.  It will exactly cover the main frame."""
1620
1621        # Prepare the picture.  On a 2GHz intel cpu, this takes about a second.
1622        x, y = parent.GetSizeTuple()
1623        image = wx.Image(path, wx.BITMAP_TYPE_PNG)
1624        image.Rescale(x, y, wx.IMAGE_QUALITY_HIGH)
1625        bm = image.ConvertToBitmap()
1626
1627        # Create and show the splash screen.  It will disappear only when the
1628        # program has entered the event loop AND either the timeout has expired
1629        # or the user has left clicked on the screen.  Thus any processing
1630        # performed in this routine (including sleeping) or processing in the
1631        # calling routine (including doing imports) will prevent the splash
1632        # screen from disappearing.
1633        #
1634        # Note that on Linux, the timeout appears to occur immediately in which
1635        # case the splash screen disappears upon entering the event loop.
1636        wx.SplashScreen(bitmap=bm,
1637                        splashStyle=(wx.SPLASH_CENTRE_ON_PARENT|
1638                                     wx.SPLASH_TIMEOUT|
1639                                     wx.STAY_ON_TOP),
1640                        milliseconds=4000,
1641                        parent=parent,
1642                        id=wx.ID_ANY)
1643
1644        # Keep the splash screen up a minimum amount of time for non-Windows
1645        # systems.  This is a workaround for Linux and possibly MacOS that
1646        # appear to ignore the splash screen timeout option.
1647        if '__WXMSW__' not in wx.PlatformInfo:
1648            if len(sys.argv) > 1 and '--time' in sys.argv[1:]:
1649                log_time("Starting sleep of 2 secs")
1650            time.sleep(2)
1651
1652        # A call to wx.Yield does not appear to be required.  If used on
1653        # Windows, the cursor changes from 'busy' to 'ready' before the event
1654        # loop is reached which is not desirable.  On Linux it seems to have
1655        # no effect.
1656        #wx.Yield()
1657
1658       
1659
1660if __name__ == "__main__": 
1661    app = ViewApp(0)
1662    app.MainLoop()
1663
1664             
Note: See TracBrowser for help on using the repository browser.