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

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 59b5c24 was 8c347a6, checked in by Gervaise Alina <gervyh@…>, 13 years ago

moving guiframe under sansguiframe

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