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

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

make sure plugins is not empty when filling data_panel cbox_anaysis up

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