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

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

bring the Grid to the top every time opening from the menu bar

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