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

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 aac129aa was 3ee8a49, checked in by Mathieu Doucet <doucetm@…>, 13 years ago

trying to fix windows installer

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