source: sasview/sansguiframe/src/sans/guiframe/gui_manager.py @ 73197d0

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 73197d0 was 73197d0, checked in by Gervaise Alina <gervyh@…>, 13 years ago

working on batch gui

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