source: sasview/guiframe/gui_manager.py @ c6f2291

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

added tip for datapanel/panel_combobox

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