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

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

committing print statement for debugging

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