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

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 850525c was 850525c, checked in by Gervaise Alina <gervyh@…>, 13 years ago

working data processor

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