source: sasview/guiframe/gui_manager.py @ 3554fd39

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

fix toolbar

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