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

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 41b1805 was ef67145, checked in by Jae Cho <jhjcho@…>, 12 years ago

added cat modify button

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