source: sasview/guiframe/gui_manager.py @ 32d26da

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

added missing return plug_wlist

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