source: sasview/guiframe/gui_manager.py @ 600eca2

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

combobox perspective

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