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

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

enabled the exit confirm dialog

  • Property mode set to 100644
File size: 128.6 KB
RevLine 
[41d466f]1
[d955bf19]2################################################################################
3#This software was developed by the University of Tennessee as part of the
4#Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
5#project funded by the US National Science Foundation.
6#
7#See the license text in license.txt
8#
9#copyright 2008, University of Tennessee
10################################################################################
[7681bac]11
[d68c655]12
[41d466f]13import wx
14import wx.aui
[32c0841]15import os
16import sys
[b0eee0f0]17import xml
[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        """
[dcb0834]2083        message = "\nDo you really want to exit this application?        \n\n"
2084        dial = wx.MessageDialog(self, message, 'Confirm Exit',
2085                           wx.YES_NO|wx.YES_DEFAULT|wx.ICON_QUESTION)
2086        if dial.ShowModal() == wx.ID_YES:
2087            return True
2088        else:
2089            return False   
[b5ca223]2090       
[41d466f]2091    def Close(self, event=None):
2092        """
[d955bf19]2093        Quit the application
[41d466f]2094        """
[390742c]2095        flag = self.quit_guiframe()
2096        if flag:
[ba535a6]2097            wx.Exit()
2098            sys.exit()
[41d466f]2099
2100    def _check_update(self, event=None): 
2101        """
[d955bf19]2102        Check with the deployment server whether a new version
2103        of the application is available.
2104        A thread is started for the connecting with the server. The thread calls
2105        a call-back method when the current version number has been obtained.
[52070a1]2106        """
[6df04e43]2107       
[d68c655]2108        if hasattr(config, "__update_URL__"):
2109            import version
[6df04e43]2110            checker = version.VersionThread2(config.__update_URL__,
[32c0841]2111                                            self._process_version,
2112                                            baggage=event==None)
[d68c655]2113            checker.start() 
[52070a1]2114   
2115    def _process_version(self, version, standalone=True):
2116        """
[d955bf19]2117        Call-back method for the process of checking for updates.
2118        This methods is called by a VersionThread object once the current
2119        version number has been obtained. If the check is being done in the
2120        background, the user will not be notified unless there's an update.
2121       
2122        :param version: version string
2123        :param standalone: True of the update is being checked in
2124           the background, False otherwise.
2125           
[52070a1]2126        """
2127        try:
[32c0841]2128            if cmp(version, config.__version__) > 0:
[6df04e43]2129                msg = "Version %s is available! See the Help " % str(version)
2130                msg += "menu to download it." 
[32c0841]2131                self.SetStatusText(msg)
[52070a1]2132                if not standalone:
2133                    import webbrowser
2134                    webbrowser.open(config.__download_page__)
2135            else:
2136                if not standalone:
[32c0841]2137                    msg = "You have the latest version"
[6df04e43]2138                    msg += " of %s" % str(config.__appname__)
[32c0841]2139                    self.SetStatusText(msg)
[41d466f]2140        except:
[32c0841]2141            msg = "guiframe: could not get latest application"
2142            msg += " version number\n  %s" % sys.exc_value
2143            logging.error(msg)
[52070a1]2144            if not standalone:
[32c0841]2145                msg = "Could not connect to the application server."
2146                msg += " Please try again later."
2147                self.SetStatusText(msg)
[52070a1]2148                   
[41d466f]2149    def _onAbout(self, evt):
2150        """
[d955bf19]2151        Pop up the about dialog
2152       
2153        :param evt: menu event
2154       
[41d466f]2155        """
2156        if config._do_aboutbox:
2157            import aboutbox 
2158            dialog = aboutbox.DialogAbout(None, -1, "")
[60c7011]2159            dialog.ShowModal()   
2160                     
2161    def _onTutorial(self, evt):
2162        """
2163        Pop up the tutorial dialog
2164       
2165        :param evt: menu event
2166       
2167        """
[075526b]2168        if config._do_tutorial:   
2169            path = config.TUTORIAL_PATH
2170            if IS_WIN:
2171                try:
[bc7bc839]2172                    from sans.guiframe.pdfview import PDFFrame
[075526b]2173                   
[bc7bc839]2174                    dialog = PDFFrame(None, -1, "Tutorial", path)
[9a56619]2175                    if hasattr(dialog, "IsIconized"):
2176                        if not dialog.IsIconized():
2177                            try:
2178                                icon = self.GetIcon()
2179                                dialog.SetIcon(icon)
2180                            except:
2181                                pass   
[075526b]2182                    #self.SetTopWindow(dialog)
2183                    dialog.Show(True) 
2184                except:
[fdb2ce2]2185                    msg = "This feature requires 'Adobe pdf Reader'\n"
2186                    msg += "Please install it first (Free)..."
[075526b]2187                    wx.MessageBox(msg, 'Error')
2188            else:
2189                try:
[be98b3d]2190                    command = "open "
[075526b]2191                    command += path
2192                    os.system(command)
2193                except:
2194                    msg = "This feature requires 'Preview' Application\n"
2195                    msg += "Please install it first..."
2196                    wx.MessageBox(msg, 'Error')
2197
[60c7011]2198                     
[41d466f]2199    def set_manager(self, manager):
2200        """
[d955bf19]2201        Sets the application manager for this frame
2202       
2203        :param manager: frame manager
[41d466f]2204        """
2205        self.app_manager = manager
2206       
2207    def post_init(self):
2208        """
[d955bf19]2209        This initialization method is called after the GUI
2210        has been created and all plug-ins loaded. It calls
2211        the post_init() method of each plug-in (if it exists)
2212        so that final initialization can be done.
[41d466f]2213        """
2214        for item in self.plugins:
2215            if hasattr(item, "post_init"):
2216                item.post_init()
2217       
[b28278e]2218    def set_default_perspective(self):
2219        """
[d955bf19]2220        Choose among the plugin the first plug-in that has
2221        "set_default_perspective" method and its return value is True will be
2222        as a default perspective when the welcome page is closed
[b28278e]2223        """
2224        for item in self.plugins:
2225            if hasattr(item, "set_default_perspective"):
2226                if item.set_default_perspective():
[749eb8a]2227                    item.on_perspective(event=None)
[b28278e]2228                    return 
[f444b20]2229       
[41d466f]2230    def set_perspective(self, panels):
2231        """
[d955bf19]2232        Sets the perspective of the GUI.
2233        Opens all the panels in the list, and closes
2234        all the others.
2235       
2236        :param panels: list of panels
[41d466f]2237        """
[adf44c2]2238        #style = self.__gui_style & GUIFRAME.TOOLBAR_ON
2239        #if (style == GUIFRAME.TOOLBAR_ON) & (not self._toolbar.IsShown()):
2240        #    self._on_toggle_toolbar()
[41d466f]2241        for item in self.panels:
2242            # Check whether this is a sticky panel
2243            if hasattr(self.panels[item], "ALWAYS_ON"):
2244                if self.panels[item].ALWAYS_ON:
2245                    continue 
[1b1bbf9]2246           
[41d466f]2247            if self.panels[item].window_name in panels:
2248                if not self._mgr.GetPane(self.panels[item].window_name).IsShown():
2249                    self._mgr.GetPane(self.panels[item].window_name).Show()
2250            else:
[3feed3e]2251                # always show the data panel if enable
2252                style = self.__gui_style & GUIFRAME.MANAGER_ON
2253                if (style == GUIFRAME.MANAGER_ON) and self.panels[item] == self._data_panel:
2254                    if 'data_panel' in self.panels.keys():
2255                        flag = self._mgr.GetPane(self.panels['data_panel'].window_name).IsShown()
2256                        self._mgr.GetPane(self.panels['data_panel'].window_name).Show(flag)
2257                else:
2258                    if self._mgr.GetPane(self.panels[item].window_name).IsShown():
2259                        self._mgr.GetPane(self.panels[item].window_name).Hide()
[1b1bbf9]2260               
[41d466f]2261        self._mgr.Update()
[4e9583c]2262       
[1b1bbf9]2263    def show_data_panel(self, event=None, action=True):
[52b8b74]2264        """
[3feed3e]2265        show the data panel
[52b8b74]2266        """
[1b1bbf9]2267        if self._data_panel_menu == None:
2268            return
[e75b5fa]2269        label = self._data_panel_menu.GetText()
[03da8ed]2270        if label == 'Show Data Explorer':
[75fbd17]2271            pane = self._mgr.GetPane(self.panels["data_panel"].window_name)
2272            #if not pane.IsShown():
[1b1bbf9]2273            if action: 
2274                pane.Show(True)
2275                self._mgr.Update()
[e75b5fa]2276            self.__gui_style = self.__gui_style | GUIFRAME.MANAGER_ON
2277           
[03da8ed]2278            self._data_panel_menu.SetText('Hide Data Explorer')
[e75b5fa]2279        else:
2280            pane = self._mgr.GetPane(self.panels["data_panel"].window_name)
2281            #if not pane.IsShown():
[1b1bbf9]2282            if action:
2283                pane.Show(False)
2284                self._mgr.Update()
[e75b5fa]2285            self.__gui_style = self.__gui_style & (~GUIFRAME.MANAGER_ON)
[03da8ed]2286            self._data_panel_menu.SetText('Show Data Explorer')
[c70eb7c]2287   
2288    def add_data_helper(self, data_list):
2289        """
2290        """
[e88ebfd]2291        if self._data_manager is not None:
2292            self._data_manager.add_data(data_list)
[c70eb7c]2293       
[75fbd17]2294    def add_data(self, data_list):
[f444b20]2295        """
[e88ebfd]2296        receive a dictionary of data from loader
2297        store them its data manager if possible
2298        send to data the current active perspective if the data panel
2299        is not active.
2300        :param data_list: dictionary of data's ID and value Data
[f444b20]2301        """
[e88ebfd]2302        #Store data into manager
2303        self.add_data_helper(data_list)
2304        # set data in the data panel
2305        if self._data_panel is not None:
2306            data_state = self._data_manager.get_data_state(data_list.keys())
2307            self._data_panel.load_data_list(data_state)
2308        #if the data panel is shown wait for the user to press a button
2309        #to send data to the current perspective. if the panel is not
2310        #show  automatically send the data to the current perspective
[3feed3e]2311        style = self.__gui_style & GUIFRAME.MANAGER_ON
2312        if style == GUIFRAME.MANAGER_ON:
[9c169f4]2313            #wait for button press from the data panel to set_data
[3feed3e]2314            if self._data_panel is not None:
2315                self._mgr.GetPane(self._data_panel.window_name).Show(True)
[9c169f4]2316                self._mgr.Update() 
[3feed3e]2317        else:
2318            #automatically send that to the current perspective
[e88ebfd]2319            self.set_data(data_id=data_list.keys())
[1b1bbf9]2320            self.on_close_welcome_panel()
[c70eb7c]2321       
[0a2fdca]2322    def set_data(self, data_id, theory_id=None): 
[c5e84fb]2323        """
[e88ebfd]2324        set data to current perspective
[c5e84fb]2325        """
[e88ebfd]2326        list_data, _ = self._data_manager.get_by_id(data_id)
2327        if self._current_perspective is not None:
[f2d9e76]2328            if self.cleanup_plots:
2329                for uid, panel in self.plot_panels.iteritems():
2330                    #panel = self.plot_panels[uid]
2331                    window = self._mgr.GetPane(panel.window_name)
2332                    # To hide all docked plot panels when set the data
2333                    if not window.IsFloating():
2334                        self.hide_panel(uid)
[f15f144d]2335            self._current_perspective.set_data(list_data.values())
[1b1bbf9]2336            self.on_close_welcome_panel()
[584c4c4]2337        else:
[e88ebfd]2338            msg = "Guiframe does not have a current perspective"
2339            logging.info(msg)
2340           
2341    def set_theory(self, state_id, theory_id=None):
[c5e84fb]2342        """
2343        """
[df22224]2344        _, list_theory = self._data_manager.get_by_id(theory_id)
[c5e84fb]2345        if self._current_perspective is not None:
2346            try:
[df22224]2347                self._current_perspective.set_theory(list_theory.values())
[c5e84fb]2348            except:
[e88ebfd]2349                msg = "Guiframe set_theory: \n" + str(sys.exc_value)
2350                logging.info(msg)
[c5e84fb]2351                wx.PostEvent(self, StatusEvent(status=msg, info="error"))
2352        else:
2353            msg = "Guiframe does not have a current perspective"
2354            logging.info(msg)
[3feed3e]2355           
[e88ebfd]2356    def plot_data(self,  state_id, data_id=None,
2357                  theory_id=None, append=False):
[f444b20]2358        """
2359        send a list of data to plot
2360        """
[d7f727d]2361        total_plot_list = []
[e88ebfd]2362        data_list, _ = self._data_manager.get_by_id(data_id)
[df22224]2363        _, temp_list_theory = self._data_manager.get_by_id(theory_id)
[d7f727d]2364        total_plot_list = data_list.values()
[df22224]2365        for item in temp_list_theory.values():
[e88ebfd]2366            theory_data, theory_state = item
[d7f727d]2367            total_plot_list.append(theory_data)
[e88ebfd]2368        GROUP_ID = wx.NewId()
[d7f727d]2369        for new_plot in total_plot_list:
[213892bc]2370            if append:
[ee2b492]2371                if self.panel_on_focus is None:
[213892bc]2372                    message = "cannot append plot. No plot panel on focus!"
2373                    message += "please click on any available plot to set focus"
2374                    wx.PostEvent(self, StatusEvent(status=message, 
2375                                                   info='warning'))
2376                    return 
2377                else:
[e88ebfd]2378                    if self.enable_add_data(new_plot):
2379                        new_plot.group_id = self.panel_on_focus.group_id
2380                    else:
[8cb8c89]2381                        message = "Only 1D Data can be append to"
2382                        message += " plot panel containing 1D data.\n"
2383                        message += "%s not be appended.\n" %str(new_plot.name)
2384                        message += "try new plot option.\n"
[e88ebfd]2385                        wx.PostEvent(self, StatusEvent(status=message, 
2386                                                   info='warning'))
[4c0572f]2387            else:
[f2d9e76]2388                if self.cleanup_plots:
2389                    for id, panel in self.plot_panels.iteritems():
2390                        window = self._mgr.GetPane(panel.window_name)
2391                        # To hide all docked plot panels when set the data
2392                        if not window.IsFloating():
2393                            self.hide_panel(id)
[4c0572f]2394                #if not append then new plot
[7c7fe67]2395                from sans.guiframe.dataFitting import Data2D
[8cb8c89]2396                if issubclass(Data2D, new_plot.__class__):
[7c7fe67]2397                    #for 2 D always plot in a separated new plot
2398                    new_plot.group_id = wx.NewId()
2399                else:
2400                    # plot all 1D in a new plot
2401                    new_plot.group_id = GROUP_ID
[e88ebfd]2402            title = "PLOT " + str(new_plot.title)
[f444b20]2403            wx.PostEvent(self, NewPlotEvent(plot=new_plot,
[f5348253]2404                                                  title=title,
2405                                                  group_id = new_plot.group_id))
[f444b20]2406           
[665c083]2407    def remove_data(self, data_id, theory_id=None):
[213892bc]2408        """
2409        Delete data state if data_id is provide
2410        delete theory created with data of id data_id if theory_id is provide
2411        if delete all true: delete the all state
2412        else delete theory
2413        """
[e26d0db]2414        temp = data_id + theory_id
[60fff67]2415        """
2416        value = [plug.is_in_use(temp) for plug in self.plugins]
2417        if len(value) > 0:
2418            print "value"
2419            return
2420            from data_panel import DataDialog
2421            dlg = DataDialog(data_list=data_list, nb_data=MAX_NBR_DATA)
2422            if dlg.ShowModal() == wx.ID_OK:
2423                selected_data_list = dlg.get_data()
2424            dlg.Destroy()
2425        """
[6db811e]2426        for plug in self.plugins:
[e26d0db]2427            plug.delete_data(temp)
[3658717e]2428        total_plot_list = []
2429        data_list, _ = self._data_manager.get_by_id(data_id)
2430        _, temp_list_theory = self._data_manager.get_by_id(theory_id)
2431        total_plot_list = data_list.values()
2432        for item in temp_list_theory.values():
2433            theory_data, theory_state = item
2434            total_plot_list.append(theory_data)
2435        for new_plot in total_plot_list:
2436            id = new_plot.id
2437            for group_id in new_plot.list_group_id:
2438                wx.PostEvent(self, NewPlotEvent(id=id,
2439                                                   group_id=group_id,
2440                                                   action='remove'))
[6a7cf2c]2441                #remove res plot: Todo: improve
[8e671c39]2442                wx.CallAfter(self._remove_res_plot, id)
[3658717e]2443        self._data_manager.delete_data(data_id=data_id, 
2444                                       theory_id=theory_id)
[ff04dfc]2445       
[6a7cf2c]2446    def _remove_res_plot(self, id):
2447        """
2448        Try to remove corresponding res plot
[213892bc]2449       
[6a7cf2c]2450        : param id: id of the data
2451        """
2452        try:
[a2da783]2453            wx.PostEvent(self, NewPlotEvent(id=("res"+str(id)),
2454                                           group_id=("res"+str(id)),
[6a7cf2c]2455                                           action='remove'))
2456        except:
2457            pass
[176fbf1]2458   
2459    def save_data1d(self, data, fname):
2460        """
2461        Save data dialog
2462        """
2463        default_name = fname
2464        wildcard = "Text files (*.txt)|*.txt|"\
2465                    "CanSAS 1D files(*.xml)|*.xml" 
2466        path = None
2467        dlg = wx.FileDialog(self, "Choose a file",
2468                            self._default_save_location,
2469                            default_name, wildcard , wx.SAVE)
2470       
2471        if dlg.ShowModal() == wx.ID_OK:
2472            path = dlg.GetPath()
2473            # ext_num = 0 for .txt, ext_num = 1 for .xml
2474            # This is MAC Fix
2475            ext_num = dlg.GetFilterIndex()
2476            if ext_num == 0:
2477                format = '.txt'
2478            else:
2479                format = '.xml'
2480            path = os.path.splitext(path)[0] + format
2481            mypath = os.path.basename(path)
2482           
2483            #TODO: This is bad design. The DataLoader is designed
2484            #to recognize extensions.
2485            # It should be a simple matter of calling the .
2486            #save(file, data, '.xml') method
2487            # of the sans.dataloader.loader.Loader class.
2488            from sans.dataloader.loader import  Loader
2489            #Instantiate a loader
2490            loader = Loader() 
2491            format = ".txt"
2492            if os.path.splitext(mypath)[1].lower() == format:
2493                # Make sure the ext included in the file name
2494                # especially on MAC
2495                fName = os.path.splitext(path)[0] + format
2496                self._onsaveTXT(data, fName)
2497            format = ".xml"
2498            if os.path.splitext(mypath)[1].lower() == format:
2499                # Make sure the ext included in the file name
2500                # especially on MAC
2501                fName = os.path.splitext(path)[0] + format
2502                loader.save(fName, data, format)
2503            try:
2504                self._default_save_location = os.path.dirname(path)
2505            except:
2506                pass   
2507        dlg.Destroy()
2508       
2509       
2510    def _onsaveTXT(self, data, path):
2511        """
2512        Save file as txt 
2513        :TODO: Refactor and remove this method. See TODO in _onSave.
2514        """
2515        if not path == None:
2516            out = open(path, 'w')
2517            has_errors = True
2518            if data.dy == None or data.dy == []:
2519                has_errors = False
2520            # Sanity check
2521            if has_errors:
2522                try:
2523                    if len(data.y) != len(data.dy):
2524                        has_errors = False
2525                except:
2526                    has_errors = False
2527            if has_errors:
2528                if data.dx != None and data.dx != []:
2529                    out.write("<X>   <Y>   <dY>   <dX>\n")
2530                else:
2531                    out.write("<X>   <Y>   <dY>\n")
2532            else:
2533                out.write("<X>   <Y>\n")
2534               
2535            for i in range(len(data.x)):
2536                if has_errors:
2537                    if data.dx != None and data.dx != []:
2538                        out.write("%g  %g  %g  %g\n" % (data.x[i], 
2539                                                    data.y[i],
2540                                                    data.dy[i],
2541                                                    data.dx[i]))
2542                    else:
2543                        out.write("%g  %g  %g\n" % (data.x[i], 
2544                                                    data.y[i],
2545                                                    data.dy[i]))
2546                else:
2547                    out.write("%g  %g\n" % (data.x[i], 
2548                                            data.y[i]))
2549            out.close()                   
2550           
2551    def save_data2d(self, data, fname):   
2552        """
2553        Save data2d dialog
2554        """
2555        default_name = fname
2556        wildcard = "IGOR/DAT 2D file in Q_map (*.dat)|*.DAT"
2557        dlg = wx.FileDialog(self, "Choose a file",
2558                            self._default_save_location,
2559                            default_name, wildcard , wx.SAVE)
2560       
2561        if dlg.ShowModal() == wx.ID_OK:
2562            path = dlg.GetPath()
2563            # ext_num = 0 for .txt, ext_num = 1 for .xml
2564            # This is MAC Fix
2565            ext_num = dlg.GetFilterIndex()
2566            if ext_num == 0:
2567                format = '.dat'
2568            else:
2569                format = ''
2570            path = os.path.splitext(path)[0] + format
2571            mypath = os.path.basename(path)
2572           
2573            #TODO: This is bad design. The DataLoader is designed
2574            #to recognize extensions.
2575            # It should be a simple matter of calling the .
2576            #save(file, data, '.xml') method
2577            # of the DataLoader.loader.Loader class.
2578            from sans.dataloader.loader import  Loader
2579            #Instantiate a loader
2580            loader = Loader() 
2581
2582            format = ".dat"
2583            if os.path.splitext(mypath)[1].lower() == format:
2584                # Make sure the ext included in the file name
2585                # especially on MAC
2586                fileName = os.path.splitext(path)[0] + format
2587                loader.save(fileName, data, format)
2588            try:
2589                self._default_save_location = os.path.dirname(path)
2590            except:
2591                pass   
2592        dlg.Destroy() 
2593                     
[f444b20]2594    def set_current_perspective(self, perspective):
2595        """
2596        set the current active perspective
2597        """
2598        self._current_perspective = perspective
[f7e9af2]2599        name = "No current analysis selected"
[cbf22e5]2600        if self._current_perspective is not None:
2601            self._add_current_plugin_menu()
[a45037aa]2602            for panel in self.panels.values():
2603                if hasattr(panel, 'CENTER_PANE') and panel.CENTER_PANE:
2604                    for name in self._current_perspective.get_perspective():
2605                        if name == panel.window_name:
2606                            panel.on_set_focus(event=None)
[fadf925]2607                            break               
[f036c692]2608            name = self._current_perspective.sub_menu
[cbf22e5]2609            if self._data_panel is not None:
2610                self._data_panel.set_active_perspective(name)
[95f9cc4]2611                self._check_applications_menu()
[1b1bbf9]2612            #Set the SansView title
2613            self._set_title_name(name)
[52f3c98]2614         
[1b1bbf9]2615           
2616    def _set_title_name(self, name):
2617        """
2618        Set the SansView title w/ the current application name
2619       
2620        : param name: application name [string]
2621        """
2622        # Set SanView Window title w/ application anme
2623        title = self.title + "  - " + name + " -"
2624        self.SetTitle(title)
2625           
[95f9cc4]2626    def _check_applications_menu(self):
2627        """
2628        check the menu of the current application
2629        """
2630        if self._applications_menu is not None:
2631            for menu in self._applications_menu.GetMenuItems():
2632                if self._current_perspective is not None:
2633                    name = self._current_perspective.sub_menu
2634                    if menu.IsCheckable():
2635                        if menu.GetLabel() == name:
2636                            menu.Check(True)
2637                        else:
2638                             menu.Check(False) 
[c5e84fb]2639           
[213892bc]2640    def set_plotpanel_floating(self, event=None):
[7a67e075]2641        """
2642        make the plot panel floatable
2643        """
[d785914]2644       
[0663dfb1]2645        self.__gui_style &= (~GUIFRAME.FIXED_PANEL)
[3feed3e]2646        self.__gui_style |= GUIFRAME.FLOATING_PANEL
[d785914]2647        plot_panel = []
[f2d9e76]2648        id = event.GetId()
2649        menu = self._window_menu.FindItemById(id)
[d785914]2650        if self._plotting_plugin is not None:
[75ea4e8]2651            plot_panel = self.plot_panels.values()
[d785914]2652            for p in plot_panel:
2653                self._popup_floating_panel(p)
[f2d9e76]2654            menu.Check(True)
2655           
[213892bc]2656    def set_plotpanel_fixed(self, event=None):
[7a67e075]2657        """
2658        make the plot panel fixed
2659        """
[0663dfb1]2660        self.__gui_style &= (~GUIFRAME.FLOATING_PANEL)
[3feed3e]2661        self.__gui_style |= GUIFRAME.FIXED_PANEL
2662        plot_panel = []
[f2d9e76]2663        id = event.GetId()
2664        menu = self._window_menu.FindItemById(id)
[3feed3e]2665        if self._plotting_plugin is not None:
[75ea4e8]2666            plot_panel = self.plot_panels.values()
[d785914]2667            for p in plot_panel:
2668                self._popup_fixed_panel(p)
[f2d9e76]2669            menu.Check(True)
2670           
2671    def on_cleanup_dock(self, event=None):     
2672        """
2673        Set Cleanup Dock option
2674        """
2675        if event == None:
2676            return
2677        id = event.GetId()
2678        menu = self._window_menu.FindItemById(id)
2679        Flag = self.cleanup_plots
2680        if not Flag:
2681            menu.Check(True)
2682            self.cleanup_plots = True
2683            msg = "Cleanup-Dock option set to 'ON'."
2684        else:
2685            menu.Check(False)
2686            self.cleanup_plots = False
2687            msg = "Cleanup-Dock option set to 'OFF'."
2688
2689        wx.PostEvent(self, StatusEvent(status= msg))
2690         
[3feed3e]2691    def _popup_fixed_panel(self, p):
2692        """
2693        """
2694        style = self.__gui_style & GUIFRAME.FIXED_PANEL
2695        if style == GUIFRAME.FIXED_PANEL:
[52f3c98]2696            self._mgr.GetPane(p.window_name).Dock()
[3feed3e]2697            self._mgr.GetPane(p.window_name).Floatable()
2698            self._mgr.GetPane(p.window_name).Right()
2699            self._mgr.GetPane(p.window_name).TopDockable(False)
2700            self._mgr.GetPane(p.window_name).BottomDockable(False)
2701            self._mgr.GetPane(p.window_name).LeftDockable(False)
2702            self._mgr.GetPane(p.window_name).RightDockable(True)
2703            self._mgr.Update()
2704           
2705    def _popup_floating_panel(self, p):
2706        """
2707        """
2708        style = self.__gui_style &  GUIFRAME.FLOATING_PANEL
2709        if style == GUIFRAME.FLOATING_PANEL: 
2710            self._mgr.GetPane(p.window_name).Floatable(True)
2711            self._mgr.GetPane(p.window_name).Float()
2712            self._mgr.GetPane(p.window_name).Dockable(False)
2713            self._mgr.Update()
[213892bc]2714           
2715    def enable_add_data(self, new_plot):
2716        """
2717        Enable append data on a plot panel
2718        """
[0a2fdca]2719
[ee2b492]2720        if self.panel_on_focus not in self._plotting_plugin.plot_panels.values():
2721            return
[213892bc]2722        is_theory = len(self.panel_on_focus.plots) <= 1 and \
2723            self.panel_on_focus.plots.values()[0].__class__.__name__ == "Theory1D"
2724           
2725        is_data2d = hasattr(new_plot, 'data')
[0a2fdca]2726       
[213892bc]2727        is_data1d = self.panel_on_focus.__class__.__name__ == "ModelPanel1D"\
2728            and self.panel_on_focus.group_id is not None
2729        has_meta_data = hasattr(new_plot, 'meta_data')
2730       
2731        #disable_add_data if the data is being recovered from  a saved state file.
2732        is_state_data = False
2733        if has_meta_data:
2734            if 'invstate' in new_plot.meta_data: is_state_data = True
2735            if  'prstate' in new_plot.meta_data: is_state_data = True
2736            if  'fitstate' in new_plot.meta_data: is_state_data = True
2737   
2738        return is_data1d and not is_data2d and not is_theory and not is_state_data
[d828481]2739   
[e4d790f]2740    def check_multimode(self, perspective=None):
2741        """
2742        Check the perspective have batch mode capablitity
2743        """
2744        if perspective == None or self._data_panel == None:
2745            return
2746        flag = perspective.get_batch_capable()
2747        flag_on = perspective.batch_on
2748        if flag:
2749            self._data_panel.rb_single_mode.SetValue(not flag_on)
2750            self._data_panel.rb_batch_mode.SetValue(flag_on)
2751        else:
2752            self._data_panel.rb_single_mode.SetValue(True)
2753            self._data_panel.rb_batch_mode.SetValue(False)
2754        self._data_panel.rb_single_mode.Enable(flag)
2755        self._data_panel.rb_batch_mode.Enable(flag)
2756               
2757
2758   
[f036c692]2759    def enable_edit_menu(self):
2760        """
2761        enable menu item under edit menu depending on the panel on focus
2762        """
[0a2fdca]2763        if self.cpanel_on_focus is not None and self._edit_menu is not None:
2764            flag = self.cpanel_on_focus.get_undo_flag()
[f036c692]2765            self._edit_menu.Enable(GUIFRAME_ID.UNDO_ID, flag)
[0a2fdca]2766            flag = self.cpanel_on_focus.get_redo_flag()
[f036c692]2767            self._edit_menu.Enable(GUIFRAME_ID.REDO_ID, flag)
[07c8630]2768            flag = self.cpanel_on_focus.get_copy_flag()
2769            self._edit_menu.Enable(GUIFRAME_ID.COPY_ID, flag)
2770            flag = self.cpanel_on_focus.get_paste_flag()
2771            self._edit_menu.Enable(GUIFRAME_ID.PASTE_ID, flag)
[3ce9937]2772            #flag = self.cpanel_on_focus.get_print_flag()
2773            #self._edit_menu.Enable(GUIFRAME_ID.PRINT_ID, flag)
[0a2fdca]2774            flag = self.cpanel_on_focus.get_preview_flag()
[f036c692]2775            self._edit_menu.Enable(GUIFRAME_ID.PREVIEW_ID, flag)
[0a2fdca]2776            flag = self.cpanel_on_focus.get_reset_flag()
[f036c692]2777            self._edit_menu.Enable(GUIFRAME_ID.RESET_ID, flag)
2778        else:
2779            flag = False
2780            self._edit_menu.Enable(GUIFRAME_ID.UNDO_ID, flag)
2781            self._edit_menu.Enable(GUIFRAME_ID.REDO_ID, flag)
[07c8630]2782            self._edit_menu.Enable(GUIFRAME_ID.COPY_ID, flag)
2783            self._edit_menu.Enable(GUIFRAME_ID.PASTE_ID, flag)
[3ce9937]2784            #self._edit_menu.Enable(GUIFRAME_ID.PRINT_ID, flag)
[f036c692]2785            self._edit_menu.Enable(GUIFRAME_ID.PREVIEW_ID, flag)
2786            self._edit_menu.Enable(GUIFRAME_ID.RESET_ID, flag)
2787           
[d828481]2788    def on_undo_panel(self, event=None):
2789        """
2790        undo previous action of the last panel on focus if possible
2791        """
[0a2fdca]2792        if self.cpanel_on_focus is not None:
2793            self.cpanel_on_focus.on_undo(event)
[f036c692]2794           
[d828481]2795    def on_redo_panel(self, event=None):
2796        """
2797        redo the last cancel action done on the last panel on focus
2798        """
[0a2fdca]2799        if self.cpanel_on_focus is not None:
2800            self.cpanel_on_focus.on_redo(event)
[f036c692]2801           
[07c8630]2802    def on_copy_panel(self, event=None):
2803        """
2804        copy the last panel on focus if possible
2805        """
2806        if self.cpanel_on_focus is not None:
2807            self.cpanel_on_focus.on_copy(event)
2808           
2809    def on_paste_panel(self, event=None):
2810        """
2811        paste clipboard to the last panel on focus
2812        """
2813        if self.cpanel_on_focus is not None:
2814            self.cpanel_on_focus.on_paste(event)
2815                   
[d828481]2816    def on_bookmark_panel(self, event=None):
2817        """
[4e4d3bb]2818        bookmark panel
[d828481]2819        """
[0a2fdca]2820        if self.cpanel_on_focus is not None:
2821            self.cpanel_on_focus.on_bookmark(event)
[f036c692]2822           
[4e4d3bb]2823    def append_bookmark(self, event=None):
2824        """
2825        Bookmark available information of the panel on focus
2826        """
2827        self._toolbar.append_bookmark(event)
2828           
[d828481]2829    def on_save_panel(self, event=None):
2830        """
2831        save possible information on the current panel
2832        """
[0a2fdca]2833        if self.cpanel_on_focus is not None:
2834            self.cpanel_on_focus.on_save(event)
[f036c692]2835           
[d828481]2836    def on_preview_panel(self, event=None):
2837        """
2838        preview information on the panel on focus
2839        """
[0a2fdca]2840        if self.cpanel_on_focus is not None:
2841            self.cpanel_on_focus.on_preview(event)
[f036c692]2842           
[d828481]2843    def on_print_panel(self, event=None):
2844        """
2845        print available information on the last panel on focus
2846        """
[0a2fdca]2847        if self.cpanel_on_focus is not None:
2848            self.cpanel_on_focus.on_print(event)
[f036c692]2849           
[d828481]2850    def on_zoom_panel(self, event=None):
2851        """
2852        zoom on the current panel if possible
2853        """
[0a2fdca]2854        if self.cpanel_on_focus is not None:
2855            self.cpanel_on_focus.on_zoom(event)
[f036c692]2856           
[d828481]2857    def on_zoom_in_panel(self, event=None):
2858        """
2859        zoom in of the panel on focus
2860        """
[0a2fdca]2861        if self.cpanel_on_focus is not None:
2862            self.cpanel_on_focus.on_zoom_in(event)
[f036c692]2863           
[d828481]2864    def on_zoom_out_panel(self, event=None):
2865        """
2866        zoom out on the panel on focus
2867        """
[0a2fdca]2868        if self.cpanel_on_focus is not None:
2869            self.cpanel_on_focus.on_zoom_out(event)
[f036c692]2870           
[d828481]2871    def on_drag_panel(self, event=None):
2872        """
2873        drag apply to the panel on focus
2874        """
[0a2fdca]2875        if self.cpanel_on_focus is not None:
2876            self.cpanel_on_focus.on_drag(event)
[f036c692]2877           
[d828481]2878    def on_reset_panel(self, event=None):
2879        """
2880        reset the current panel
2881        """
[0a2fdca]2882        if self.cpanel_on_focus is not None:
2883            self.cpanel_on_focus.on_reset(event)
[03314e7]2884           
[37c36d9]2885    def on_change_caption(self, name, old_caption, new_caption):     
2886        """
2887        Change the panel caption
2888       
2889        :param name: window_name of the pane
2890        :param old_caption: current caption [string]
2891        :param new_caption: new caption [string]
2892        """
2893        # wx.aui.AuiPaneInfo
2894        pane_info = self.get_paneinfo(name) 
2895        # update the data_panel.cb_plotpanel
2896        if 'data_panel' in self.panels.keys():
2897            # remove from data_panel combobox
2898            data_panel = self.panels["data_panel"]
2899            if data_panel.cb_plotpanel is not None:
[53cf669]2900                # Check if any panel has the same caption
2901                has_newstring = data_panel.cb_plotpanel.FindString\
2902                                                            (str(new_caption)) 
2903                caption = new_caption
2904                if has_newstring != wx.NOT_FOUND:
2905                    captions = self._get_plotpanel_captions()
2906                    # Append nummber
2907                    inc = 1
2908                    while (1):
2909                        caption = new_caption + '_%s'% str(inc)
2910                        if caption not in captions:
2911                            break
2912                        inc += 1
2913                    # notify to users
2914                    msg = "Found Same Title: Added '_%s'"% str(inc)
2915                    wx.PostEvent(self, StatusEvent(status=msg))
2916                # update data_panel cb
[37c36d9]2917                pos = data_panel.cb_plotpanel.FindString(str(old_caption)) 
2918                if pos != wx.NOT_FOUND:
[53cf669]2919                    data_panel.cb_plotpanel.SetString(pos, caption)
2920                    data_panel.cb_plotpanel.SetStringSelection(caption)
[37c36d9]2921        # update window Show menu
2922        if self._window_menu != None:
2923            for item in self._window_menu.GetMenuItems():
2924                pos = self._window_menu.FindItem(old_caption)
2925                if self._window_menu.GetLabel(pos) == str(old_caption):
[53cf669]2926                    self._window_menu.SetLabel(pos, caption)
[37c36d9]2927                break
[53cf669]2928        # New Caption
2929        pane_info.Caption(caption)
[37c36d9]2930        # update aui manager
2931        self._mgr.Update()
[53cf669]2932        return caption
[37c36d9]2933       
2934    def get_paneinfo(self, name):
2935        """
2936        Get pane Caption from window_name
2937       
2938        :param name: window_name in AuiPaneInfo
2939        : return: AuiPaneInfo of the name
2940        """
2941        return self._mgr.GetPane(name) 
2942   
[03314e7]2943    def enable_undo(self):
2944        """
2945        enable undo related control
2946        """
[0a2fdca]2947        if self.cpanel_on_focus is not None:
2948            self._toolbar.enable_undo(self.cpanel_on_focus)
[03314e7]2949           
2950    def enable_redo(self):
2951        """
2952        enable redo
2953        """
[0a2fdca]2954        if self.cpanel_on_focus is not None:
2955            self._toolbar.enable_redo(self.cpanel_on_focus)
[03314e7]2956           
[07c8630]2957    def enable_copy(self):
2958        """
2959        enable copy related control
2960        """
2961        if self.cpanel_on_focus is not None:
2962            self._toolbar.enable_copy(self.cpanel_on_focus)
2963           
2964    def enable_paste(self):
2965        """
2966        enable paste
2967        """
2968        if self.cpanel_on_focus is not None:
2969            self._toolbar.enable_paste(self.cpanel_on_focus)
2970                       
[03314e7]2971    def enable_bookmark(self):
2972        """
2973        Bookmark
2974        """
[0a2fdca]2975        if self.cpanel_on_focus is not None:
2976            self._toolbar.enable_bookmark(self.cpanel_on_focus)
[03314e7]2977           
2978    def enable_save(self):
2979        """
2980        save
2981        """
[0a2fdca]2982        if self.cpanel_on_focus is not None:
2983            self._toolbar.enable_save(self.cpanel_on_focus)
[03314e7]2984           
2985    def enable_preview(self):
2986        """
2987        preview
2988        """
[0a2fdca]2989        if self.cpanel_on_focus is not None:
2990            self._toolbar.enable_preview(self.cpanel_on_focus)
[03314e7]2991           
2992    def enable_print(self):
2993        """
2994        print
2995        """
[0a2fdca]2996        if self.cpanel_on_focus is not None:
2997            self._toolbar.enable_print(self.cpanel_on_focus)
[03314e7]2998           
2999    def enable_zoom(self):
3000        """
3001        zoom
3002        """
[0a2fdca]3003        if self.cpanel_on_focus is not None:
[03314e7]3004            self._toolbar.enable_zoom(self.panel_on_focus)
3005           
3006    def enable_zoom_in(self):
3007        """
3008        zoom in
3009        """
[0a2fdca]3010        if self.cpanel_on_focus is not None:
[03314e7]3011            self._toolbar.enable_zoom_in(self.panel_on_focus)
3012           
3013    def enable_zoom_out(self):
3014        """
3015        zoom out
3016        """
[0a2fdca]3017        if self.cpanel_on_focus is not None:
[03314e7]3018            self._toolbar.enable_zoom_out(self.panel_on_focus)
3019           
3020    def enable_drag(self, event=None):
3021        """
3022        drag
3023        """
[0a2fdca]3024        if self.cpanel_on_focus is not None:
[03314e7]3025            self._toolbar.enable_drag(self.panel_on_focus)
3026           
3027    def enable_reset(self):
3028        """
3029        reset the current panel
3030        """
[0a2fdca]3031        if self.cpanel_on_focus is not None:
[03314e7]3032            self._toolbar.enable_reset(self.panel_on_focus)
[6d727ae]3033
3034    def set_schedule_full_draw(self, panel=None, func='del'):
3035        """
3036        Add/subtract the schedule full draw list with the panel given
3037       
3038        :param panel: plot panel
3039        :param func: append or del [string]
3040        """
3041
3042        # append this panel in the schedule list if not in yet
3043        if func == 'append':
3044            if not panel in self.schedule_full_draw_list:
3045                self.schedule_full_draw_list.append(panel) 
3046        # remove this panel from schedule list
3047        elif func == 'del':
3048            if len(self.schedule_full_draw_list) > 0:
3049                if panel in self.schedule_full_draw_list:
3050                    self.schedule_full_draw_list.remove(panel)
3051
3052        # reset the schdule
3053        if len(self.schedule_full_draw_list) == 0:
3054            self.schedule = False
3055        else:
3056            self.schedule = True   
3057       
3058    def full_draw(self):
3059        """
3060        Draw the panels with axes in the schedule to full dwar list
3061        """
3062        count = len(self.schedule_full_draw_list)
3063        #if not self.schedule:
3064        if count < 1:
3065            self.set_schedule(False)
3066            return
3067        else:
3068            ind = 0
3069            # if any of the panel is shown do full_draw
3070            for panel in self.schedule_full_draw_list:
3071                ind += 1
3072                if self._mgr.GetPane(panel.window_name).IsShown():
3073                    break
3074                # otherwise, return
3075                if ind == count:
3076                    return
3077
3078        #Simple redraw only for a panel shown
3079        def f_draw(panel):
3080            """
3081            Draw A panel in the full dwar list
3082            """
[dee097b]3083            try:
3084                # This checking of GetCapture is to stop redrawing
3085                # while any panel is capture.
3086                if self.GetCapture() == None:
3087                    # draw if possible
3088                    panel.set_resizing(False)
[8d8415f]3089                    panel.Show(False)
[dee097b]3090                    panel.draw_plot()
[8d8415f]3091                   
[dee097b]3092                    # Check if the panel is not shown
3093                    if not self._mgr.GetPane(panel.window_name).IsShown():
3094                        self._mgr.GetPane(panel.window_name).Hide()
[8d8415f]3095                    else:
3096                        panel.Show(True)
[dee097b]3097            except:
3098                pass
[6d727ae]3099       
3100        # Draw all panels       
3101        map(f_draw, self.schedule_full_draw_list)
3102       
3103        # Reset the attr 
3104        if len(self.schedule_full_draw_list) == 0:
3105            self.set_schedule(False)
3106        else:
3107            self.set_schedule(True)
[de99e3e4]3108        # do not update mgr
3109        #self._mgr.Update()
[6d727ae]3110       
3111    def set_schedule(self, schedule=False): 
3112        """
3113        Set schedule
3114        """
3115        self.schedule = schedule
3116               
3117    def get_schedule(self): 
3118        """
3119        Get schedule
3120        """
3121        return self.schedule
3122   
[0a2fdca]3123    def on_set_plot_focus(self, panel):
3124        """
3125        Set focus on a plot panel
3126        """
[dee097b]3127        self.set_plot_unfocus()
[0a2fdca]3128        panel.on_set_focus(None) 
3129        # set focusing panel
3130        self.panel_on_focus = panel 
[bd60472]3131        self.set_panel_on_focus(None)
[53cf669]3132
[dee097b]3133    def set_plot_unfocus(self): 
3134        """
3135        Un focus all plot panels
3136        """
3137        for plot in self.plot_panels.values():
3138            plot.on_kill_focus(None)
3139
[6d727ae]3140    def _onDrawIdle(self, *args, **kwargs):
3141        """
3142        ReDraw with axes
3143        """
[674e945]3144        try:
3145            # check if it is time to redraw
3146            if self.GetCapture() == None:
3147                # Draw plot, changes resizing too
3148                self.full_draw()
3149        except:
3150            pass
[6d727ae]3151           
3152        # restart idle       
3153        self._redraw_idle(*args, **kwargs)
3154
3155           
3156    def _redraw_idle(self, *args, **kwargs):
3157        """
3158        Restart Idle
3159        """
3160        # restart idle   
[30ccad1]3161        self.idletimer.Restart(55*TIME_FACTOR, *args, **kwargs)
[6d727ae]3162
[3feed3e]3163       
[d828481]3164class DefaultPanel(wx.Panel, PanelBase):
[41d466f]3165    """
[d955bf19]3166    Defines the API for a panels to work with
3167    the GUI manager
[41d466f]3168    """
3169    ## Internal nickname for the window, used by the AUI manager
3170    window_name = "default"
3171    ## Name to appear on the window title bar
3172    window_caption = "Welcome panel"
3173    ## Flag to tell the AUI manager to put this panel in the center pane
3174    CENTER_PANE = True
[1b3a5a9]3175    def __init__(self, parent, *args, **kwds):
3176        wx.Panel.__init__(self, parent, *args, **kwds)
3177        PanelBase.__init__(self, parent)
[d828481]3178   
[41d466f]3179
[4753fc2]3180
[41d466f]3181# Toy application to test this Frame
3182class ViewApp(wx.App):
[d955bf19]3183    """
3184    """
[41d466f]3185    def OnInit(self):
[d955bf19]3186        """
3187        """
[957723f]3188        pos, size = self.window_placement((GUIFRAME_WIDTH, GUIFRAME_HEIGHT))
[3385795]3189        self.frame = ViewerFrame(parent=None, 
[957723f]3190                                 title=APPLICATION_NAME, 
[3385795]3191                                 pos=pos, 
[957723f]3192                                 gui_style = DEFAULT_STYLE,
[3385795]3193                                 size=size) 
[7a955a9]3194        self.frame.Hide()
[957723f]3195        self.s_screen = None
[e9f6979]3196
[1eae432]3197        try:
[19b5c5c9]3198            self.open_file()
3199        except:
3200            msg = "%s Could not load " % str(APPLICATION_NAME)
3201            msg += "input file from command line.\n"
3202            logging.error(msg)
[957723f]3203        # Display a splash screen on top of the frame.
[3385795]3204        if len(sys.argv) > 1 and '--time' in sys.argv[1:]:
3205            log_time("Starting to display the splash screen")
[957723f]3206        try:
3207            if os.path.isfile(SPLASH_SCREEN_PATH):
3208                self.s_screen = self.display_splash_screen(parent=self.frame, 
3209                                        path=SPLASH_SCREEN_PATH)
3210            else:
3211                self.frame.Show()   
3212        except:
[7a955a9]3213            if self.s_screen is not None:
3214                self.s_screen.Close()
3215            msg = "Cannot display splash screen\n"
3216            msg += str (sys.exc_value)
3217            logging.error(msg)
3218            self.frame.Show()
[19b5c5c9]3219 
[41d466f]3220        if hasattr(self.frame, 'special'):
3221            self.frame.special.SetCurrent()
3222        self.SetTopWindow(self.frame)
[19b5c5c9]3223 
[41d466f]3224        return True
[b46b1b9]3225
[957723f]3226    def open_file(self):
3227        """
3228        open a state file at the start of the application
3229        """
[c3f697e]3230        input_file = None
3231        if len(sys.argv) >= 2:
3232            cmd = sys.argv[0].lower()
[19b5c5c9]3233            basename  = os.path.basename(cmd)
3234            app_base = str(APPLICATION_NAME).lower()
3235            if os.path.isfile(cmd) or basename.lower() == app_base:
3236                app_py = app_base + '.py'
3237                app_exe = app_base + '.exe'
3238                app_app = app_base + '.app'
3239                if basename.lower() in [app_py, app_exe, app_app, app_base]:
[204d0fa]3240                    data_base = sys.argv[1]
3241                    input_file = os.path.normpath(os.path.join(DATAPATH, 
3242                                                               data_base))
[c3f697e]3243        if input_file is None:
3244            return
[976604d]3245        if self.frame is not None:
[29ef718]3246            self.frame.set_input_file(input_file=input_file)
[1b1bbf9]3247         
3248           
[41d466f]3249    def set_manager(self, manager):
3250        """
[d955bf19]3251        Sets a reference to the application manager
3252        of the GUI manager (Frame)
[41d466f]3253        """
3254        self.frame.set_manager(manager)
3255       
[278cc25]3256    def build_gui(self):
3257        """
[d955bf19]3258        Build the GUI
[278cc25]3259        """
[976604d]3260        #try to load file at the start
3261        try:
3262            self.open_file()
3263        except:
3264            raise
[29ef718]3265        self.frame.build_gui()
[7a955a9]3266        #if self.s_screen is not None and self.s_screen.IsShown():
3267        #    self.s_screen.Close()
[278cc25]3268       
[f9e803e]3269    def set_welcome_panel(self, panel_class):
3270        """
[d955bf19]3271        Set the welcome panel
3272       
3273        :param panel_class: class of the welcome panel to be instantiated
3274       
[f9e803e]3275        """
3276        self.frame.set_welcome_panel(panel_class)
3277       
[278cc25]3278    def add_perspective(self, perspective):
3279        """
[d955bf19]3280        Manually add a perspective to the application GUI
[278cc25]3281        """
3282        self.frame.add_perspective(perspective)
[3385795]3283   
3284    def window_placement(self, size):
3285        """
3286        Determines the position and size of the application frame such that it
3287        fits on the user's screen without obstructing (or being obstructed by)
3288        the Windows task bar.  The maximum initial size in pixels is bounded by
3289        WIDTH x HEIGHT.  For most monitors, the application
3290        will be centered on the screen; for very large monitors it will be
3291        placed on the left side of the screen.
3292        """
3293        window_width, window_height = size
3294        screen_size = wx.GetDisplaySize()
[2edc8eb]3295        window_height = window_height if screen_size[1]>window_height else screen_size[1]-10
3296        window_width  = window_width if screen_size[0]> window_width else screen_size[0]-10
[3385795]3297        xpos = ypos = 0
3298
3299        # Note that when running Linux and using an Xming (X11) server on a PC
3300        # with a dual  monitor configuration, the reported display size may be
3301        # that of both monitors combined with an incorrect display count of 1.
3302        # To avoid displaying this app across both monitors, we check for
3303        # screen 'too big'.  If so, we assume a smaller width which means the
3304        # application will be placed towards the left hand side of the screen.
3305
3306        _, _, x, y = wx.Display().GetClientArea() # size excludes task bar
3307        if len(sys.argv) > 1 and '--platform' in sys.argv[1:]:
3308            w, h = wx.DisplaySize()  # size includes task bar area
[491525f]3309        # display on left side, not centered on screen
3310        if x > 1920 and x > (2*y): x = x / 2 
[3385795]3311        if x > window_width:  xpos = (x - window_width)/2
3312        if y > window_height: ypos = (y - window_height)/2
3313
3314        # Return the suggested position and size for the application frame.
3315        return (xpos, ypos), (min(x, window_width), min(y, window_height))
3316   
[783940c]3317    def display_splash_screen(self, parent, 
[957723f]3318                              path=SPLASH_SCREEN_PATH):
[3385795]3319        """Displays the splash screen.  It will exactly cover the main frame."""
[957723f]3320       
[3385795]3321        # Prepare the picture.  On a 2GHz intel cpu, this takes about a second.
3322        x, y = parent.GetSizeTuple()
3323        image = wx.Image(path, wx.BITMAP_TYPE_PNG)
[957723f]3324        image.Rescale(SPLASH_SCREEN_WIDTH, 
3325                      SPLASH_SCREEN_HEIGHT, wx.IMAGE_QUALITY_HIGH)
[3385795]3326        bm = image.ConvertToBitmap()
3327
3328        # Create and show the splash screen.  It will disappear only when the
3329        # program has entered the event loop AND either the timeout has expired
3330        # or the user has left clicked on the screen.  Thus any processing
3331        # performed in this routine (including sleeping) or processing in the
3332        # calling routine (including doing imports) will prevent the splash
3333        # screen from disappearing.
3334        #
3335        # Note that on Linux, the timeout appears to occur immediately in which
3336        # case the splash screen disappears upon entering the event loop.
[783940c]3337        s_screen = wx.SplashScreen(bitmap=bm,
3338                         splashStyle=(wx.SPLASH_TIMEOUT|
3339                                              wx.SPLASH_CENTRE_ON_SCREEN),
3340                                 style=(wx.SIMPLE_BORDER|
3341                                        wx.FRAME_NO_TASKBAR|
3342                                        wx.STAY_ON_TOP),
3343                                       
[957723f]3344                        milliseconds=SS_MAX_DISPLAY_TIME,
[3385795]3345                        parent=parent,
3346                        id=wx.ID_ANY)
[7a955a9]3347        from gui_statusbar import SPageStatusbar
3348        statusBar = SPageStatusbar(s_screen)
3349        s_screen.SetStatusBar(statusBar)
[783940c]3350        s_screen.Bind(wx.EVT_CLOSE, self.on_close_splash_screen)
3351        s_screen.Show()
3352        return s_screen
3353       
3354       
3355    def on_close_splash_screen(self, event):
3356        """
3357        """
3358        self.frame.Show(True)
3359        event.Skip()
[6df04e43]3360
[41d466f]3361if __name__ == "__main__": 
3362    app = ViewApp(0)
[32c0841]3363    app.MainLoop()
3364
3365             
Note: See TracBrowser for help on using the repository browser.