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

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

trying to improve the status bar

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