source: sasview/guiframe/gui_manager.py @ 054c10a

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

removed mac specific operation of menu/panel closing; it works on wx 2.9.3/mac

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