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

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 aa07420 was aa07420, checked in by Mathieu Doucet <doucetm@…>, 12 years ago

put back sys.path[0]

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