source: sasview/guiframe/gui_manager.py @ ecfcef6

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 ecfcef6 was 56d5562, checked in by Jae Cho <jhjcho@…>, 13 years ago

renamed a function _on_view

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