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

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

removed raise in custom config setting

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