source: sasview/guiframe/gui_manager.py @ 8c6a0b9

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 8c6a0b9 was 889e9f8, checked in by Jae Cho <jhjcho@…>, 13 years ago

try wx2.9 for mac

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