source: sasview/guiframe/gui_manager.py @ 559d055

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 559d055 was 19b5c5c9, checked in by Jae Cho <jhjcho@…>, 13 years ago

made changes to fit the implementation of SANSVIEWPATH env.

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