source: sasview/guiframe/gui_manager.py @ 69b4027

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 69b4027 was 75fbd17, checked in by Gervaise Alina <gervyh@…>, 14 years ago

working on save state

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