source: sasview/sansguiframe/src/sans/guiframe/gui_manager.py @ 54547cc1

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

refactore import config code

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