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

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 889de4d9 was 390742c, checked in by Gervaise Alina <gervyh@…>, 13 years ago

add quit dialog

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