source: sasview/guiframe/gui_manager.py @ e88ebfd

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

working on guiframe

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