source: sasview/sansguiframe/src/sans/guiframe/gui_manager.py @ 37c36d9

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

added capability of modifying the Graph window caption

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