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

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

save state fix for multiple panel

  • Property mode set to 100644
File size: 89.7 KB
Line 
1
2################################################################################
3#This software was developed by the University of Tennessee as part of the
4#Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
5#project funded by the US National Science Foundation.
6#
7#See the license text in license.txt
8#
9#copyright 2008, University of Tennessee
10################################################################################
11
12
13import wx
14import wx.aui
15import os
16import sys
17import xml
18
19try:
20    # Try to find a local config
21    import imp
22    path = os.getcwd()
23    if(os.path.isfile("%s/%s.py" % (path, 'local_config'))) or \
24        (os.path.isfile("%s/%s.pyc" % (path, 'local_config'))):
25        fObj, path, descr = imp.find_module('local_config', [path])
26        config = imp.load_module('local_config', fObj, path, descr) 
27    else:
28        # Try simply importing local_config
29        import local_config as config
30except:
31    # Didn't find local config, load the default
32    import config
33   
34import warnings
35warnings.simplefilter("ignore")
36
37import logging
38
39from sans.guiframe.events import EVT_STATUS
40from sans.guiframe.events import EVT_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
53#read some constants from config
54APPLICATION_STATE_EXTENSION = config.APPLICATION_STATE_EXTENSION
55APPLICATION_NAME = config.__appname__
56SPLASH_SCREEN_PATH = config.SPLASH_SCREEN_PATH
57DEFAULT_STYLE = config.DEFAULT_STYLE
58SPLASH_SCREEN_WIDTH = config.SPLASH_SCREEN_WIDTH
59SPLASH_SCREEN_HEIGHT = config.SPLASH_SCREEN_HEIGHT
60SS_MAX_DISPLAY_TIME = config.SS_MAX_DISPLAY_TIME
61PLOPANEL_WIDTH = config.PLOPANEL_WIDTH
62PLOPANEL_HEIGTH = config.PLOPANEL_HEIGTH
63GUIFRAME_WIDTH = config.GUIFRAME_WIDTH
64GUIFRAME_HEIGHT = config.GUIFRAME_HEIGHT
65PLUGIN_STATE_EXTENSIONS =  config.PLUGIN_STATE_EXTENSIONS
66extension_list = []
67if APPLICATION_STATE_EXTENSION is not None:
68    extension_list.append(APPLICATION_STATE_EXTENSION)
69EXTENSIONS = PLUGIN_STATE_EXTENSIONS + extension_list
70try:
71    PLUGINS_WLIST = '|'.join(config.PLUGINS_WLIST)
72except:
73    PLUGINS_WLIST = ''
74APPLICATION_WLIST = config.APPLICATION_WLIST
75
76class ViewerFrame(wx.Frame):
77    """
78    Main application frame
79    """
80   
81    def __init__(self, parent, title, 
82                 size=(GUIFRAME_WIDTH, GUIFRAME_HEIGHT),
83                 gui_style=GUIFRAME.DEFAULT_STYLE, 
84                 pos=wx.DefaultPosition):
85        """
86        Initialize the Frame object
87        """
88       
89        wx.Frame.__init__(self, parent=parent, title=title, pos=pos,size=size)
90        # title
91        self.title = title
92        # Preferred window size
93        self._window_width, self._window_height = size
94        self.__gui_style = gui_style
95       
96        # Logging info
97        logging.basicConfig(level=logging.DEBUG,
98                    format='%(asctime)s %(levelname)s %(message)s',
99                    filename='sans_app.log',
100                    filemode='w')       
101        path = os.path.dirname(__file__)
102        temp_path = os.path.join(path,'images')
103        ico_file = os.path.join(temp_path,'ball.ico')
104        if os.path.isfile(ico_file):
105            self.SetIcon(wx.Icon(ico_file, wx.BITMAP_TYPE_ICO))
106        else:
107            temp_path = os.path.join(os.getcwd(),'images')
108            ico_file = os.path.join(temp_path,'ball.ico')
109            if os.path.isfile(ico_file):
110                self.SetIcon(wx.Icon(ico_file, wx.BITMAP_TYPE_ICO))
111       
112        ## Application manager
113        self._input_file = None
114        self.app_manager = None
115        self._mgr = None
116        #add current perpsective
117        self._current_perspective = None
118        self._plotting_plugin = None
119        self._data_plugin = None
120        #Menu bar and item
121        self._menubar = None
122        self._file_menu = None
123        self._data_menu = None
124        self._view_menu = None
125        self._window_menu = None
126        self._data_panel_menu = None
127        self._help_menu = None
128        self._tool_menu = None
129        self._applications_menu_pos = -1
130        self._applications_menu_name = None
131        self._applications_menu = None
132        self._edit_menu = None
133        self._toolbar_menu = None
134        self._save_appl_menu = None
135        #tool bar
136        self._toolbar = None
137        # (un)-focus color
138        #self.color = '#b3b3b3'
139        ## Find plug-ins
140        # Modify this so that we can specify the directory to look into
141        self.plugins = []
142        #add local plugin
143        self.plugins += self._get_local_plugins()
144        self.plugins += self._find_plugins()
145        ## List of panels
146        self.panels = {}
147        # List of plot panels
148        self.plot_panels = {}
149
150        # Default locations
151        self._default_save_location = os.getcwd()       
152       
153        # Welcome panel
154        self.defaultPanel = None
155        #panel on focus
156        self.panel_on_focus = None
157        #control_panel on focus
158        self.cpanel_on_focus = None
159        self.loader = Loader()   
160        #data manager
161        from data_manager import DataManager
162        self._data_manager = DataManager()
163        self._data_panel = DataPanel(parent=self)
164        if self.panel_on_focus is not None:
165            self._data_panel.set_panel_on_focus(self.panel_on_focus.window_caption)
166        # list of plot panels in schedule to full redraw
167        self.schedule = False
168        #self.callback = True
169        self._idle_count = 0
170        self.schedule_full_draw_list = []
171        self.idletimer = wx.CallLater(1, self._onDrawIdle)
172
173        # Check for update
174        #self._check_update(None)
175        # Register the close event so it calls our own method
176        wx.EVT_CLOSE(self, self.Close)
177        # Register to status events
178        self.Bind(EVT_STATUS, self._on_status_event)
179        #Register add extra data on the same panel event on load
180        self.Bind(EVT_PANEL_ON_FOCUS, self.set_panel_on_focus)
181        self.Bind(EVT_APPEND_BOOKMARK, self.append_bookmark)
182       
183       
184    def set_input_file(self, input_file):
185        """
186        :param input_file: file to read
187        """
188        self._input_file = input_file
189       
190    def get_data_manager(self):
191        """
192        """
193        return self._data_manager
194   
195    def get_toolbar(self):
196        """
197        """
198        return self._toolbar
199   
200    def set_panel_on_focus(self, event):
201        """
202        Store reference to the last panel on focus
203        update the toolbar if available
204        update edit menu if available
205        """
206        if event != None:
207            self.panel_on_focus = event.panel
208        panel_name = 'No panel on focus'
209        application_name = 'No Selected Analysis'
210        if self.panel_on_focus is not None:
211            for ID in self.panels.keys():
212                if self.panel_on_focus != self.panels[ID]:
213                    self.panels[ID].on_kill_focus(None)
214
215            if self._data_panel is not None:
216                panel_name = self.panel_on_focus.window_caption
217                ID = self.panel_on_focus.uid
218                self._data_panel.set_panel_on_focus(ID)
219                #update combo
220                if self.panel_on_focus in self.plot_panels.values():
221                    self._data_panel.cb_plotpanel.SetStringSelection(str\
222                                         (self.panel_on_focus.window_caption))
223                elif self.panel_on_focus != self._data_panel:
224                    self.cpanel_on_focus = self.panel_on_focus
225                #update toolbar
226                self._update_toolbar_helper()
227                #update edit menu
228                self.enable_edit_menu()
229
230
231    def build_gui(self):
232        """
233        """
234        # set tool bar
235        self._setup_tool_bar()
236        # Set up the layout
237        self._setup_layout()
238        # Set up the menu
239        self._setup_menus()
240       
241        try:
242            self.load_from_cmd(self._input_file)
243        except:
244            msg = "%s Cannot load file %s\n" %(str(APPLICATION_NAME), 
245                                             str(self._input_file))
246            msg += str(sys.exc_value) + '\n'
247            print msg
248        self.post_init()
249        #self.show_welcome_panel(None)
250        self.Show(True)
251        #self._check_update(None)
252             
253    def _setup_layout(self):
254        """
255        Set up the layout
256        """
257        # Status bar
258        from gui_statusbar import StatusBar
259        self.sb = StatusBar(self, wx.ID_ANY)
260        self.SetStatusBar(self.sb)
261        # Add panel
262        default_flag = wx.aui.AUI_MGR_DEFAULT#| wx.aui.AUI_MGR_ALLOW_ACTIVE_PANE
263        self._mgr = wx.aui.AuiManager(self, flags=default_flag)
264        self._mgr.SetDockSizeConstraint(0.5, 0.5)
265        # border color
266        #self.b_color = wx.aui.AUI_DOCKART_BORDER_COLOUR 
267        #self._mgr.GetArtProvider().SetColor(self.b_color, self.color)
268        #self._mgr.SetArtProvider(wx.aui.AuiDockArt(wx.AuiDefaultDockArt))
269        #print "set", self._dockart.GetColour(13)
270        # Load panels
271        self._load_panels()
272        self.set_default_perspective()
273        self._mgr.Update()
274       
275    def SetStatusText(self, *args, **kwds):
276        """
277        """
278        number = self.sb.get_msg_position()
279        wx.Frame.SetStatusText(number=number, *args, **kwds)
280       
281    def PopStatusText(self, *args, **kwds):
282        """
283        """
284        field = self.sb.get_msg_position()
285        wx.Frame.PopStatusText(field=field)
286       
287    def PushStatusText(self, *args, **kwds):
288        """
289        """
290        field = self.sb.get_msg_position()
291        wx.Frame.PushStatusText(self, field=field, string=string)
292
293    def add_perspective(self, plugin):
294        """
295        Add a perspective if it doesn't already
296        exist.
297        """
298        is_loaded = False
299        for item in self.plugins:
300            if plugin.__class__ == item.__class__:
301                msg = "Plugin %s already loaded" % plugin.sub_menu
302                logging.info(msg)
303                is_loaded = True   
304        if not is_loaded:
305            self.plugins.append(plugin)
306     
307    def _get_local_plugins(self):
308        """
309        get plugins local to guiframe and others
310        """
311        plugins = []
312        #import guiframe local plugins
313        #check if the style contain guiframe.dataloader
314        style1 = self.__gui_style & GUIFRAME.DATALOADER_ON
315        style2 = self.__gui_style & GUIFRAME.PLOTTING_ON
316        if style1 == GUIFRAME.DATALOADER_ON:
317            try:
318                from sans.guiframe.local_perspectives.data_loader import data_loader
319                self._data_plugin = data_loader.Plugin()
320                plugins.append(self._data_plugin)
321            except:
322                msg = "ViewerFrame._get_local_plugins:"
323                msg += "cannot import dataloader plugin.\n %s" % sys.exc_value
324                logging.error(msg)
325        if style2 == GUIFRAME.PLOTTING_ON:
326            try:
327                from sans.guiframe.local_perspectives.plotting import plotting
328                self._plotting_plugin = plotting.Plugin()
329                plugins.append(self._plotting_plugin)
330            except:
331                msg = "ViewerFrame._get_local_plugins:"
332                msg += "cannot import plotting plugin.\n %s" % sys.exc_value
333                logging.error(msg)
334     
335        return plugins
336   
337    def _find_plugins(self, dir="perspectives"):
338        """
339        Find available perspective plug-ins
340       
341        :param dir: directory in which to look for plug-ins
342       
343        :return: list of plug-ins
344       
345        """
346        import imp
347        plugins = []
348        # Go through files in panels directory
349        try:
350            list = os.listdir(dir)
351            ## the default panel is the panel is the last plugin added
352            for item in list:
353                toks = os.path.splitext(os.path.basename(item))
354                name = ''
355                if not toks[0] == '__init__':
356                    if toks[1] == '.py' or toks[1] == '':
357                        name = toks[0]
358                    #check the validity of the module name parsed
359                    #before trying to import it
360                    if name is None or name.strip() == '':
361                        continue
362                    path = [os.path.abspath(dir)]
363                    file = ''
364                    try:
365                        if toks[1] == '':
366                            mod_path = '.'.join([dir, name])
367                            module = __import__(mod_path, globals(),
368                                                locals(), [name])
369                        else:
370                            (file, path, info) = imp.find_module(name, path)
371                            module = imp.load_module( name, file, item, info)
372                        if hasattr(module, "PLUGIN_ID"):
373                            try: 
374                                plug = module.Plugin()
375                                if plug.set_default_perspective():
376                                    self._current_perspective = plug
377                                plugins.append(plug)
378                                msg = "Found plug-in: %s" % module.PLUGIN_ID
379                                logging.info(msg)
380                            except:
381                                msg = "Error accessing PluginPanel"
382                                msg += " in %s\n  %s" % (name, sys.exc_value)
383                                config.printEVT(msg)
384                    except:
385                        msg = "ViewerFrame._find_plugins: %s" % sys.exc_value
386                        #print msg
387                        logging.error(msg)
388                    finally:
389                        if not file == None:
390                            file.close()
391        except:
392            # Should raise and catch at a higher level and
393            # display error on status bar
394            pass   
395        return plugins
396   
397    def set_welcome_panel(self, panel_class):
398        """
399        Sets the default panel as the given welcome panel
400       
401        :param panel_class: class of the welcome panel to be instantiated
402       
403        """
404        self.defaultPanel = panel_class(self, -1, style=wx.RAISED_BORDER)
405       
406    def _get_panels_size(self, p):
407        """
408        find the proper size of the current panel
409        get the proper panel width and height
410        """
411        panel_height_min = self._window_height
412        panel_width_min = self._window_width
413        style = self.__gui_style & (GUIFRAME.MANAGER_ON)
414        if self._data_panel is not None  and (p == self._data_panel):
415            panel_width_min = self._window_width * 4/25 
416            panel_height_min = self._window_height * 0.8
417            return panel_width_min, panel_height_min
418        if hasattr(p, "CENTER_PANE") and p.CENTER_PANE:
419            style = self.__gui_style & (GUIFRAME.PLOTTING_ON|GUIFRAME.MANAGER_ON)
420            if style == (GUIFRAME.PLOTTING_ON|GUIFRAME.MANAGER_ON):
421                panel_width_min = self._window_width * 15/25 
422            return panel_width_min, panel_height_min
423        return panel_width_min, panel_height_min
424   
425    def _load_panels(self):
426        """
427        Load all panels in the panels directory
428        """
429       
430        # Look for plug-in panels
431        panels = []   
432        for item in self.plugins:
433            if hasattr(item, "get_panels"):
434                ps = item.get_panels(self)
435                panels.extend(ps)
436       
437        # Show a default panel with some help information
438        # It also sets the size of the application windows
439        #TODO: Use this for slpash screen
440        if self.defaultPanel is None:
441            self.defaultPanel = DefaultPanel(self, -1, style=wx.RAISED_BORDER)
442        # add a blank default panel always present
443        self.panels["default"] = self.defaultPanel
444        self._mgr.AddPane(self.defaultPanel, wx.aui.AuiPaneInfo().
445                              Name("default").
446                              CenterPane().
447                              #CloseButton(False).
448                              #MinimizeButton(False).
449                              # This is where we set the size of
450                              # the application window
451                              BestSize(wx.Size(self._window_width, 
452                                               self._window_height)).
453                              Show())
454
455        #add data panel
456        self.panels["data_panel"] = self._data_panel
457        w, h = self._get_panels_size(self._data_panel)
458        self._mgr.AddPane(self._data_panel, wx.aui.AuiPaneInfo().
459                              Name(self._data_panel.window_name).
460                              Caption(self._data_panel.window_caption).
461                              Left().
462                              MinimizeButton().
463                              CloseButton(True).
464                              TopDockable(False).
465                              BottomDockable(False).
466                              LeftDockable(True).
467                              RightDockable(False).
468                              BestSize(wx.Size(w, h)).
469                              Hide())
470
471        style = self.__gui_style & GUIFRAME.MANAGER_ON
472        data_pane = self._mgr.GetPane(self.panels["data_panel"].window_name)
473        if style != GUIFRAME.MANAGER_ON:
474            self._mgr.GetPane(self.panels["data_panel"].window_name).Hide()
475        else:
476            self._mgr.GetPane(self.panels["data_panel"].window_name).Show()
477           
478        # Add the panels to the AUI manager
479        for panel_class in panels:
480            p = panel_class
481            id = wx.NewId()
482            #w, h = self._get_panels_size(p)
483            # Check whether we need to put this panel
484            # in the center pane
485            if hasattr(p, "CENTER_PANE") and p.CENTER_PANE:
486                w, h = self._get_panels_size(p)
487                if p.CENTER_PANE:
488                    self.panels[str(id)] = p
489                    self._mgr.AddPane(p, wx.aui.AuiPaneInfo().
490                                          Name(p.window_name).
491                                          Caption(p.window_caption).
492                                          #CenterPane().
493                                          Center().
494                                          CloseButton(False).
495                                          #MinimizeButton(False).
496                                          #BestSize(wx.Size(w, h)).
497                                          Hide())
498            else:
499                self.panels[str(id)] = p
500                self._mgr.AddPane(p, wx.aui.AuiPaneInfo().
501                                  Name(p.window_name).Caption(p.window_caption).
502                                  Right().
503                                  Dock().
504                                  TopDockable().
505                                  BottomDockable().
506                                  LeftDockable().
507                                  RightDockable().
508                                  MinimizeButton().
509                                  Hide())       
510     
511    def update_data(self, prev_data, new_data):
512        """
513        """
514        prev_id, data_state = self._data_manager.update_data(prev_data=prev_data, 
515                                       new_data=new_data)
516       
517        self._data_panel.remove_by_id(prev_id)
518        self._data_panel.load_data_list(data_state)
519       
520    def update_theory(self, data_id, theory, state=None):
521        """
522        """ 
523        data_state = self._data_manager.update_theory(data_id=data_id, 
524                                         theory=theory,
525                                         state=state) 
526        self._data_panel.load_data_list(data_state)
527       
528    def onfreeze(self, theory_id):
529        """
530        """
531        data_state_list = self._data_manager.freeze(theory_id)
532        self._data_panel.load_data_list(list=data_state_list)
533        for data_state in data_state_list.values():
534            new_plot = data_state.get_data()
535           
536            wx.PostEvent(self, NewPlotEvent(plot=new_plot,
537                                             title=new_plot.title))
538       
539    def freeze(self, data_id, theory_id):
540        """
541        """
542        data_state_list = self._data_manager.freeze_theory(data_id=data_id, 
543                                                theory_id=theory_id)
544        self._data_panel.load_data_list(list=data_state_list)
545        for data_state in data_state_list.values():
546            new_plot = data_state.get_data()
547            wx.PostEvent(self, NewPlotEvent(plot=new_plot,
548                                             title=new_plot.title))
549       
550    def delete_data(self, data):
551        """
552        """
553        self._current_perspective.delete_data(data)
554       
555   
556    def get_context_menu(self, plotpanel=None):
557        """
558        Get the context menu items made available
559        by the different plug-ins.
560        This function is used by the plotting module
561        """
562        if plotpanel is None:
563            return
564        menu_list = []
565        for item in self.plugins:
566            menu_list.extend(item.get_context_menu(plotpanel=plotpanel))
567        return menu_list
568       
569    def popup_panel(self, p):
570        """
571        Add a panel object to the AUI manager
572       
573        :param p: panel object to add to the AUI manager
574       
575        :return: ID of the event associated with the new panel [int]
576       
577        """
578        ID = wx.NewId()
579        self.panels[str(ID)] = p
580        count = 0
581        for item in self.panels:
582            if self.panels[item].window_name.startswith(p.window_name): 
583                count += 1
584        windowname = p.window_name
585        caption = p.window_caption
586        if count > 0:
587            windowname += str(count+1)
588            caption += (' '+str(count))
589        p.window_name = windowname
590        p.window_caption = caption
591           
592        style1 = self.__gui_style & GUIFRAME.FIXED_PANEL
593        style2 = self.__gui_style & GUIFRAME.FLOATING_PANEL
594        if style1 == GUIFRAME.FIXED_PANEL:
595            self._mgr.AddPane(p, wx.aui.AuiPaneInfo().
596                              Name(windowname).
597                              Caption(caption).
598                              Position(10).
599                              Floatable().
600                              Right().
601                              Dock().
602                              MinimizeButton().
603                              Resizable(True).
604                              # Use a large best size to make sure the AUI
605                              # manager takes all the available space
606                              BestSize(wx.Size(PLOPANEL_WIDTH, 
607                                               PLOPANEL_HEIGTH)))
608                              #MinSize(wx.Size(PLOPANEL_WIDTH*0.9,
609                              #                PLOPANEL_HEIGTH)))
610            self._popup_fixed_panel(p)
611   
612        elif style2 == GUIFRAME.FLOATING_PANEL:
613            self._mgr.AddPane(p, wx.aui.AuiPaneInfo().
614                              Name(windowname).Caption(caption).
615                              MinimizeButton().
616                              Resizable(True).
617                              # Use a large best size to make sure the AUI
618                              #  manager takes all the available space
619                              BestSize(wx.Size(PLOPANEL_WIDTH, 
620                                               PLOPANEL_HEIGTH)))
621            self._popup_floating_panel(p)
622           
623        pane = self._mgr.GetPane(windowname)
624        self._mgr.MaximizePane(pane)
625        self._mgr.RestoreMaximizedPane()
626        # Register for showing/hiding the panel
627        wx.EVT_MENU(self, ID, self._on_view)
628        if p not in self.plot_panels.values():
629            self.plot_panels[ID] = p
630            if self._data_panel is not None and \
631                self._plotting_plugin is not None:
632                ind = self._data_panel.cb_plotpanel.FindString('None')
633                if ind != wx.NOT_FOUND:
634                    self._data_panel.cb_plotpanel.Delete(ind)
635                self._data_panel.cb_plotpanel.Append(str(caption), p)
636        self._mgr.Update()
637        return ID
638       
639    def _setup_menus(self):
640        """
641        Set up the application menus
642        """
643        # Menu
644        self._menubar = wx.MenuBar()
645        self._add_menu_file()
646        self._add_menu_edit()
647        self._add_menu_view()
648        #self._add_menu_data()
649        self._add_menu_application()
650        self._add_menu_tool()
651        self._add_current_plugin_menu()
652        self._add_menu_window()
653        self._add_help_menu()
654        self.SetMenuBar(self._menubar)
655       
656    def _setup_tool_bar(self):
657        """
658        add toolbar to the frame
659        """
660        #set toolbar
661        self._toolbar = GUIToolBar(self, -1)
662        self.SetToolBar(self._toolbar)
663        self._update_toolbar_helper()
664        self._on_toggle_toolbar(event=None)
665   
666    def _update_toolbar_helper(self):
667        """
668        """
669        application_name = 'No Selected Analysis'
670        panel_name = 'No Panel on Focus'
671        if self._toolbar is  None:
672            return
673        self._toolbar.update_toolbar(self.cpanel_on_focus)
674        if self._current_perspective is not None:
675            application_name = self._current_perspective.sub_menu
676        if self.cpanel_on_focus is not None:
677            panel_name = self.cpanel_on_focus.window_caption
678        self._toolbar.update_button(application_name=application_name, 
679                                        panel_name=panel_name)
680        self._toolbar.Realize()
681       
682    def _add_menu_tool(self):
683        """
684        Tools menu
685        Go through plug-ins and find tools to populate the tools menu
686        """
687        style = self.__gui_style & GUIFRAME.CALCULATOR_ON
688        if style == GUIFRAME.CALCULATOR_ON:
689            self._tool_menu = None
690            for item in self.plugins:
691                if hasattr(item, "get_tools"):
692                    for tool in item.get_tools():
693                        # Only create a menu if we have at least one tool
694                        if self._tool_menu is None:
695                            self._tool_menu = wx.Menu()
696                        id = wx.NewId()
697                        self._tool_menu.Append(id, tool[0], tool[1])
698                        wx.EVT_MENU(self, id, tool[2])
699            if self._tool_menu is not None:
700                self._menubar.Append(self._tool_menu, '&Tool')
701               
702    def _add_current_plugin_menu(self):
703        """
704        add current plugin menu
705        Look for plug-in menus
706        Add available plug-in sub-menus.
707        """
708        if (self._menubar is None) or (self._current_perspective is None):
709            return
710        #replace or add a new menu for the current plugin
711       
712        pos = self._menubar.FindMenu(str(self._applications_menu_name))
713        if pos != -1:
714            menu_list = self._current_perspective.populate_menu(self)
715            if menu_list:
716                for (menu, name) in menu_list:
717                    hidden_menu = self._menubar.Replace(pos, menu, name) 
718                    self._applications_menu_name = name
719                #self._applications_menu_pos = pos
720            else:
721                hidden_menu = self._menubar.Remove(pos)
722                self._applications_menu_name = None
723            #get the position of the menu when it first added
724            self._applications_menu_pos = pos
725           
726        else:
727            menu_list = self._current_perspective.populate_menu(self)
728            if menu_list:
729                for (menu,name) in menu_list:
730                    if self._applications_menu_pos == -1:
731                        self._menubar.Append(menu, name)
732                    else:
733                        self._menubar.Insert(self._applications_menu_pos, menu, name)
734                    self._applications_menu_name = name
735                 
736    def _add_help_menu(self):
737        """
738        add help menu
739        """
740        # Help menu
741        self._help_menu = wx.Menu()
742        style = self.__gui_style & GUIFRAME.WELCOME_PANEL_ON
743        if style == GUIFRAME.WELCOME_PANEL_ON:
744            # add the welcome panel menu item
745            if self.defaultPanel is not None:
746                id = wx.NewId()
747                self._help_menu.Append(id, '&Welcome', '')
748                self._help_menu.AppendSeparator()
749                wx.EVT_MENU(self, id, self.show_welcome_panel)
750        # Look for help item in plug-ins
751        for item in self.plugins:
752            if hasattr(item, "help"):
753                id = wx.NewId()
754                self._help_menu.Append(id,'&%s Help' % item.sub_menu, '')
755                wx.EVT_MENU(self, id, item.help)
756        if config._do_aboutbox:
757            id = wx.NewId()
758            self._help_menu.Append(id,'&About', 'Software information')
759            wx.EVT_MENU(self, id, self._onAbout)
760       
761        # Checking for updates needs major refactoring to work with py2exe
762        # We need to make sure it doesn't hang the application if the server
763        # is not up. We also need to make sure there's a proper executable to
764        # run if we spawn a new background process.
765        #id = wx.NewId()
766        #self._help_menu.Append(id,'&Check for update',
767        #'Check for the latest version of %s' % config.__appname__)
768        #wx.EVT_MENU(self, id, self._check_update)
769        self._menubar.Append(self._help_menu, '&Help')
770           
771    def _add_menu_view(self):
772        """
773        add menu items under view menu
774        """
775        self._view_menu = wx.Menu()
776        style = self.__gui_style & GUIFRAME.MANAGER_ON
777        id = wx.NewId()
778        self._data_panel_menu = self._view_menu.Append(id,
779                                                '&Data Explorer ON', '')
780        wx.EVT_MENU(self, id, self.show_data_panel)
781        if style == GUIFRAME.MANAGER_ON:
782            self._data_panel_menu.SetText('Data Explorer OFF')
783        else:
784            self._data_panel_menu.SetText('Data Explorer ON')
785        self._view_menu.AppendSeparator()
786        id = wx.NewId()
787        style1 = self.__gui_style & GUIFRAME.TOOLBAR_ON
788        if style1 == GUIFRAME.TOOLBAR_ON:
789            self._toolbar_menu = self._view_menu.Append(id,'&Hide Toolbar', '')
790        else:
791            self._toolbar_menu = self._view_menu.Append(id,'&Show Toolbar', '')
792        wx.EVT_MENU(self, id, self._on_toggle_toolbar)
793        self._menubar.Append(self._view_menu, '&View')
794       
795    def _add_menu_window(self):
796        """
797        add a menu window to the menu bar
798        Window menu
799        Attach a menu item for each panel in our
800        panel list that also appears in a plug-in.
801       
802        Only add the panel menu if there is only one perspective and
803        it has more than two panels.
804        Note: the first plug-in is always the plotting plug-in.
805        The first application
806        #plug-in is always the second one in the list.
807        """
808        self._window_menu = wx.Menu()
809        if self._plotting_plugin is not None:
810            for (menu, name) in self._plotting_plugin.populate_menu(self):
811                self._window_menu.AppendSubMenu(menu, name)
812        self._menubar.Append(self._window_menu, '&Graph')
813
814        style = self.__gui_style & GUIFRAME.PLOTTING_ON
815        if style == GUIFRAME.PLOTTING_ON:
816            self._window_menu.AppendSeparator()
817            id = wx.NewId()
818            preferences_menu = wx.Menu()
819            hint = "All plot panels will floating"
820            preferences_menu.Append(id, '&Float', hint)
821            wx.EVT_MENU(self, id, self.set_plotpanel_floating)
822            id = wx.NewId()
823            hint = "All plot panels will displayed within the frame"
824            preferences_menu.Append(id, '&Dock', hint)
825            wx.EVT_MENU(self, id, self.set_plotpanel_fixed)
826
827            self._window_menu.AppendSubMenu(preferences_menu,'&Preferences')
828        if self._window_menu.GetMenuItemCount() == 0:
829            pos = self._menubar.FindMenu('Graph')
830            self._menubar.Remove(pos)
831        #wx.EVT_MENU(self, id, self.show_preferences_panel)   
832        """
833        if len(self.plugins) == 2:
834            plug = self.plugins[1]
835            pers = plug.get_perspective()
836       
837            if len(pers) > 1:
838                self._window_menu = wx.Menu()
839                for item in self.panels:
840                    if item == 'default':
841                        continue
842                    panel = self.panels[item]
843                    if panel.window_name in pers:
844                        self._window_menu.Append(int(item),
845                                                  panel.window_caption,
846                                        "Show %s window" % panel.window_caption)
847                        wx.EVT_MENU(self, int(item), self._on_view)
848                self._menubar.Append(self._window_menu, '&Window')
849                """
850               
851    def _add_menu_application(self):
852        """
853       
854        # Attach a menu item for each defined perspective or application.
855        # Only add the perspective menu if there are more than one perspectives
856        add menu application
857        """
858        style = self.__gui_style & GUIFRAME.MULTIPLE_APPLICATIONS
859        if style == GUIFRAME.MULTIPLE_APPLICATIONS:
860            plug_data_count = False
861            plug_no_data_count = False
862            self._applications_menu = wx.Menu()
863            pos = 0
864            separator = self._applications_menu.AppendSeparator()
865            for plug in self.plugins:
866                if len(plug.get_perspective()) > 0:
867                    id = wx.NewId()
868                    if plug.use_data():
869                       
870                        self._applications_menu.InsertCheckItem(pos, id, plug.sub_menu,
871                                      "Switch to analysis: %s" % plug.sub_menu)
872                        plug_data_count = True
873                        pos += 1
874                    else:
875                        plug_no_data_count = True
876                        self._applications_menu.AppendCheckItem(id, plug.sub_menu,
877                                      "Switch to analysis: %s" % plug.sub_menu)
878                    wx.EVT_MENU(self, id, plug.on_perspective)
879            #self._applications_menu.
880            if (not plug_data_count or not plug_no_data_count):
881                self._applications_menu.RemoveItem(separator)
882            self._menubar.Append(self._applications_menu, '&Analysis')
883            self._check_applications_menu()
884           
885    def _populate_file_menu(self):
886        """
887        Insert menu item under file menu
888        """
889        for plugin in self.plugins:
890            if len(plugin.populate_file_menu()) > 0:
891                for item in plugin.populate_file_menu():
892                    m_name, m_hint, m_handler = item
893                    id = wx.NewId()
894                    self._file_menu.Append(id, m_name, m_hint)
895                    wx.EVT_MENU(self, id, m_handler)
896                self._file_menu.AppendSeparator()
897               
898    def _add_menu_file(self):
899        """
900        add menu file
901        """
902       
903         # File menu
904        self._file_menu = wx.Menu()
905        #append item from plugin under menu file if necessary
906        self._populate_file_menu()
907        style = self.__gui_style & GUIFRAME.DATALOADER_ON
908        style1 = self.__gui_style & GUIFRAME.MULTIPLE_APPLICATIONS
909        if style == GUIFRAME.DATALOADER_ON:
910            id = wx.NewId()
911            hint_load_file = "read all analysis states save previously"
912            self._save_appl_menu = self._file_menu.Append(id, 
913                                    '&Open Project', hint_load_file)
914            wx.EVT_MENU(self, id, self._on_open_state_project)
915           
916            if style1 == GUIFRAME.MULTIPLE_APPLICATIONS:
917                # some menu of plugin to be seen under file menu
918                hint_load_file = "Read a status files and load"
919                hint_load_file += " them into the analysis"
920                id = wx.NewId()
921                self._save_appl_menu = self._file_menu.Append(id, 
922                                        '&Open Analysis', hint_load_file)
923                wx.EVT_MENU(self, id, self._on_open_state_application)
924               
925            self._file_menu.AppendSeparator()
926            id = wx.NewId()
927            self._file_menu.Append(id, '&Save Project',
928                                 'Save the state of the whole analysis')
929           
930            wx.EVT_MENU(self, id, self._on_save_project)
931            if style1 == GUIFRAME.MULTIPLE_APPLICATIONS:
932                #self._file_menu.AppendSeparator()
933                id = wx.NewId()
934                self._save_appl_menu = self._file_menu.Append(id, 
935                                                          '&Save Analysis',
936                            'Save state of the current active analysis panel')
937                wx.EVT_MENU(self, id, self._on_save_application)
938           
939            self._file_menu.AppendSeparator()
940       
941        id = wx.NewId()
942        self._file_menu.Append(id, '&Quit', 'Exit') 
943        wx.EVT_MENU(self, id, self.Close)
944        # Add sub menus
945        self._menubar.Append(self._file_menu, '&File')
946       
947    def _add_menu_edit(self):
948        """
949        add menu edit
950        """
951        # Edit Menu
952        self._edit_menu = wx.Menu()
953        self._edit_menu.Append(GUIFRAME_ID.UNDO_ID, '&Undo', 
954                               'Undo the previous action')
955        wx.EVT_MENU(self, GUIFRAME_ID.UNDO_ID, self.on_undo_panel)
956        self._edit_menu.Append(GUIFRAME_ID.REDO_ID, '&Redo', 
957                               'Redo the previous action')
958        wx.EVT_MENU(self, GUIFRAME_ID.REDO_ID, self.on_redo_panel)
959        self._edit_menu.AppendSeparator()
960        self._edit_menu.Append(GUIFRAME_ID.PREVIEW_ID, '&Report',
961                               'Preview current panel')
962        wx.EVT_MENU(self, GUIFRAME_ID.PREVIEW_ID, self.on_preview_panel)
963        self._edit_menu.Append(GUIFRAME_ID.PRINT_ID, '&Print',
964                               'Print current panel')
965        wx.EVT_MENU(self, GUIFRAME_ID.PRINT_ID, self.on_print_panel)
966        self._edit_menu.Append(GUIFRAME_ID.RESET_ID, '&Reset', 
967                               'Reset current panel')
968        wx.EVT_MENU(self, GUIFRAME_ID.RESET_ID, self.on_reset_panel)
969   
970        self._menubar.Append(self._edit_menu,  '&Edit')
971        self.enable_edit_menu()
972       
973    def get_style(self):
974        """
975        """
976        return  self.__gui_style
977   
978    def _add_menu_data(self):
979        """
980        Add menu item item data to menu bar
981        """
982        if self._data_plugin is not None:
983            menu_list = self._data_plugin.populate_menu(self)
984            if menu_list:
985                for (menu, name) in menu_list:
986                    self._menubar.Append(menu, name)
987       
988                       
989    def _on_toggle_toolbar(self, event=None):
990        """
991        hide or show toolbar
992        """
993        if self._toolbar is None:
994            return
995        if self._toolbar.IsShown():
996            if self._toolbar_menu is not None:
997                self._toolbar_menu.SetItemLabel('Show Toolbar')
998            self._toolbar.Hide()
999        else:
1000            if self._toolbar_menu is not None:
1001                self._toolbar_menu.SetItemLabel('Hide Toolbar')
1002            self._toolbar.Show()
1003        self._toolbar.Realize()
1004       
1005    def _on_status_event(self, evt):
1006        """
1007        Display status message
1008        """
1009        self.sb.set_status(event=evt)
1010       
1011    def _on_view(self, evt):
1012        """
1013        A panel was selected to be shown. If it's not already
1014        shown, display it.
1015       
1016        :param evt: menu event
1017       
1018        """
1019        self.show_panel(evt.GetId(), 'on')
1020        wx.CallLater(5, self.set_schedule(True))
1021       
1022    def on_close_welcome_panel(self):
1023        """
1024        Close the welcome panel
1025        """
1026        if self.defaultPanel is None:
1027            return 
1028        default_panel = self._mgr.GetPane(self.panels["default"].window_name)
1029        if default_panel.IsShown():
1030            default_panel.Hide()
1031            # Recover current perspective
1032            perspective = self._current_perspective
1033            perspective.on_perspective(event=None)
1034            self._mgr.Update()
1035            # Show toolbar
1036            style = self.__gui_style & GUIFRAME.TOOLBAR_ON
1037            if (style == GUIFRAME.TOOLBAR_ON) & (not self._toolbar.IsShown()):
1038                self._on_toggle_toolbar()
1039           
1040    def show_welcome_panel(self, event):
1041        """   
1042        Display the welcome panel
1043        """
1044        if self.defaultPanel is None:
1045            return 
1046        for id in self.panels.keys():
1047            if id  ==  'default':
1048                # Show default panel
1049                if not self._mgr.GetPane(self.panels["default"].window_name).IsShown():
1050                    self._mgr.GetPane(self.panels["default"].window_name).Show(True)
1051            elif id == "data_panel":
1052                flag = self._mgr.GetPane(self.panels["data_panel"].window_name).IsShown()
1053                self._mgr.GetPane(self.panels["data_panel"].window_name).Show(flag)
1054            else:
1055                self._mgr.GetPane(self.panels[id].window_name).IsShown()
1056                self._mgr.GetPane(self.panels[id].window_name).Hide()
1057            if self._toolbar != None and not self._toolbar.IsShown():
1058                self._toolbar.Show(True)
1059            self._on_toggle_toolbar()
1060
1061        self._mgr.Update()
1062       
1063    def show_panel(self, uid, show=None):
1064        """
1065        Shows the panel with the given id
1066       
1067        :param uid: unique ID number of the panel to show
1068       
1069        """
1070        ID = str(uid)
1071        config.printEVT("show_panel: %s" % ID)
1072        if ID in self.panels.keys():
1073            if not self._mgr.GetPane(self.panels[ID].window_name).IsShown(): 
1074                if show == 'on':
1075                    self._mgr.GetPane(self.panels[ID].window_name).Show()   
1076                elif self.panels[ID].window_caption.split(" ")[0] == \
1077                                                            "Residuals":
1078                    self._mgr.GetPane(self.panels[ID].window_name).Hide()
1079                else:
1080                    self._mgr.GetPane(self.panels[ID].window_name).Show()
1081                # Hide default panel
1082                self._mgr.GetPane(self.panels["default"].window_name).Hide()
1083        self._mgr.Update()     
1084        self._redraw_idle()
1085                   
1086    def hide_panel(self, uid):
1087        """
1088        hide panel
1089        """
1090        ID = str(uid)
1091        caption = self.panels[ID].window_caption
1092        config.printEVT("hide_panel: %s" % ID)
1093        if ID in self.panels.keys():
1094            if self._mgr.GetPane(self.panels[ID].window_name).IsShown():
1095                self._mgr.GetPane(self.panels[ID].window_name).Hide()
1096                if self._data_panel is not None and \
1097                            ID in self.plot_panels.keys():
1098                    self._data_panel.cb_plotpanel.Append(str(caption), p)
1099                # Hide default panel
1100                self._mgr.GetPane(self.panels["default"].window_name).Hide()
1101            self._mgr.Update()
1102               
1103    def delete_panel(self, uid):
1104        """
1105        delete panel given uid
1106        """
1107        ID = str(uid)
1108        config.printEVT("delete_panel: %s" % ID)
1109        caption = self.panels[ID].window_caption
1110        if ID in self.panels.keys():
1111            self.panel_on_focus = None
1112            panel = self.panels[ID]
1113            self._plotting_plugin.delete_panel(panel.group_id)
1114            self._mgr.DetachPane(panel)
1115            panel.Hide()
1116            panel.clear()
1117            panel.Close()
1118            self._mgr.Update()
1119            print "here here "
1120            return 
1121            if ID in self.panels.keys():
1122                del self.panels[ID]
1123            if ID in self.plot_panels.keys():
1124                del self.plot_panels[ID]
1125            if self._data_panel is not None:
1126                ind = self._data_panel.cb_plotpanel.FindString(str(caption))
1127                if ind != wx.NOT_FOUND:
1128                   self._data_panel.cb_plotpanel.Delete(ind)
1129           
1130            self._mgr.Update()
1131 
1132     
1133    def clear_panel(self):
1134        """
1135        """
1136        for item in self.panels:
1137            try:
1138                self.panels[item].clear_panel()
1139            except:
1140                pass
1141           
1142    def create_gui_data(self, data, path=None):
1143        """
1144        """
1145        return self._data_manager.create_gui_data(data, path)
1146   
1147    def get_data(self, path):
1148        """
1149        """
1150        message = ""
1151        log_msg = ''
1152        output = []
1153        error_message = ""
1154        basename  = os.path.basename(path)
1155        root, extension = os.path.splitext(basename)
1156        if extension.lower() not in EXTENSIONS:
1157            log_msg = "File Loader cannot "
1158            log_msg += "load: %s\n" % str(basename)
1159            log_msg += "Try Data opening...."
1160            logging.info(log_msg)
1161            self.load_complete(output=output, error_message=error_message,
1162                   message=log_msg, path=path)   
1163            return
1164       
1165        #reading a state file
1166        for plug in self.plugins:
1167            reader, ext = plug.get_extensions()
1168            if reader is not None:
1169                #read the state of the single plugin
1170                if extension == ext:
1171                    reader.read(path)
1172                    return
1173                elif extension == APPLICATION_STATE_EXTENSION:
1174                    reader.read(path)
1175       
1176        style = self.__gui_style & GUIFRAME.MANAGER_ON
1177        if style == GUIFRAME.MANAGER_ON:
1178            if self._data_panel is not None:
1179                #data_state = self._data_manager.get_selected_data()
1180                #self._data_panel.load_data_list(data_state)
1181                self._mgr.GetPane(self._data_panel.window_name).Show(True)
1182     
1183    def load_from_cmd(self,  path):   
1184        """
1185        load data from cmd or application
1186        """ 
1187        if path is None:
1188            return
1189        else:
1190            path = os.path.abspath(path)
1191            if not os.path.isfile(path):
1192               return
1193        basename  = os.path.basename(path)
1194        root, extension = os.path.splitext(basename)
1195        if extension.lower() not in EXTENSIONS:
1196            self.load_data(path)
1197        else:
1198            self.load_state(path)
1199         
1200    def load_state(self, path):   
1201        """
1202        load data from command line or application
1203        """
1204        if path and (path is not None) and os.path.isfile(path):
1205            basename  = os.path.basename(path)
1206            if APPLICATION_STATE_EXTENSION is not None \
1207                and basename.endswith(APPLICATION_STATE_EXTENSION):
1208                #remove panels for new states
1209                for plug in self.plugins:
1210                    reader, ext = plug.get_extensions()
1211                    if ext is not None and ext.strip() != ''\
1212                        and ext.lower() not in EXTENSIONS:
1213                        plug.clear_panel() 
1214            self.panel_on_focus = None   
1215            self.cpanel_on_focus = None 
1216            self.get_data(path)
1217        if self.defaultPanel is not None and \
1218            self._mgr.GetPane(self.panels["default"].window_name).IsShown():
1219            self.on_close_welcome_panel()
1220           
1221    def load_data(self, path):
1222        """
1223        load data from command line
1224        """
1225        if not os.path.isfile(path):
1226            return
1227        basename  = os.path.basename(path)
1228        root, extension = os.path.splitext(basename)
1229        if extension.lower() in EXTENSIONS:
1230            log_msg = "Data Loader cannot "
1231            log_msg += "load: %s\n" % str(path)
1232            log_msg += "Try File opening ...."
1233            print log_msg
1234            return
1235        message = ""
1236        log_msg = ''
1237        output = {}
1238        error_message = ""
1239        try:
1240            print "Loading Data...:\n" + str(path) + "\n"
1241            temp =  self.loader.load(path)
1242            if temp.__class__.__name__ == "list":
1243                for item in temp:
1244                    data = self.create_gui_data(item, path)
1245                    output[data.id] = data
1246            else:
1247                data = self.create_gui_data(temp, path)
1248                output[data.id] = data
1249           
1250            self.add_data(data_list=output)
1251        except:
1252            error_message = "Error while loading"
1253            error_message += " Data from cmd:\n %s\n" % str(path)
1254            error_message += str(sys.exc_value) + "\n"
1255            print error_message
1256           
1257     
1258    def _on_open_state_application(self, event):
1259        """
1260        """
1261        path = None
1262        if self._default_save_location == None:
1263            self._default_save_location = os.getcwd()
1264       
1265        plug_wlist = self._on_open_state_app_helper()
1266        dlg = wx.FileDialog(self, 
1267                            "Choose a file", 
1268                            self._default_save_location, "",
1269                            plug_wlist)
1270        if dlg.ShowModal() == wx.ID_OK:
1271            path = dlg.GetPath()
1272            if path is not None:
1273                self._default_save_location = os.path.dirname(path)
1274        dlg.Destroy()
1275        self.load_state(path=path) 
1276   
1277    def _on_open_state_app_helper(self):
1278        """
1279        Helps '_on_open_state_application()' to find the extension of
1280        the current perspective/application
1281        """
1282        # No current perspective or no extension attr
1283        if self._current_perspective is None:
1284            return PLUGINS_WLIST
1285        try:
1286            # Find the extension of the perspective and get that as 1st item in list
1287            ind = None
1288            app_ext = self._current_perspective._extensions
1289            plug_wlist = config.PLUGINS_WLIST
1290            for ext in set(plug_wlist):
1291                if ext.count(app_ext) > 0:
1292                    ind = ext
1293                    break
1294            # Found the extension
1295            if ind != None:
1296                plug_wlist.remove(ind)
1297                plug_wlist.insert(0, ind)
1298                try:
1299                    plug_wlist ='|'.join(plug_wlist)
1300                except:
1301                    plug_wlist = ''
1302
1303        except:
1304            plug_wlist = PLUGINS_WLIST
1305           
1306        return plug_wlist
1307           
1308    def _on_open_state_project(self, event):
1309        """
1310        """
1311        path = None
1312        if self._default_save_location == None:
1313            self._default_save_location = os.getcwd()
1314       
1315        dlg = wx.FileDialog(self, 
1316                            "Choose a file", 
1317                            self._default_save_location, "",
1318                             APPLICATION_WLIST)
1319        if dlg.ShowModal() == wx.ID_OK:
1320            path = dlg.GetPath()
1321            if path is not None:
1322                self._default_save_location = os.path.dirname(path)
1323        dlg.Destroy()
1324        self.load_state(path=path)
1325   
1326    def _on_save_application(self, event):
1327        """
1328        save the state of the current active application
1329        """
1330        if self.cpanel_on_focus is not None:
1331            self.cpanel_on_focus.on_save(event)
1332           
1333    def _on_save_project(self, event):
1334        """
1335        save the state of the current active application
1336        """
1337        ## Default file location for save
1338        self._default_save_location = os.getcwd()
1339        if self._current_perspective is  None:
1340            return
1341        reader, ext = self._current_perspective.get_extensions()
1342        path = None
1343        extension = '*' + APPLICATION_STATE_EXTENSION
1344        dlg = wx.FileDialog(self, "Save Project file",
1345                            self._default_save_location, "",
1346                             extension, 
1347                             wx.SAVE)
1348        if dlg.ShowModal() == wx.ID_OK:
1349            path = dlg.GetPath()
1350            self._default_save_location = os.path.dirname(path)
1351        else:
1352            return None
1353        dlg.Destroy()
1354        if path is None:
1355            return
1356        # default cansas xml doc
1357        doc = None
1358        for panel in self.panels.values():
1359            temp = panel.save_project(doc)
1360            if temp is not None:
1361                doc = temp
1362         
1363        # Write the XML document
1364        if doc != None:
1365            fd = open(path, 'w')
1366            fd.write(doc.toprettyxml())
1367            fd.close()
1368        else:
1369            msg = "%s cannot read %s\n" % (str(APPLICATION_NAME), str(path))
1370            logging.error(msg)
1371                   
1372    def on_save_helper(self, doc, reader, panel, path):
1373        """
1374        Save state into a file
1375        """
1376        try:
1377            if reader is not None:
1378                # case of a panel with multi-pages
1379                if hasattr(panel, "opened_pages"):
1380                    for uid, page in panel.opened_pages.iteritems():
1381                        data = page.get_data()
1382                        # state must be cloned
1383                        state = page.get_state().clone()
1384                        if data is not None:
1385                            new_doc = reader.write_toXML(data, state)
1386                            if doc != None and hasattr(doc, "firstChild"):
1387                                child = new_doc.firstChild.firstChild
1388                                doc.firstChild.appendChild(child) 
1389                            else:
1390                                doc = new_doc
1391                # case of only a panel
1392                else:
1393                    data = panel.get_data()
1394                    state = panel.get_state()
1395                    if data is not None:
1396                        new_doc = reader.write_toXML(data, state)
1397                        if doc != None and hasattr(doc, "firstChild"):
1398                            child = new_doc.firstChild.firstChild
1399                            doc.firstChild.appendChild(child) 
1400                        else:
1401                            doc = new_doc
1402        except: 
1403            raise
1404            #pass
1405
1406        return doc
1407
1408    def quit_guiframe(self):
1409        """
1410        Pop up message to make sure the user wants to quit the application
1411        """
1412        message = "Do you really want to quit \n"
1413        message += "this application?"
1414        dial = wx.MessageDialog(self, message, 'Question',
1415                           wx.YES_NO|wx.YES_DEFAULT|wx.ICON_QUESTION)
1416        if dial.ShowModal() == wx.ID_YES:
1417            return True
1418        else:
1419            return False   
1420       
1421    def Close(self, event=None):
1422        """
1423        Quit the application
1424        """
1425        #flag = self.quit_guiframe()
1426        if True:
1427            wx.Exit()
1428            sys.exit()
1429
1430    def _check_update(self, event=None): 
1431        """
1432        Check with the deployment server whether a new version
1433        of the application is available.
1434        A thread is started for the connecting with the server. The thread calls
1435        a call-back method when the current version number has been obtained.
1436        """
1437        if hasattr(config, "__update_URL__"):
1438            import version
1439            checker = version.VersionThread(config.__update_URL__,
1440                                            self._process_version,
1441                                            baggage=event==None)
1442            checker.start() 
1443   
1444    def _process_version(self, version, standalone=True):
1445        """
1446        Call-back method for the process of checking for updates.
1447        This methods is called by a VersionThread object once the current
1448        version number has been obtained. If the check is being done in the
1449        background, the user will not be notified unless there's an update.
1450       
1451        :param version: version string
1452        :param standalone: True of the update is being checked in
1453           the background, False otherwise.
1454           
1455        """
1456        try:
1457            if cmp(version, config.__version__) > 0:
1458                msg = "Version %s is available! See the Help "
1459                msg += "menu to download it." % version
1460                self.SetStatusText(msg)
1461                if not standalone:
1462                    import webbrowser
1463                    webbrowser.open(config.__download_page__)
1464            else:
1465                if not standalone:
1466                    msg = "You have the latest version"
1467                    msg += " of %s" % config.__appname__
1468                    self.SetStatusText(msg)
1469        except:
1470            msg = "guiframe: could not get latest application"
1471            msg += " version number\n  %s" % sys.exc_value
1472            logging.error(msg)
1473            if not standalone:
1474                msg = "Could not connect to the application server."
1475                msg += " Please try again later."
1476                self.SetStatusText(msg)
1477                   
1478    def _onAbout(self, evt):
1479        """
1480        Pop up the about dialog
1481       
1482        :param evt: menu event
1483       
1484        """
1485        if config._do_aboutbox:
1486            import aboutbox 
1487            dialog = aboutbox.DialogAbout(None, -1, "")
1488            dialog.ShowModal()           
1489           
1490    def set_manager(self, manager):
1491        """
1492        Sets the application manager for this frame
1493       
1494        :param manager: frame manager
1495        """
1496        self.app_manager = manager
1497       
1498    def post_init(self):
1499        """
1500        This initialization method is called after the GUI
1501        has been created and all plug-ins loaded. It calls
1502        the post_init() method of each plug-in (if it exists)
1503        so that final initialization can be done.
1504        """
1505        for item in self.plugins:
1506            if hasattr(item, "post_init"):
1507                item.post_init()
1508       
1509    def set_default_perspective(self):
1510        """
1511        Choose among the plugin the first plug-in that has
1512        "set_default_perspective" method and its return value is True will be
1513        as a default perspective when the welcome page is closed
1514        """
1515        for item in self.plugins:
1516            if hasattr(item, "set_default_perspective"):
1517                if item.set_default_perspective():
1518                    item.on_perspective(event=None)
1519                    return 
1520       
1521    def set_perspective(self, panels):
1522        """
1523        Sets the perspective of the GUI.
1524        Opens all the panels in the list, and closes
1525        all the others.
1526       
1527        :param panels: list of panels
1528        """
1529        style = self.__gui_style & GUIFRAME.TOOLBAR_ON
1530        if (style == GUIFRAME.TOOLBAR_ON) & (not self._toolbar.IsShown()):
1531            self._on_toggle_toolbar()
1532        for item in self.panels:
1533            # Check whether this is a sticky panel
1534            if hasattr(self.panels[item], "ALWAYS_ON"):
1535                if self.panels[item].ALWAYS_ON:
1536                    continue 
1537           
1538            if self.panels[item].window_name in panels:
1539                if not self._mgr.GetPane(self.panels[item].window_name).IsShown():
1540                    self._mgr.GetPane(self.panels[item].window_name).Show()
1541            else:
1542                # always show the data panel if enable
1543                style = self.__gui_style & GUIFRAME.MANAGER_ON
1544                if (style == GUIFRAME.MANAGER_ON) and self.panels[item] == self._data_panel:
1545                    if 'data_panel' in self.panels.keys():
1546                        flag = self._mgr.GetPane(self.panels['data_panel'].window_name).IsShown()
1547                        self._mgr.GetPane(self.panels['data_panel'].window_name).Show(flag)
1548                else:
1549                    if self._mgr.GetPane(self.panels[item].window_name).IsShown():
1550                        self._mgr.GetPane(self.panels[item].window_name).Hide()
1551               
1552        self._mgr.Update()
1553       
1554    def show_data_panel(self, event=None, action=True):
1555        """
1556        show the data panel
1557        """
1558        if self._data_panel_menu == None:
1559            return
1560        label = self._data_panel_menu.GetText()
1561        if label == 'Data Explorer ON':
1562            pane = self._mgr.GetPane(self.panels["data_panel"].window_name)
1563            #if not pane.IsShown():
1564            if action: 
1565                pane.Show(True)
1566                self._mgr.Update()
1567            self.__gui_style = self.__gui_style | GUIFRAME.MANAGER_ON
1568           
1569            self._data_panel_menu.SetText('Data Explorer OFF')
1570        else:
1571            pane = self._mgr.GetPane(self.panels["data_panel"].window_name)
1572            #if not pane.IsShown():
1573            if action:
1574                pane.Show(False)
1575                self._mgr.Update()
1576            self.__gui_style = self.__gui_style & (~GUIFRAME.MANAGER_ON)
1577            self._data_panel_menu.SetText('Data Explorer ON')
1578   
1579    def add_data_helper(self, data_list):
1580        """
1581        """
1582        if self._data_manager is not None:
1583            self._data_manager.add_data(data_list)
1584       
1585    def add_data(self, data_list):
1586        """
1587        receive a dictionary of data from loader
1588        store them its data manager if possible
1589        send to data the current active perspective if the data panel
1590        is not active.
1591        :param data_list: dictionary of data's ID and value Data
1592        """
1593        #Store data into manager
1594        self.add_data_helper(data_list)
1595        # set data in the data panel
1596        if self._data_panel is not None:
1597            data_state = self._data_manager.get_data_state(data_list.keys())
1598            self._data_panel.load_data_list(data_state)
1599        #if the data panel is shown wait for the user to press a button
1600        #to send data to the current perspective. if the panel is not
1601        #show  automatically send the data to the current perspective
1602        style = self.__gui_style & GUIFRAME.MANAGER_ON
1603        if style == GUIFRAME.MANAGER_ON:
1604            #wait for button press from the data panel to set_data
1605            if self._data_panel is not None:
1606                self._mgr.GetPane(self._data_panel.window_name).Show(True)
1607                self._mgr.Update() 
1608        else:
1609            #automatically send that to the current perspective
1610            self.set_data(data_id=data_list.keys())
1611            self.on_close_welcome_panel()
1612       
1613    def set_data(self, data_id, theory_id=None): 
1614        """
1615        set data to current perspective
1616        """
1617        list_data, _ = self._data_manager.get_by_id(data_id)
1618        if self._current_perspective is not None:
1619            for uid, panel in self.plot_panels.iteritems() :
1620                #panel = self.plot_panels[uid]
1621                window = self._mgr.GetPane(panel.window_name)
1622                # To hide all docked plot panels when set the data
1623                #if not window.IsFloating():
1624                #    self.hide_panel(uid)
1625            self._current_perspective.set_data(list_data.values())
1626            self.on_close_welcome_panel()
1627        else:
1628            msg = "Guiframe does not have a current perspective"
1629            logging.info(msg)
1630           
1631    def set_theory(self, state_id, theory_id=None):
1632        """
1633        """
1634        _, list_theory = self._data_manager.get_by_id(theory_id)
1635        if self._current_perspective is not None:
1636            try:
1637                self._current_perspective.set_theory(list_theory.values())
1638            except:
1639                msg = "Guiframe set_theory: \n" + str(sys.exc_value)
1640                logging.info(msg)
1641                wx.PostEvent(self, StatusEvent(status=msg, info="error"))
1642        else:
1643            msg = "Guiframe does not have a current perspective"
1644            logging.info(msg)
1645           
1646    def plot_data(self,  state_id, data_id=None,
1647                  theory_id=None, append=False):
1648        """
1649        send a list of data to plot
1650        """
1651        total_plot_list = []
1652        data_list, _ = self._data_manager.get_by_id(data_id)
1653        _, temp_list_theory = self._data_manager.get_by_id(theory_id)
1654        total_plot_list = data_list.values()
1655        for item in temp_list_theory.values():
1656            theory_data, theory_state = item
1657            total_plot_list.append(theory_data)
1658        GROUP_ID = wx.NewId()
1659        for new_plot in total_plot_list:
1660            if append:
1661                if self.panel_on_focus is None:
1662                    message = "cannot append plot. No plot panel on focus!"
1663                    message += "please click on any available plot to set focus"
1664                    wx.PostEvent(self, StatusEvent(status=message, 
1665                                                   info='warning'))
1666                    return 
1667                else:
1668                    if self.enable_add_data(new_plot):
1669                        new_plot.group_id = self.panel_on_focus.group_id
1670                    else:
1671                        message = "Only 1D Data can be append to plot panel\n"
1672                        message += "%s will be plot separetly\n" %str(new_plot.name)
1673                        wx.PostEvent(self, StatusEvent(status=message, 
1674                                                   info='warning'))
1675            else:
1676                #if not append then new plot
1677                new_plot.group_id = GROUP_ID
1678            title = "PLOT " + str(new_plot.title)
1679            wx.PostEvent(self, NewPlotEvent(plot=new_plot,
1680                                                  title=title))
1681           
1682    def remove_data(self, data_id, theory_id=None):
1683        """
1684        Delete data state if data_id is provide
1685        delete theory created with data of id data_id if theory_id is provide
1686        if delete all true: delete the all state
1687        else delete theory
1688        """
1689        for plug in self.plugins:
1690            plug.delete_data(data_id)
1691        total_plot_list = []
1692        data_list, _ = self._data_manager.get_by_id(data_id)
1693        _, temp_list_theory = self._data_manager.get_by_id(theory_id)
1694        total_plot_list = data_list.values()
1695        for item in temp_list_theory.values():
1696            theory_data, theory_state = item
1697            total_plot_list.append(theory_data)
1698        for new_plot in total_plot_list:
1699            id = new_plot.id
1700            for group_id in new_plot.list_group_id:
1701                wx.PostEvent(self, NewPlotEvent(id=id,
1702                                                   group_id=group_id,
1703                                                   action='remove'))
1704        self._data_manager.delete_data(data_id=data_id, 
1705                                       theory_id=theory_id)
1706           
1707       
1708    def set_current_perspective(self, perspective):
1709        """
1710        set the current active perspective
1711        """
1712        self._current_perspective = perspective
1713        name = "No current analysis selected"
1714        if self._current_perspective is not None:
1715            self._add_current_plugin_menu()
1716            for panel in self.panels.values():
1717                if hasattr(panel, 'CENTER_PANE') and panel.CENTER_PANE:
1718                    for name in self._current_perspective.get_perspective():
1719                        if name == panel.window_name:
1720                            panel.on_set_focus(event=None)
1721                            break
1722                           
1723            name = self._current_perspective.sub_menu
1724            if self._data_panel is not None:
1725                self._data_panel.set_active_perspective(name)
1726                self._check_applications_menu()
1727            #Set the SansView title
1728            self._set_title_name(name)
1729         
1730           
1731    def _set_title_name(self, name):
1732        """
1733        Set the SansView title w/ the current application name
1734       
1735        : param name: application name [string]
1736        """
1737        # Set SanView Window title w/ application anme
1738        title = self.title + "  - " + name + " -"
1739        self.SetTitle(title)
1740           
1741    def _check_applications_menu(self):
1742        """
1743        check the menu of the current application
1744        """
1745        if self._applications_menu is not None:
1746            for menu in self._applications_menu.GetMenuItems():
1747                if self._current_perspective is not None:
1748                    name = self._current_perspective.sub_menu
1749                    if menu.IsCheckable():
1750                        if menu.GetLabel() == name:
1751                            menu.Check(True)
1752                        else:
1753                             menu.Check(False) 
1754           
1755    def set_plotpanel_floating(self, event=None):
1756        """
1757        make the plot panel floatable
1758        """
1759        self.__gui_style &= (~GUIFRAME.FIXED_PANEL)
1760        self.__gui_style |= GUIFRAME.FLOATING_PANEL
1761        for p in self.panels.values():
1762            plot_panel = self._plotting_plugin.plot_panels.values()
1763            for p in self.panels.values():
1764                if p in plot_panel:
1765                    self._popup_floating_panel(p)
1766       
1767    def set_plotpanel_fixed(self, event=None):
1768        """
1769        make the plot panel fixed
1770        """
1771        self.__gui_style &= (~GUIFRAME.FLOATING_PANEL)
1772        self.__gui_style |= GUIFRAME.FIXED_PANEL
1773        plot_panel = []
1774        if self._plotting_plugin is not None:
1775            plot_panel = self._plotting_plugin.plot_panels.values()
1776            for p in self.panels.values():
1777                if p in plot_panel:
1778                    self._popup_fixed_panel(p)
1779                   
1780    def _popup_fixed_panel(self, p):
1781        """
1782        """
1783        style = self.__gui_style & GUIFRAME.FIXED_PANEL
1784        if style == GUIFRAME.FIXED_PANEL:
1785            self._mgr.GetPane(p.window_name).Dock()
1786            self._mgr.GetPane(p.window_name).Floatable()
1787            self._mgr.GetPane(p.window_name).Right()
1788            self._mgr.GetPane(p.window_name).TopDockable(False)
1789            self._mgr.GetPane(p.window_name).BottomDockable(False)
1790            self._mgr.GetPane(p.window_name).LeftDockable(False)
1791            self._mgr.GetPane(p.window_name).RightDockable(True)
1792            flag = self._mgr.GetPane(p.window_name).IsShown()
1793            self._mgr.GetPane(p.window_name).Show(flag)
1794            self._mgr.Update()
1795           
1796    def _popup_floating_panel(self, p):
1797        """
1798        """
1799        style = self.__gui_style &  GUIFRAME.FLOATING_PANEL
1800        if style == GUIFRAME.FLOATING_PANEL: 
1801            self._mgr.GetPane(p.window_name).Floatable(True)
1802            self._mgr.GetPane(p.window_name).Float()
1803            self._mgr.GetPane(p.window_name).Dockable(False)
1804            flag = self._mgr.GetPane(p.window_name).IsShown()
1805            self._mgr.GetPane(p.window_name).Show(flag)
1806            self._mgr.Update()
1807           
1808    def enable_add_data(self, new_plot):
1809        """
1810        Enable append data on a plot panel
1811        """
1812
1813        if self.panel_on_focus not in self._plotting_plugin.plot_panels.values():
1814            return
1815        is_theory = len(self.panel_on_focus.plots) <= 1 and \
1816            self.panel_on_focus.plots.values()[0].__class__.__name__ == "Theory1D"
1817           
1818        is_data2d = hasattr(new_plot, 'data')
1819       
1820        is_data1d = self.panel_on_focus.__class__.__name__ == "ModelPanel1D"\
1821            and self.panel_on_focus.group_id is not None
1822        has_meta_data = hasattr(new_plot, 'meta_data')
1823       
1824        #disable_add_data if the data is being recovered from  a saved state file.
1825        is_state_data = False
1826        if has_meta_data:
1827            if 'invstate' in new_plot.meta_data: is_state_data = True
1828            if  'prstate' in new_plot.meta_data: is_state_data = True
1829            if  'fitstate' in new_plot.meta_data: is_state_data = True
1830   
1831        return is_data1d and not is_data2d and not is_theory and not is_state_data
1832   
1833    def enable_edit_menu(self):
1834        """
1835        enable menu item under edit menu depending on the panel on focus
1836        """
1837        if self.cpanel_on_focus is not None and self._edit_menu is not None:
1838            flag = self.cpanel_on_focus.get_undo_flag()
1839            self._edit_menu.Enable(GUIFRAME_ID.UNDO_ID, flag)
1840            flag = self.cpanel_on_focus.get_redo_flag()
1841            self._edit_menu.Enable(GUIFRAME_ID.REDO_ID, flag)
1842            flag = self.cpanel_on_focus.get_print_flag()
1843            self._edit_menu.Enable(GUIFRAME_ID.PRINT_ID, flag)
1844            flag = self.cpanel_on_focus.get_preview_flag()
1845            self._edit_menu.Enable(GUIFRAME_ID.PREVIEW_ID, flag)
1846            flag = self.cpanel_on_focus.get_reset_flag()
1847            self._edit_menu.Enable(GUIFRAME_ID.RESET_ID, flag)
1848        else:
1849            flag = False
1850            self._edit_menu.Enable(GUIFRAME_ID.UNDO_ID, flag)
1851            self._edit_menu.Enable(GUIFRAME_ID.REDO_ID, flag)
1852            self._edit_menu.Enable(GUIFRAME_ID.PRINT_ID, flag)
1853            self._edit_menu.Enable(GUIFRAME_ID.PREVIEW_ID, flag)
1854            self._edit_menu.Enable(GUIFRAME_ID.RESET_ID, flag)
1855           
1856    def on_undo_panel(self, event=None):
1857        """
1858        undo previous action of the last panel on focus if possible
1859        """
1860        if self.cpanel_on_focus is not None:
1861            self.cpanel_on_focus.on_undo(event)
1862           
1863    def on_redo_panel(self, event=None):
1864        """
1865        redo the last cancel action done on the last panel on focus
1866        """
1867        if self.cpanel_on_focus is not None:
1868            self.cpanel_on_focus.on_redo(event)
1869           
1870    def on_bookmark_panel(self, event=None):
1871        """
1872        bookmark panel
1873        """
1874        if self.cpanel_on_focus is not None:
1875            self.cpanel_on_focus.on_bookmark(event)
1876           
1877    def append_bookmark(self, event=None):
1878        """
1879        Bookmark available information of the panel on focus
1880        """
1881        self._toolbar.append_bookmark(event)
1882           
1883    def on_save_panel(self, event=None):
1884        """
1885        save possible information on the current panel
1886        """
1887        if self.cpanel_on_focus is not None:
1888            self.cpanel_on_focus.on_save(event)
1889           
1890    def on_preview_panel(self, event=None):
1891        """
1892        preview information on the panel on focus
1893        """
1894        if self.cpanel_on_focus is not None:
1895            self.cpanel_on_focus.on_preview(event)
1896           
1897    def on_print_panel(self, event=None):
1898        """
1899        print available information on the last panel on focus
1900        """
1901        if self.cpanel_on_focus is not None:
1902            self.cpanel_on_focus.on_print(event)
1903           
1904    def on_zoom_panel(self, event=None):
1905        """
1906        zoom on the current panel if possible
1907        """
1908        if self.cpanel_on_focus is not None:
1909            self.cpanel_on_focus.on_zoom(event)
1910           
1911    def on_zoom_in_panel(self, event=None):
1912        """
1913        zoom in of the panel on focus
1914        """
1915        if self.cpanel_on_focus is not None:
1916            self.cpanel_on_focus.on_zoom_in(event)
1917           
1918    def on_zoom_out_panel(self, event=None):
1919        """
1920        zoom out on the panel on focus
1921        """
1922        if self.cpanel_on_focus is not None:
1923            self.cpanel_on_focus.on_zoom_out(event)
1924           
1925    def on_drag_panel(self, event=None):
1926        """
1927        drag apply to the panel on focus
1928        """
1929        if self.cpanel_on_focus is not None:
1930            self.cpanel_on_focus.on_drag(event)
1931           
1932    def on_reset_panel(self, event=None):
1933        """
1934        reset the current panel
1935        """
1936        if self.cpanel_on_focus is not None:
1937            self.cpanel_on_focus.on_reset(event)
1938           
1939    def enable_undo(self):
1940        """
1941        enable undo related control
1942        """
1943        if self.cpanel_on_focus is not None:
1944            self._toolbar.enable_undo(self.cpanel_on_focus)
1945           
1946    def enable_redo(self):
1947        """
1948        enable redo
1949        """
1950        if self.cpanel_on_focus is not None:
1951            self._toolbar.enable_redo(self.cpanel_on_focus)
1952           
1953    def enable_bookmark(self):
1954        """
1955        Bookmark
1956        """
1957        if self.cpanel_on_focus is not None:
1958            self._toolbar.enable_bookmark(self.cpanel_on_focus)
1959           
1960    def enable_save(self):
1961        """
1962        save
1963        """
1964        if self.cpanel_on_focus is not None:
1965            self._toolbar.enable_save(self.cpanel_on_focus)
1966           
1967    def enable_preview(self):
1968        """
1969        preview
1970        """
1971        if self.cpanel_on_focus is not None:
1972            self._toolbar.enable_preview(self.cpanel_on_focus)
1973           
1974    def enable_print(self):
1975        """
1976        print
1977        """
1978        if self.cpanel_on_focus is not None:
1979            self._toolbar.enable_print(self.cpanel_on_focus)
1980           
1981    def enable_zoom(self):
1982        """
1983        zoom
1984        """
1985        if self.cpanel_on_focus is not None:
1986            self._toolbar.enable_zoom(self.panel_on_focus)
1987           
1988    def enable_zoom_in(self):
1989        """
1990        zoom in
1991        """
1992        if self.cpanel_on_focus is not None:
1993            self._toolbar.enable_zoom_in(self.panel_on_focus)
1994           
1995    def enable_zoom_out(self):
1996        """
1997        zoom out
1998        """
1999        if self.cpanel_on_focus is not None:
2000            self._toolbar.enable_zoom_out(self.panel_on_focus)
2001           
2002    def enable_drag(self, event=None):
2003        """
2004        drag
2005        """
2006        if self.cpanel_on_focus is not None:
2007            self._toolbar.enable_drag(self.panel_on_focus)
2008           
2009    def enable_reset(self):
2010        """
2011        reset the current panel
2012        """
2013        if self.cpanel_on_focus is not None:
2014            self._toolbar.enable_reset(self.panel_on_focus)
2015
2016    def set_schedule_full_draw(self, panel=None, func='del'):
2017        """
2018        Add/subtract the schedule full draw list with the panel given
2019       
2020        :param panel: plot panel
2021        :param func: append or del [string]
2022        """
2023
2024        # append this panel in the schedule list if not in yet
2025        if func == 'append':
2026            if not panel in self.schedule_full_draw_list:
2027                self.schedule_full_draw_list.append(panel) 
2028        # remove this panel from schedule list
2029        elif func == 'del':
2030            if len(self.schedule_full_draw_list) > 0:
2031                if panel in self.schedule_full_draw_list:
2032                    self.schedule_full_draw_list.remove(panel)
2033
2034        # reset the schdule
2035        if len(self.schedule_full_draw_list) == 0:
2036            self.schedule = False
2037        else:
2038            self.schedule = True   
2039       
2040    def full_draw(self):
2041        """
2042        Draw the panels with axes in the schedule to full dwar list
2043        """
2044        count = len(self.schedule_full_draw_list)
2045        #if not self.schedule:
2046        if count < 1:
2047            self.set_schedule(False)
2048            return
2049        else:
2050            ind = 0
2051            # if any of the panel is shown do full_draw
2052            for panel in self.schedule_full_draw_list:
2053                ind += 1
2054                if self._mgr.GetPane(panel.window_name).IsShown():
2055                    break
2056                # otherwise, return
2057                if ind == count:
2058                    return
2059
2060        #Simple redraw only for a panel shown
2061        def f_draw(panel):
2062            """
2063            Draw A panel in the full dwar list
2064            """
2065            # Check if the panel is shown
2066            if self._mgr.GetPane(panel.window_name).IsShown():
2067                try:
2068                    # This checking of GetCapture is to stop redrawing
2069                    # while any panel is capture.
2070                    if self.GetCapture() == None:
2071                        # draw if possible
2072                        panel.set_resizing(False)
2073                        panel.draw_plot()
2074                except:
2075                    pass
2076        #print self.callback,self.schedule,self.schedule_full_draw_list
2077       
2078        # Draw all panels       
2079        map(f_draw, self.schedule_full_draw_list)
2080       
2081        # Reset the attr 
2082        if len(self.schedule_full_draw_list) == 0:
2083            self.set_schedule(False)
2084        else:
2085            self.set_schedule(True)
2086        # update mgr
2087        self._mgr.Update()
2088       
2089    def set_schedule(self, schedule=False): 
2090        """
2091        Set schedule
2092        """
2093        self.schedule = schedule
2094               
2095    def get_schedule(self): 
2096        """
2097        Get schedule
2098        """
2099        return self.schedule
2100   
2101    def on_set_plot_focus(self, panel):
2102        """
2103        Set focus on a plot panel
2104        """
2105        for plot in self.plot_panels.values():
2106            # make sure we don't double focus
2107            if panel != plot:
2108                plot.on_kill_focus(None)
2109
2110        panel.on_set_focus(None) 
2111        # set focusing panel
2112        self.panel_on_focus = panel 
2113        self.set_panel_on_focus(None)
2114        print " on_set_plot_focus"
2115         
2116    def _onDrawIdle(self, *args, **kwargs):
2117        """
2118        ReDraw with axes
2119        """
2120        # check if it is time to redraw
2121        if self.GetCapture() == None:
2122            # Draw plot, changes resizing too
2123            self.full_draw()
2124           
2125        # restart idle       
2126        self._redraw_idle(*args, **kwargs)
2127
2128           
2129    def _redraw_idle(self, *args, **kwargs):
2130        """
2131        Restart Idle
2132        """
2133        # restart idle   
2134        self.idletimer.Restart(55, *args, **kwargs)
2135
2136       
2137class DefaultPanel(wx.Panel, PanelBase):
2138    """
2139    Defines the API for a panels to work with
2140    the GUI manager
2141    """
2142    ## Internal nickname for the window, used by the AUI manager
2143    window_name = "default"
2144    ## Name to appear on the window title bar
2145    window_caption = "Welcome panel"
2146    ## Flag to tell the AUI manager to put this panel in the center pane
2147    CENTER_PANE = True
2148    def __init__(self, parent, *args, **kwds):
2149        wx.Panel.__init__(self, parent, *args, **kwds)
2150        PanelBase.__init__(self, parent)
2151   
2152
2153
2154# Toy application to test this Frame
2155class ViewApp(wx.App):
2156    """
2157    """
2158    def OnInit(self):
2159        """
2160        """
2161        pos, size = self.window_placement((GUIFRAME_WIDTH, GUIFRAME_HEIGHT))
2162        self.frame = ViewerFrame(parent=None, 
2163                                 title=APPLICATION_NAME, 
2164                                 pos=pos, 
2165                                 gui_style = DEFAULT_STYLE,
2166                                 size=size) 
2167        self.s_screen = None
2168        # Display a splash screen on top of the frame.
2169        if len(sys.argv) > 1 and '--time' in sys.argv[1:]:
2170            log_time("Starting to display the splash screen")
2171       
2172        try:
2173            if os.path.isfile(SPLASH_SCREEN_PATH):
2174                self.s_screen = self.display_splash_screen(parent=self.frame, 
2175                                        path=SPLASH_SCREEN_PATH)
2176            else:
2177                self.frame.Show()   
2178        except:
2179           msg = "Cannot display splash screen\n"
2180           msg += str (sys.exc_value)
2181           logging.error(msg)
2182           self.frame.Show()
2183           
2184        if hasattr(self.frame, 'special'):
2185            self.frame.special.SetCurrent()
2186        self.SetTopWindow(self.frame)
2187        try:
2188            self.open_file()
2189        except:
2190            msg = "%s Could not load " % str(APPLICATION_NAME)
2191            msg += "input file from command line.\n"
2192            logging.error(msg)
2193        return True
2194
2195    def open_file(self):
2196        """
2197        open a state file at the start of the application
2198        """
2199        input_file = None
2200        if len(sys.argv) >= 2:
2201            cmd = sys.argv[0].lower()
2202            if os.path.isfile(cmd):
2203                basename  = os.path.basename(cmd)
2204                app_py = str(APPLICATION_NAME).lower() + '.py'
2205                app_exe = str(APPLICATION_NAME).lower() + '.exe'
2206                if basename.lower() in [app_py, app_exe]:
2207                    input_file = sys.argv[1]
2208        if input_file is None:
2209            return
2210        if self.frame is not None:
2211            self.frame.set_input_file(input_file=input_file)
2212         
2213           
2214    def set_manager(self, manager):
2215        """
2216        Sets a reference to the application manager
2217        of the GUI manager (Frame)
2218        """
2219        self.frame.set_manager(manager)
2220       
2221    def build_gui(self):
2222        """
2223        Build the GUI
2224        """
2225        #try to load file at the start
2226        try:
2227            self.open_file()
2228        except:
2229            raise
2230        self.frame.build_gui()
2231        if self.s_screen is not None and self.s_screen.IsShown():
2232            self.s_screen.Close()
2233       
2234    def set_welcome_panel(self, panel_class):
2235        """
2236        Set the welcome panel
2237       
2238        :param panel_class: class of the welcome panel to be instantiated
2239       
2240        """
2241        self.frame.set_welcome_panel(panel_class)
2242       
2243    def add_perspective(self, perspective):
2244        """
2245        Manually add a perspective to the application GUI
2246        """
2247        self.frame.add_perspective(perspective)
2248   
2249    def window_placement(self, size):
2250        """
2251        Determines the position and size of the application frame such that it
2252        fits on the user's screen without obstructing (or being obstructed by)
2253        the Windows task bar.  The maximum initial size in pixels is bounded by
2254        WIDTH x HEIGHT.  For most monitors, the application
2255        will be centered on the screen; for very large monitors it will be
2256        placed on the left side of the screen.
2257        """
2258        window_width, window_height = size
2259        screen_size = wx.GetDisplaySize()
2260        window_height = window_height if screen_size[1]>window_height else screen_size[1]-50
2261        window_width  = window_width if screen_size[0]> window_width else screen_size[0]-50
2262        xpos = ypos = 0
2263
2264        # Note that when running Linux and using an Xming (X11) server on a PC
2265        # with a dual  monitor configuration, the reported display size may be
2266        # that of both monitors combined with an incorrect display count of 1.
2267        # To avoid displaying this app across both monitors, we check for
2268        # screen 'too big'.  If so, we assume a smaller width which means the
2269        # application will be placed towards the left hand side of the screen.
2270
2271        _, _, x, y = wx.Display().GetClientArea() # size excludes task bar
2272        if len(sys.argv) > 1 and '--platform' in sys.argv[1:]:
2273            w, h = wx.DisplaySize()  # size includes task bar area
2274        if x > 1920: x = 1280  # display on left side, not centered on screen
2275        if x > window_width:  xpos = (x - window_width)/2
2276        if y > window_height: ypos = (y - window_height)/2
2277
2278        # Return the suggested position and size for the application frame.
2279        return (xpos, ypos), (min(x, window_width), min(y, window_height))
2280   
2281    def display_splash_screen(self, parent, 
2282                              path=SPLASH_SCREEN_PATH):
2283        """Displays the splash screen.  It will exactly cover the main frame."""
2284       
2285        # Prepare the picture.  On a 2GHz intel cpu, this takes about a second.
2286        x, y = parent.GetSizeTuple()
2287        image = wx.Image(path, wx.BITMAP_TYPE_PNG)
2288        image.Rescale(SPLASH_SCREEN_WIDTH, 
2289                      SPLASH_SCREEN_HEIGHT, wx.IMAGE_QUALITY_HIGH)
2290        bm = image.ConvertToBitmap()
2291
2292        # Create and show the splash screen.  It will disappear only when the
2293        # program has entered the event loop AND either the timeout has expired
2294        # or the user has left clicked on the screen.  Thus any processing
2295        # performed in this routine (including sleeping) or processing in the
2296        # calling routine (including doing imports) will prevent the splash
2297        # screen from disappearing.
2298        #
2299        # Note that on Linux, the timeout appears to occur immediately in which
2300        # case the splash screen disappears upon entering the event loop.
2301        s_screen = wx.SplashScreen(bitmap=bm,
2302                         splashStyle=(wx.SPLASH_TIMEOUT|
2303                                              wx.SPLASH_CENTRE_ON_SCREEN),
2304                                 style=(wx.SIMPLE_BORDER|
2305                                        wx.FRAME_NO_TASKBAR|
2306                                        wx.STAY_ON_TOP),
2307                                       
2308                        milliseconds=SS_MAX_DISPLAY_TIME,
2309                        parent=parent,
2310                        id=wx.ID_ANY)
2311
2312        s_screen.Bind(wx.EVT_CLOSE, self.on_close_splash_screen)
2313        s_screen.Show()
2314        return s_screen
2315       
2316       
2317    def on_close_splash_screen(self, event):
2318        """
2319        """
2320        self.frame.Show(True)
2321        event.Skip()
2322     
2323if __name__ == "__main__": 
2324    app = ViewApp(0)
2325    app.MainLoop()
2326
2327             
Note: See TracBrowser for help on using the repository browser.