source: sasview/guiframe/gui_manager.py @ 559d055

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 559d055 was 19b5c5c9, checked in by Jae Cho <jhjcho@…>, 13 years ago

made changes to fit the implementation of SANSVIEWPATH env.

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