source: sasview/guiframe/gui_manager.py @ 39e5025f

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

modify menu item position according to what was discuss today

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