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

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

readjusted the draw idle time for large graph

  • Property mode set to 100644
File size: 133.5 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            if self._toolbar is not None:
632                self._toolbar.update_toolbar(None)
633            p_panel.on_set_focus(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        Helping to update the toolbar
1161        """
1162        application_name = 'No Selected Analysis'
1163        panel_name = 'No Panel on Focus'
1164        c_panel = self.cpanel_on_focus
1165        if self._toolbar is  None:
1166            return
1167        if c_panel is not None:
1168            self.reset_bookmark_menu(self.cpanel_on_focus)
1169        if self._current_perspective is not None:
1170            application_name = self._current_perspective.sub_menu
1171        c_panel_state = c_panel
1172        if c_panel is not None:
1173            panel_name = c_panel.window_caption
1174            if not c_panel.IsShownOnScreen():
1175                c_panel_state = None
1176        self._toolbar.update_toolbar(c_panel_state)
1177        self._toolbar.update_button(application_name=application_name, 
1178                                        panel_name=panel_name)
1179        self._toolbar.Realize()
1180       
1181    def _add_menu_tool(self):
1182        """
1183        Tools menu
1184        Go through plug-ins and find tools to populate the tools menu
1185        """
1186        style = self.__gui_style & GUIFRAME.CALCULATOR_ON
1187        if style == GUIFRAME.CALCULATOR_ON:
1188            self._tool_menu = None
1189            for item in self.plugins:
1190                if hasattr(item, "get_tools"):
1191                    for tool in item.get_tools():
1192                        # Only create a menu if we have at least one tool
1193                        if self._tool_menu is None:
1194                            self._tool_menu = wx.Menu()
1195                        if tool[0].lower().count('python') > 0:
1196                            self._tool_menu.AppendSeparator()
1197                        id = wx.NewId()
1198                        self._tool_menu.Append(id, tool[0], tool[1])
1199                        wx.EVT_MENU(self, id, tool[2])
1200            if self._tool_menu is not None:
1201                self._menubar.Append(self._tool_menu, '&Tool')
1202               
1203    def _add_current_plugin_menu(self):
1204        """
1205        add current plugin menu
1206        Look for plug-in menus
1207        Add available plug-in sub-menus.
1208        """
1209        if (self._menubar is None) or (self._current_perspective is None):
1210            return
1211        #replace or add a new menu for the current plugin
1212       
1213        pos = self._menubar.FindMenu(str(self._applications_menu_name))
1214        if pos != -1:
1215            menu_list = self._current_perspective.populate_menu(self)
1216            if menu_list:
1217                for (menu, name) in menu_list:
1218                    hidden_menu = self._menubar.Replace(pos, menu, name) 
1219                    self._applications_menu_name = name
1220                #self._applications_menu_pos = pos
1221            else:
1222                hidden_menu = self._menubar.Remove(pos)
1223                self._applications_menu_name = None
1224            #get the position of the menu when it first added
1225            self._applications_menu_pos = pos
1226           
1227        else:
1228            menu_list = self._current_perspective.populate_menu(self)
1229            if menu_list:
1230                for (menu,name) in menu_list:
1231                    if self._applications_menu_pos == -1:
1232                        self._menubar.Append(menu, name)
1233                    else:
1234                        self._menubar.Insert(self._applications_menu_pos, menu, name)
1235                    self._applications_menu_name = name
1236                 
1237    def _add_help_menu(self):
1238        """
1239        add help menu
1240        """
1241        # Help menu
1242        self._help_menu = wx.Menu()
1243        style = self.__gui_style & GUIFRAME.WELCOME_PANEL_ON
1244        if style == GUIFRAME.WELCOME_PANEL_ON or custom_config != None:
1245            # add the welcome panel menu item
1246            if config.WELCOME_PANEL_ON and self.defaultPanel is not None:
1247                id = wx.NewId()
1248                self._help_menu.Append(id, '&Welcome', '')
1249                self._help_menu.AppendSeparator()
1250                wx.EVT_MENU(self, id, self.show_welcome_panel)
1251        # Look for help item in plug-ins
1252        for item in self.plugins:
1253            if hasattr(item, "help"):
1254                id = wx.NewId()
1255                self._help_menu.Append(id,'&%s Help' % item.sub_menu, '')
1256                wx.EVT_MENU(self, id, item.help)
1257        if config._do_tutorial and (IS_WIN or sys.platform =='darwin'):
1258            self._help_menu.AppendSeparator()
1259            id = wx.NewId()
1260            self._help_menu.Append(id,'&Tutorial', 'Software tutorial')
1261            wx.EVT_MENU(self, id, self._onTutorial)
1262           
1263        if config._do_aboutbox:
1264            self._help_menu.AppendSeparator()
1265            id = wx.NewId()
1266            self._help_menu.Append(id,'&About', 'Software information')
1267            wx.EVT_MENU(self, id, self._onAbout)
1268       
1269        # Checking for updates
1270        id = wx.NewId()
1271        self._help_menu.Append(id,'&Check for update', 
1272         'Check for the latest version of %s' % config.__appname__)
1273        wx.EVT_MENU(self, id, self._check_update)
1274        self._menubar.Append(self._help_menu, '&Help')
1275           
1276    def _add_menu_view(self):
1277        """
1278        add menu items under view menu
1279        """
1280        if not VIEW_MENU:
1281            return
1282        self._view_menu = wx.Menu()
1283        style = self.__gui_style & GUIFRAME.MANAGER_ON
1284        id = wx.NewId()
1285        self._data_panel_menu = self._view_menu.Append(id,
1286                                                '&Show Data Explorer', '')
1287        wx.EVT_MENU(self, id, self.show_data_panel)
1288        if style == GUIFRAME.MANAGER_ON:
1289            self._data_panel_menu.SetText('Hide Data Explorer')
1290        else:
1291            self._data_panel_menu.SetText('Show Data Explorer')
1292 
1293        self._view_menu.AppendSeparator()
1294        id = wx.NewId()
1295        style1 = self.__gui_style & GUIFRAME.TOOLBAR_ON
1296        if style1 == GUIFRAME.TOOLBAR_ON:
1297            self._toolbar_menu = self._view_menu.Append(id,'&Hide Toolbar', '')
1298        else:
1299            self._toolbar_menu = self._view_menu.Append(id,'&Show Toolbar', '')
1300        wx.EVT_MENU(self, id, self._on_toggle_toolbar)
1301                   
1302        self._view_menu.AppendSeparator()
1303        id = wx.NewId()
1304        hint = "Display batch results into a grid"
1305        self._view_menu.Append(id, '&Show Batch Results', hint) 
1306        wx.EVT_MENU(self, id, self.show_batch_frame)
1307
1308        if custom_config != None:
1309            self._view_menu.AppendSeparator()
1310            id = wx.NewId()
1311            preference_menu = self._view_menu.Append(id,'Startup Setting', '')
1312            wx.EVT_MENU(self, id, self._on_preference_menu)
1313           
1314        self._menubar.Append(self._view_menu, '&View')   
1315         
1316    def show_batch_frame(self, event=None):
1317        """
1318        show the grid of result
1319        """
1320        # Show(False) before Show(True) in order to bring it to the front
1321        self.batch_frame.Show(False)
1322        self.batch_frame.Show(True)
1323       
1324    def _on_preference_menu(self, event):     
1325        """
1326        Build a panel to allow to edit Mask
1327        """
1328       
1329        from sans.guiframe.startup_configuration \
1330        import StartupConfiguration as ConfDialog
1331       
1332        self.panel = ConfDialog(parent=self, gui=self.__gui_style)
1333        self.panel.ShowModal()
1334        #wx.PostEvent(self.parent, event)
1335       
1336
1337    def _add_menu_window(self):
1338        """
1339        add a menu window to the menu bar
1340        Window menu
1341        Attach a menu item for each panel in our
1342        panel list that also appears in a plug-in.
1343       
1344        Only add the panel menu if there is only one perspective and
1345        it has more than two panels.
1346        Note: the first plug-in is always the plotting plug-in.
1347        The first application
1348        #plug-in is always the second one in the list.
1349        """
1350        self._window_menu = wx.Menu()
1351        if self._plotting_plugin is not None:
1352            for (menu, name) in self._plotting_plugin.populate_menu(self):
1353                self._window_menu.AppendSubMenu(menu, name)
1354        self._menubar.Append(self._window_menu, '&Graph')
1355
1356        style = self.__gui_style & GUIFRAME.PLOTTING_ON
1357        if style == GUIFRAME.PLOTTING_ON:
1358           
1359            self._window_menu.AppendSeparator()
1360            id = wx.NewId()
1361            hint = "Hide all the graph panels"
1362            self._window_menu.Append(id, '&Hide  All', hint)
1363            wx.EVT_MENU(self, id, self.hide_all_plotpanels)
1364            id = wx.NewId()
1365            hint = "Show all the graph panels"
1366            self._window_menu.Append(id, '&Show All', hint)
1367            wx.EVT_MENU(self, id, self.show_all_plotpanels)
1368           
1369            self._window_menu.AppendSeparator()
1370            id = wx.NewId()
1371            preferences_menu = wx.Menu()
1372            hint = "All plot panels will floating"
1373            preferences_menu.AppendRadioItem(id, '&Float All', hint)
1374            wx.EVT_MENU(self, id, self.set_plotpanel_floating)
1375            style = self.__gui_style & GUIFRAME.FLOATING_PANEL
1376            f_menu = preferences_menu.FindItemById(id)
1377            if style == GUIFRAME.FLOATING_PANEL: 
1378                f_checked = True
1379            else:
1380                f_checked = False
1381            f_menu.Check(f_checked)
1382
1383            id = wx.NewId()
1384            hint = "All plot panels will displayed within the frame"
1385            preferences_menu.AppendRadioItem(id, '&Dock All', hint)
1386            wx.EVT_MENU(self, id, self.set_plotpanel_fixed) 
1387            if not f_checked:
1388                d_menu = preferences_menu.FindItemById(id)
1389                d_menu.Check(True)
1390            preferences_menu.AppendSeparator()
1391            id = wx.NewId()
1392            hint = "Clean up the dock area for plots on new-plot"
1393            preferences_menu.AppendCheckItem(id, '&CleanUp Dock on NewPlot', hint)
1394            wx.EVT_MENU(self, id, self.on_cleanup_dock)
1395            flag = self.cleanup_plots
1396            if self.cleanup_plots:
1397                c_menu = preferences_menu.FindItemById(id)
1398                c_menu.Check(True) 
1399            self._window_menu.AppendSubMenu(preferences_menu,'&Preferences')
1400        if self._window_menu.GetMenuItemCount() == 0:
1401            pos = self._menubar.FindMenu('Graph')
1402            self._menubar.Remove(pos)
1403        #wx.EVT_MENU(self, id, self.show_preferences_panel)   
1404        """
1405        if len(self.plugins) == 2:
1406            plug = self.plugins[1]
1407            pers = plug.get_perspective()
1408       
1409            if len(pers) > 1:
1410                self._window_menu = wx.Menu()
1411                for item in self.panels:
1412                    if item == 'default':
1413                        continue
1414                    panel = self.panels[item]
1415                    if panel.window_name in pers:
1416                        self._window_menu.Append(int(item),
1417                                                  panel.window_caption,
1418                                        "Show %s window" % panel.window_caption)
1419                        wx.EVT_MENU(self, int(item), self.on_view)
1420                self._menubar.Append(self._window_menu, '&Window')
1421                """
1422
1423               
1424    def _add_menu_application(self):
1425        """
1426       
1427        # Attach a menu item for each defined perspective or application.
1428        # Only add the perspective menu if there are more than one perspectives
1429        add menu application
1430        """
1431        #style = self.__gui_style & GUIFRAME.MULTIPLE_APPLICATIONS
1432        #if style == GUIFRAME.MULTIPLE_APPLICATIONS:
1433        if self._num_perspectives  > 1:
1434            plug_data_count = False
1435            plug_no_data_count = False
1436            self._applications_menu = wx.Menu()
1437            pos = 0
1438            separator = self._applications_menu.AppendSeparator()
1439            for plug in self.plugins:
1440                if len(plug.get_perspective()) > 0:
1441                    id = wx.NewId()
1442                    if plug.use_data():
1443                       
1444                        self._applications_menu.InsertCheckItem(pos, id, plug.sub_menu,
1445                                      "Switch to analysis: %s" % plug.sub_menu)
1446                        plug_data_count = True
1447                        pos += 1
1448                    else:
1449                        plug_no_data_count = True
1450                        self._applications_menu.AppendCheckItem(id, plug.sub_menu,
1451                                      "Switch to analysis: %s" % plug.sub_menu)
1452                    wx.EVT_MENU(self, id, plug.on_perspective)
1453            #self._applications_menu.
1454            if (not plug_data_count or not plug_no_data_count):
1455                self._applications_menu.RemoveItem(separator)
1456            self._menubar.Append(self._applications_menu, '&Analysis')
1457            self._check_applications_menu()
1458           
1459    def _populate_file_menu(self):
1460        """
1461        Insert menu item under file menu
1462        """
1463        for plugin in self.plugins:
1464            if len(plugin.populate_file_menu()) > 0:
1465                for item in plugin.populate_file_menu():
1466                    m_name, m_hint, m_handler = item
1467                    id = wx.NewId()
1468                    self._file_menu.Append(id, m_name, m_hint)
1469                    wx.EVT_MENU(self, id, m_handler)
1470                self._file_menu.AppendSeparator()
1471               
1472    def _add_menu_file(self):
1473        """
1474        add menu file
1475        """
1476       
1477         # File menu
1478        self._file_menu = wx.Menu()
1479        #append item from plugin under menu file if necessary
1480        self._populate_file_menu()
1481        style = self.__gui_style & GUIFRAME.DATALOADER_ON
1482        style1 = self.__gui_style & GUIFRAME.MULTIPLE_APPLICATIONS
1483        if OPEN_SAVE_MENU:
1484            id = wx.NewId()
1485            hint_load_file = "read all analysis states saved previously"
1486            self._save_appl_menu = self._file_menu.Append(id, 
1487                                    '&Open Project', hint_load_file)
1488            wx.EVT_MENU(self, id, self._on_open_state_project)
1489           
1490        if style1 == GUIFRAME.MULTIPLE_APPLICATIONS:
1491            # some menu of plugin to be seen under file menu
1492            hint_load_file = "Read a status files and load"
1493            hint_load_file += " them into the analysis"
1494            id = wx.NewId()
1495            self._save_appl_menu = self._file_menu.Append(id, 
1496                                    '&Open Analysis', hint_load_file)
1497            wx.EVT_MENU(self, id, self._on_open_state_application)
1498        if OPEN_SAVE_MENU:       
1499            self._file_menu.AppendSeparator()
1500            id = wx.NewId()
1501            self._file_menu.Append(id, '&Save Project',
1502                                 'Save the state of the whole analysis')
1503            wx.EVT_MENU(self, id, self._on_save_project)
1504        if style1 == GUIFRAME.MULTIPLE_APPLICATIONS:
1505            #self._file_menu.AppendSeparator()
1506            id = wx.NewId()
1507            self._save_appl_menu = self._file_menu.Append(id, 
1508                                                      '&Save Analysis',
1509                        'Save state of the current active analysis panel')
1510            wx.EVT_MENU(self, id, self._on_save_application)
1511            self._file_menu.AppendSeparator()
1512       
1513        id = wx.NewId()
1514        self._file_menu.Append(id, '&Quit', 'Exit') 
1515        wx.EVT_MENU(self, id, self.Close)
1516        # Add sub menus
1517        self._menubar.Append(self._file_menu, '&File')
1518       
1519    def _add_menu_edit(self):
1520        """
1521        add menu edit
1522        """
1523        if not EDIT_MENU:
1524            return
1525        # Edit Menu
1526        self._edit_menu = wx.Menu()
1527        self._edit_menu.Append(GUIFRAME_ID.UNDO_ID, '&Undo', 
1528                               'Undo the previous action')
1529        wx.EVT_MENU(self, GUIFRAME_ID.UNDO_ID, self.on_undo_panel)
1530        self._edit_menu.Append(GUIFRAME_ID.REDO_ID, '&Redo', 
1531                               'Redo the previous action')
1532        wx.EVT_MENU(self, GUIFRAME_ID.REDO_ID, self.on_redo_panel)
1533        self._edit_menu.AppendSeparator()
1534        self._edit_menu.Append(GUIFRAME_ID.COPY_ID, '&Copy Params', 
1535                               'Copy parameter values')
1536        wx.EVT_MENU(self, GUIFRAME_ID.COPY_ID, self.on_copy_panel)
1537        self._edit_menu.Append(GUIFRAME_ID.PASTE_ID, '&Paste Params', 
1538                               'Paste parameter values')
1539        wx.EVT_MENU(self, GUIFRAME_ID.PASTE_ID, self.on_paste_panel)
1540        self._edit_menu.AppendSeparator()
1541       
1542        self._edit_menu.Append(GUIFRAME_ID.PREVIEW_ID, '&Report Results',
1543                               'Preview current panel')
1544        wx.EVT_MENU(self, GUIFRAME_ID.PREVIEW_ID, self.on_preview_panel)
1545        #self._edit_menu.Append(GUIFRAME_ID.PRINT_ID, '&Print',
1546        #                       'Print current panel')
1547        #wx.EVT_MENU(self, GUIFRAME_ID.PRINT_ID, self.on_print_panel)
1548        self._edit_menu.Append(GUIFRAME_ID.RESET_ID, '&Reset Page', 
1549                               'Reset current panel')
1550        wx.EVT_MENU(self, GUIFRAME_ID.RESET_ID, self.on_reset_panel)
1551   
1552        self._menubar.Append(self._edit_menu,  '&Edit')
1553        self.enable_edit_menu()
1554       
1555    def get_style(self):
1556        """
1557        """
1558        return  self.__gui_style
1559   
1560    def _add_menu_data(self):
1561        """
1562        Add menu item item data to menu bar
1563        """
1564        if self._data_plugin is not None:
1565            menu_list = self._data_plugin.populate_menu(self)
1566            if menu_list:
1567                for (menu, name) in menu_list:
1568                    self._menubar.Append(menu, name)
1569       
1570                       
1571    def _on_toggle_toolbar(self, event=None):
1572        """
1573        hide or show toolbar
1574        """
1575        if self._toolbar is None:
1576            return
1577        if self._toolbar.IsShown():
1578            if self._toolbar_menu is not None:
1579                self._toolbar_menu.SetItemLabel('Show Toolbar')
1580            self._toolbar.Hide()
1581        else:
1582            if self._toolbar_menu is not None:
1583                self._toolbar_menu.SetItemLabel('Hide Toolbar')
1584            self._toolbar.Show()
1585        self._toolbar.Realize()
1586       
1587    def _on_status_event(self, evt):
1588        """
1589        Display status message
1590        """
1591        # This CallAfter fixes many crashes on MAC.
1592        wx.CallAfter(self.sb.set_status, evt)
1593       
1594    def on_view(self, evt):
1595        """
1596        A panel was selected to be shown. If it's not already
1597        shown, display it.
1598       
1599        :param evt: menu event
1600       
1601        """
1602        panel_id = str(evt.GetId())
1603        self.on_set_plot_focus(self.panels[panel_id])
1604        self.show_panel(evt.GetId(), 'on')     
1605        wx.CallLater(5*TIME_FACTOR, self.set_schedule(True))
1606        self.set_plot_unfocus()
1607       
1608    def on_close_welcome_panel(self):
1609        """
1610        Close the welcome panel
1611        """
1612        if self.defaultPanel is None:
1613            return 
1614        default_panel = self._mgr.GetPane(self.panels["default"].window_name)
1615        if default_panel.IsShown():
1616            default_panel.Hide()
1617            # Recover current perspective
1618            perspective = self._current_perspective
1619            perspective.on_perspective(event=None)
1620            self._mgr.Update()
1621            # Show toolbar
1622            #style = self.__gui_style & GUIFRAME.TOOLBAR_ON
1623            #if (style == GUIFRAME.TOOLBAR_ON) & (not self._toolbar.IsShown()):
1624            #    self._on_toggle_toolbar()
1625           
1626    def show_welcome_panel(self, event):
1627        """   
1628        Display the welcome panel
1629        """
1630        if self.defaultPanel is None:
1631            return 
1632        for id, panel in self.panels.iteritems():
1633            if id  ==  'default':
1634                # Show default panel
1635                if not self._mgr.GetPane(self.panels["default"].window_name).IsShown():
1636                    self._mgr.GetPane(self.panels["default"].window_name).Show(True)
1637            elif id == "data_panel":
1638                flag = self._mgr.GetPane(self.panels["data_panel"].window_name).IsShown()
1639                self._mgr.GetPane(self.panels["data_panel"].window_name).Show(flag)
1640            elif panel not in self.plot_panels.values() :
1641                self._mgr.GetPane(self.panels[id].window_name).IsShown()
1642                self._mgr.GetPane(self.panels[id].window_name).Hide()
1643        #style = self.__gui_style & GUIFRAME.TOOLBAR_ON
1644        #if (style == GUIFRAME.TOOLBAR_ON) & (self._toolbar.IsShown()):
1645        #    #    self._toolbar.Show(True)
1646        #    self._on_toggle_toolbar()
1647
1648        self._mgr.Update()
1649       
1650    def show_panel(self, uid, show=None):
1651        """
1652        Shows the panel with the given id
1653       
1654        :param uid: unique ID number of the panel to show
1655       
1656        """
1657        ID = str(uid)
1658        config.printEVT("show_panel: %s" % ID)
1659        if ID in self.panels.keys():
1660            if not self._mgr.GetPane(self.panels[ID].window_name).IsShown(): 
1661                if show == 'on':
1662                    self._mgr.GetPane(self.panels[ID].window_name).Show()   
1663                elif self.panels[ID].window_caption.split(" ")[0] == \
1664                                                            "Residuals":
1665                    self._mgr.GetPane(self.panels[ID].window_name).Hide()
1666                else:
1667                    self._mgr.GetPane(self.panels[ID].window_name).Show()
1668                # Hide default panel
1669                self._mgr.GetPane(self.panels["default"].window_name).Hide()
1670        self._mgr.Update()     
1671        self._redraw_idle()
1672
1673    def show_all_plotpanels(self, event):
1674        """
1675        Show all plotpanels shown
1676       
1677        :param event: menu event
1678        """
1679        #event.Skip()
1680        any_hidden = False
1681        for id in self.plot_panels.keys():
1682            if self._mgr.GetPane(self.plot_panels[id].window_name).IsShown():
1683                continue
1684            else:
1685                any_hidden = True
1686                self.show_panel(id)
1687        if not any_hidden:
1688            msg = "No hidden graph panel exists."
1689        else:
1690            # Make sure the Checkmenuitem checked: Need this for-loop \
1691            # because the check menu is not responding on floating panel
1692            if IS_WIN:
1693                try:
1694                    for item in self._plotting_plugin.menu.GetMenuItems():
1695                        item.Check(True)
1696                except:
1697                    # MAC is not using checkmenuitem
1698                    pass
1699            msg = "All graph panels are shown."
1700        wx.PostEvent(self, StatusEvent(status=msg))
1701           
1702    def hide_all_plotpanels(self, event):
1703        """
1704        Hide all plotpanels shown
1705       
1706        :param event: menu event
1707        """
1708        #event.Skip()
1709        any_shown = False
1710        for ID in self.plot_panels.keys():
1711            if self._mgr.GetPane(self.plot_panels[ID].window_name).IsShown():
1712                any_shown = True
1713                try:
1714                    self.hide_panel(ID)
1715                except:
1716                    print "hide_panel: No such plot id %s" % ID
1717            else:
1718                continue
1719        if not any_shown:
1720            msg = "No shown graph panel exists."
1721        else:
1722            # Make sure the Checkmenuitem unchecked: Need this for-loop
1723            # because the check menu is not responding on floating panel
1724            if IS_WIN:
1725                try:
1726                    for item in self._plotting_plugin.menu.GetMenuItems():
1727                        item.Check(False)
1728                except:
1729                    # MAC is not using checkmenuitem
1730                    pass
1731            msg = "All graph panels are hidden."
1732        wx.PostEvent(self, StatusEvent(status=msg))
1733                   
1734    def hide_panel(self, uid):
1735        """
1736        hide panel except default panel
1737        """
1738        ID = str(uid)
1739        caption = self.panels[ID].window_caption
1740        config.printEVT("hide_panel: %s" % ID)
1741        if ID in self.panels.keys():
1742            if self._mgr.GetPane(self.panels[ID].window_name).IsShown():
1743                self._mgr.GetPane(self.panels[ID].window_name).Hide()
1744                if self._data_panel is not None and \
1745                            ID in self.plot_panels.keys():
1746                    self._data_panel.cb_plotpanel.Append(str(caption), p)
1747                # Do not Hide default panel here...
1748                #self._mgr.GetPane(self.panels["default"].window_name).Hide()
1749            self._mgr.Update()
1750               
1751    def delete_panel(self, uid):
1752        """
1753        delete panel given uid
1754        """
1755        ID = str(uid)
1756        config.printEVT("delete_panel: %s" % ID)
1757        try:
1758            caption = self.panels[ID].window_caption
1759        except:
1760            print "delete_panel: No such plot id as %s" % ID
1761            return
1762        if ID in self.panels.keys():
1763            self.panel_on_focus = None
1764            panel = self.panels[ID]
1765            self._mgr.DetachPane(panel)
1766            self._plotting_plugin.delete_panel(panel.group_id)
1767            panel.Hide()
1768            panel.clear()
1769            panel.Close()
1770            if panel in self.schedule_full_draw_list:
1771               self.schedule_full_draw_list.remove(panel) 
1772           
1773            #delete uid number not str(uid)
1774            if ID in self.plot_panels.keys():
1775                del self.plot_panels[ID]
1776            if ID in self.panels.keys():
1777                del self.panels[ID]
1778            #CallAfter: make sure panel is clear before updating mgr
1779            wx.CallAfter(self._mgr.Update)
1780            return 
1781     
1782    def clear_panel(self):
1783        """
1784        """
1785        for item in self.panels:
1786            try:
1787                self.panels[item].clear_panel()
1788            except:
1789                pass
1790           
1791    def create_gui_data(self, data, path=None):
1792        """
1793        """
1794        return self._data_manager.create_gui_data(data, path)
1795   
1796    def get_data(self, path):
1797        """
1798        """
1799        message = ""
1800        log_msg = ''
1801        output = []
1802        error_message = ""
1803        basename  = os.path.basename(path)
1804        root, extension = os.path.splitext(basename)
1805        if extension.lower() not in EXTENSIONS:
1806            log_msg = "File Loader cannot "
1807            log_msg += "load: %s\n" % str(basename)
1808            log_msg += "Try Data opening...."
1809            logging.info(log_msg)
1810            self.load_complete(output=output, error_message=error_message,
1811                   message=log_msg, path=path)   
1812            return
1813       
1814        #reading a state file
1815        for plug in self.plugins:
1816            reader, ext = plug.get_extensions()
1817            if reader is not None:
1818                #read the state of the single plugin
1819                if extension == ext:
1820                    reader.read(path)
1821                    return
1822                elif extension == APPLICATION_STATE_EXTENSION:
1823                    reader.read(path)
1824       
1825        style = self.__gui_style & GUIFRAME.MANAGER_ON
1826        if style == GUIFRAME.MANAGER_ON:
1827            if self._data_panel is not None:
1828                #data_state = self._data_manager.get_selected_data()
1829                #self._data_panel.load_data_list(data_state)
1830                self._mgr.GetPane(self._data_panel.window_name).Show(True)
1831     
1832    def load_from_cmd(self,  path):   
1833        """
1834        load data from cmd or application
1835        """ 
1836        if path is None:
1837            return
1838        else:
1839            path = os.path.abspath(path)
1840            if not os.path.isfile(path) and not os.path.isdir(path):
1841               return
1842           
1843            if os.path.isdir(path):
1844                self.load_folder(path)
1845                return
1846
1847        basename  = os.path.basename(path)
1848        root, extension = os.path.splitext(basename)
1849        if extension.lower() not in EXTENSIONS:
1850            self.load_data(path)
1851        else:
1852            self.load_state(path)
1853
1854        self._default_save_location = os.path.dirname(path)
1855
1856    def load_state(self, path):   
1857        """
1858        load data from command line or application
1859        """
1860        if path and (path is not None) and os.path.isfile(path):
1861            basename  = os.path.basename(path)
1862            if APPLICATION_STATE_EXTENSION is not None \
1863                and basename.endswith(APPLICATION_STATE_EXTENSION):
1864                #Hide current plot_panels i
1865                for ID in self.plot_panels.keys():
1866                    panel = self._mgr.GetPane(self.plot_panels[ID].window_name)
1867                    if panel.IsShown():
1868                        panel.Hide()
1869            self.get_data(path)
1870        if self.defaultPanel is not None and \
1871            self._mgr.GetPane(self.panels["default"].window_name).IsShown():
1872            self.on_close_welcome_panel()
1873           
1874    def load_data(self, path):
1875        """
1876        load data from command line
1877        """
1878        if not os.path.isfile(path):
1879            return
1880        basename  = os.path.basename(path)
1881        root, extension = os.path.splitext(basename)
1882        if extension.lower() in EXTENSIONS:
1883            log_msg = "Data Loader cannot "
1884            log_msg += "load: %s\n" % str(path)
1885            log_msg += "Try File opening ...."
1886            print log_msg
1887            return
1888        message = ""
1889        log_msg = ''
1890        output = {}
1891        error_message = ""
1892        try:
1893            print "Loading Data...:\n" + str(path) + "\n"
1894            temp =  self.loader.load(path)
1895            if temp.__class__.__name__ == "list":
1896                for item in temp:
1897                    data = self.create_gui_data(item, path)
1898                    output[data.id] = data
1899            else:
1900                data = self.create_gui_data(temp, path)
1901                output[data.id] = data
1902           
1903            self.add_data(data_list=output)
1904        except:
1905            error_message = "Error while loading"
1906            error_message += " Data from cmd:\n %s\n" % str(path)
1907            error_message += str(sys.exc_value) + "\n"
1908            print error_message
1909 
1910    def load_folder(self, path):
1911        """
1912        Load entire folder
1913        """   
1914        if not os.path.isdir(path):
1915            return
1916        if self._data_plugin is None:
1917            return
1918        try:
1919            if path is not None:
1920                self._default_save_location = os.path.dirname(path)
1921                file_list = self._data_plugin.get_file_path(path)
1922                self._data_plugin.get_data(file_list)
1923            else:
1924                return 
1925        except:
1926            error_message = "Error while loading"
1927            error_message += " Data folder from cmd:\n %s\n" % str(path)
1928            error_message += str(sys.exc_value) + "\n"
1929            print error_message
1930           
1931    def _on_open_state_application(self, event):
1932        """
1933        """
1934        path = None
1935        if self._default_save_location == None:
1936            self._default_save_location = os.getcwd()
1937       
1938        plug_wlist = self._on_open_state_app_helper()
1939        dlg = wx.FileDialog(self, 
1940                            "Choose a file", 
1941                            self._default_save_location, "",
1942                            plug_wlist)
1943        if dlg.ShowModal() == wx.ID_OK:
1944            path = dlg.GetPath()
1945            if path is not None:
1946                self._default_save_location = os.path.dirname(path)
1947        dlg.Destroy()
1948        self.load_state(path=path) 
1949   
1950    def _on_open_state_app_helper(self):
1951        """
1952        Helps '_on_open_state_application()' to find the extension of
1953        the current perspective/application
1954        """
1955        # No current perspective or no extension attr
1956        if self._current_perspective is None:
1957            return PLUGINS_WLIST
1958        try:
1959            # Find the extension of the perspective and get that as 1st item in list
1960            ind = None
1961            app_ext = self._current_perspective._extensions
1962            plug_wlist = config.PLUGINS_WLIST
1963            for ext in set(plug_wlist):
1964                if ext.count(app_ext) > 0:
1965                    ind = ext
1966                    break
1967            # Found the extension
1968            if ind != None:
1969                plug_wlist.remove(ind)
1970                plug_wlist.insert(0, ind)
1971                try:
1972                    plug_wlist ='|'.join(plug_wlist)
1973                except:
1974                    plug_wlist = ''
1975
1976        except:
1977            plug_wlist = PLUGINS_WLIST
1978           
1979        return plug_wlist
1980           
1981    def _on_open_state_project(self, event):
1982        """
1983        """
1984        path = None
1985        if self._default_save_location == None:
1986            self._default_save_location = os.getcwd()
1987       
1988        dlg = wx.FileDialog(self, 
1989                            "Choose a file", 
1990                            self._default_save_location, "",
1991                             APPLICATION_WLIST)
1992        if dlg.ShowModal() == wx.ID_OK:
1993            path = dlg.GetPath()
1994            if path is not None:
1995                self._default_save_location = os.path.dirname(path)
1996        dlg.Destroy()
1997       
1998        #try:   
1999        #    os.popen(path)
2000        #    #self.Close()
2001        #except:
2002        self.load_state(path=path)
2003       
2004    def _on_save_application(self, event):
2005        """
2006        save the state of the current active application
2007        """
2008        if self.cpanel_on_focus is not None:
2009            try:
2010                self.cpanel_on_focus.on_save(event)
2011            except:
2012                msg = "Error occurred while saving: "
2013                msg += "To save, the application panel should have a data set.."
2014                wx.PostEvent(self, StatusEvent(status=msg)) 
2015           
2016    def _on_save_project(self, event):
2017        """
2018        save the state of the SansView as *.svs
2019        """
2020        if self._current_perspective is  None:
2021            return
2022        reader, ext = self._current_perspective.get_extensions()
2023        path = None
2024        extension = '*' + APPLICATION_STATE_EXTENSION
2025        dlg = wx.FileDialog(self, "Save Project file",
2026                            self._default_save_location, "sansview_proj",
2027                             extension, 
2028                             wx.SAVE)
2029        if dlg.ShowModal() == wx.ID_OK:
2030            path = dlg.GetPath()
2031            self._default_save_location = os.path.dirname(path)
2032        else:
2033            return None
2034        dlg.Destroy()
2035        try:
2036            if path is None:
2037                return
2038            # default cansas xml doc
2039            doc = None
2040            for panel in self.panels.values():
2041                temp = panel.save_project(doc)
2042                if temp is not None:
2043                    doc = temp
2044             
2045            # Write the XML document
2046            extens = APPLICATION_STATE_EXTENSION
2047            fName = os.path.splitext(path)[0] + extens
2048            if doc != None:
2049                fd = open(fName, 'w')
2050                fd.write(doc.toprettyxml())
2051                fd.close()
2052            else:
2053                msg = "%s cannot read %s\n" % (str(APPLICATION_NAME), str(path))
2054                logging.error(msg)
2055        except:
2056           msg = "Error occurred while saving: "
2057           msg += "To save, at leat one application panel "
2058           msg += "should have a data set.."
2059           wx.PostEvent(self, StatusEvent(status=msg))   
2060                   
2061    def on_save_helper(self, doc, reader, panel, path):
2062        """
2063        Save state into a file
2064        """
2065        try:
2066            if reader is not None:
2067                # case of a panel with multi-pages
2068                if hasattr(panel, "opened_pages"):
2069                    for uid, page in panel.opened_pages.iteritems():
2070                        data = page.get_data()
2071                        # state must be cloned
2072                        state = page.get_state().clone()
2073                        if data is not None:
2074                            new_doc = reader.write_toXML(data, state)
2075                            if doc != None and hasattr(doc, "firstChild"):
2076                                child = new_doc.firstChild.firstChild
2077                                doc.firstChild.appendChild(child) 
2078                            else:
2079                                doc = new_doc
2080                # case of only a panel
2081                else:
2082                    data = panel.get_data()
2083                    state = panel.get_state()
2084                    if data is not None:
2085                        new_doc = reader.write_toXML(data, state)
2086                        if doc != None and hasattr(doc, "firstChild"):
2087                            child = new_doc.firstChild.firstChild
2088                            doc.firstChild.appendChild(child) 
2089                        else:
2090                            doc = new_doc
2091        except: 
2092            raise
2093            #pass
2094
2095        return doc
2096
2097    def quit_guiframe(self):
2098        """
2099        Pop up message to make sure the user wants to quit the application
2100        """
2101        message = "\nDo you really want to exit this application?        \n\n"
2102        dial = wx.MessageDialog(self, message, 'Confirm Exit',
2103                           wx.YES_NO|wx.YES_DEFAULT|wx.ICON_QUESTION)
2104        if dial.ShowModal() == wx.ID_YES:
2105            return True
2106        else:
2107            return False   
2108       
2109    def WindowClose(self, event=None):
2110        """
2111        Quit the application from x icon
2112        """
2113        flag = self.quit_guiframe()
2114        if flag:
2115            self.Close()
2116           
2117    def Close(self, event=None):
2118        """
2119        Quit the application
2120        """
2121        wx.Exit()
2122        sys.exit()
2123           
2124    def _check_update(self, event=None): 
2125        """
2126        Check with the deployment server whether a new version
2127        of the application is available.
2128        A thread is started for the connecting with the server. The thread calls
2129        a call-back method when the current version number has been obtained.
2130        """
2131        try:
2132            f=urllib2.urlopen(config.__update_URL__, 
2133                              timeout=1.0)
2134            content=f.read()
2135        except:
2136            content = "0.0.0"
2137       
2138        version = content.strip()
2139        if len(re.findall('\d+\.\d+\.\d+$', version)) < 0:
2140            content = "0.0.0"
2141        self._process_version(content, standalone=event==None)
2142   
2143    def _process_version(self, version, standalone=True):
2144        """
2145        Call-back method for the process of checking for updates.
2146        This methods is called by a VersionThread object once the current
2147        version number has been obtained. If the check is being done in the
2148        background, the user will not be notified unless there's an update.
2149       
2150        :param version: version string
2151        :param standalone: True of the update is being checked in
2152           the background, False otherwise.
2153           
2154        """
2155        try:
2156            if version == "0.0.0":
2157                msg = "Could not connect to the application server."
2158                msg += " Please try again later."
2159                self.SetStatusText(msg)
2160            elif cmp(version, config.__version__) > 0:
2161                msg = "Version %s is available! " % str(version)
2162                if not standalone:
2163                    import webbrowser
2164                    webbrowser.open(config.__download_page__)
2165                else:
2166                    msg +=  "See the help menu to download it." 
2167                self.SetStatusText(msg)
2168            else:
2169                if not standalone:
2170                    msg = "You have the latest version"
2171                    msg += " of %s" % str(config.__appname__)
2172                    self.SetStatusText(msg)
2173        except:
2174            msg = "guiframe: could not get latest application"
2175            msg += " version number\n  %s" % sys.exc_value
2176            logging.error(msg)
2177            if not standalone:
2178                msg = "Could not connect to the application server."
2179                msg += " Please try again later."
2180                self.SetStatusText(msg)
2181                   
2182    def _onAbout(self, evt):
2183        """
2184        Pop up the about dialog
2185       
2186        :param evt: menu event
2187       
2188        """
2189        if config._do_aboutbox:
2190            import aboutbox 
2191            dialog = aboutbox.DialogAbout(None, -1, "")
2192            dialog.ShowModal()   
2193                     
2194    def _onTutorial(self, evt):
2195        """
2196        Pop up the tutorial dialog
2197       
2198        :param evt: menu event
2199       
2200        """
2201        if config._do_tutorial:   
2202            path = config.TUTORIAL_PATH
2203            if IS_WIN:
2204                try:
2205                    from sans.guiframe.pdfview import PDFFrame
2206                   
2207                    dialog = PDFFrame(None, -1, "Tutorial", path)
2208                    # put icon
2209                    self.put_icon(frame) 
2210                    #self.SetTopWindow(dialog)
2211                    dialog.Show(True) 
2212                except:
2213                    print "Error in _onTutorial: %s" % sys.exc_value
2214                    try:
2215                        #in case when the pdf default set other than acrobat
2216                        import ho.pisa as pisa
2217                        pisa.startViewer(path)
2218                    except:
2219                        msg = "This feature requires 'PDF Viewer'\n"
2220                        msg += "Please install it first (Free)..."
2221                        wx.MessageBox(msg, 'Error')
2222            else:
2223                try:
2224                    command = "open '%s'" % path
2225                    os.system(command)
2226                except:
2227                    try:
2228                        #in case when the pdf default set other than preview
2229                        import ho.pisa as pisa
2230                        pisa.startViewer(path)
2231                    except:
2232                        msg = "This feature requires 'Preview' Application\n"
2233                        msg += "Please install it first..."
2234                        wx.MessageBox(msg, 'Error')
2235
2236                     
2237    def set_manager(self, manager):
2238        """
2239        Sets the application manager for this frame
2240       
2241        :param manager: frame manager
2242        """
2243        self.app_manager = manager
2244       
2245    def post_init(self):
2246        """
2247        This initialization method is called after the GUI
2248        has been created and all plug-ins loaded. It calls
2249        the post_init() method of each plug-in (if it exists)
2250        so that final initialization can be done.
2251        """
2252        for item in self.plugins:
2253            if hasattr(item, "post_init"):
2254                item.post_init()
2255       
2256    def set_default_perspective(self):
2257        """
2258        Choose among the plugin the first plug-in that has
2259        "set_default_perspective" method and its return value is True will be
2260        as a default perspective when the welcome page is closed
2261        """
2262        for item in self.plugins:
2263            if hasattr(item, "set_default_perspective"):
2264                if item.set_default_perspective():
2265                    item.on_perspective(event=None)
2266                    return 
2267       
2268    def set_perspective(self, panels):
2269        """
2270        Sets the perspective of the GUI.
2271        Opens all the panels in the list, and closes
2272        all the others.
2273       
2274        :param panels: list of panels
2275        """
2276        #style = self.__gui_style & GUIFRAME.TOOLBAR_ON
2277        #if (style == GUIFRAME.TOOLBAR_ON) & (not self._toolbar.IsShown()):
2278        #    self._on_toggle_toolbar()
2279        for item in self.panels:
2280            # Check whether this is a sticky panel
2281            if hasattr(self.panels[item], "ALWAYS_ON"):
2282                if self.panels[item].ALWAYS_ON:
2283                    continue 
2284           
2285            if self.panels[item].window_name in panels:
2286                if not self._mgr.GetPane(self.panels[item].window_name).IsShown():
2287                    self._mgr.GetPane(self.panels[item].window_name).Show()
2288            else:
2289                # always show the data panel if enable
2290                style = self.__gui_style & GUIFRAME.MANAGER_ON
2291                if (style == GUIFRAME.MANAGER_ON) and self.panels[item] == self._data_panel:
2292                    if 'data_panel' in self.panels.keys():
2293                        flag = self._mgr.GetPane(self.panels['data_panel'].window_name).IsShown()
2294                        self._mgr.GetPane(self.panels['data_panel'].window_name).Show(flag)
2295                else:
2296                    if self._mgr.GetPane(self.panels[item].window_name).IsShown():
2297                        self._mgr.GetPane(self.panels[item].window_name).Hide()
2298               
2299        self._mgr.Update()
2300       
2301    def show_data_panel(self, event=None, action=True):
2302        """
2303        show the data panel
2304        """
2305        if self._data_panel_menu == None:
2306            return
2307        label = self._data_panel_menu.GetText()
2308        if label == 'Show Data Explorer':
2309            pane = self._mgr.GetPane(self.panels["data_panel"].window_name)
2310            #if not pane.IsShown():
2311            if action: 
2312                pane.Show(True)
2313                self._mgr.Update()
2314            self.__gui_style = self.__gui_style | GUIFRAME.MANAGER_ON
2315           
2316            self._data_panel_menu.SetText('Hide Data Explorer')
2317        else:
2318            pane = self._mgr.GetPane(self.panels["data_panel"].window_name)
2319            #if not pane.IsShown():
2320            if action:
2321                pane.Show(False)
2322                self._mgr.Update()
2323            self.__gui_style = self.__gui_style & (~GUIFRAME.MANAGER_ON)
2324            self._data_panel_menu.SetText('Show Data Explorer')
2325   
2326    def add_data_helper(self, data_list):
2327        """
2328        """
2329        if self._data_manager is not None:
2330            self._data_manager.add_data(data_list)
2331       
2332    def add_data(self, data_list):
2333        """
2334        receive a dictionary of data from loader
2335        store them its data manager if possible
2336        send to data the current active perspective if the data panel
2337        is not active.
2338        :param data_list: dictionary of data's ID and value Data
2339        """
2340        #Store data into manager
2341        self.add_data_helper(data_list)
2342        # set data in the data panel
2343        if self._data_panel is not None:
2344            data_state = self._data_manager.get_data_state(data_list.keys())
2345            self._data_panel.load_data_list(data_state)
2346        #if the data panel is shown wait for the user to press a button
2347        #to send data to the current perspective. if the panel is not
2348        #show  automatically send the data to the current perspective
2349        style = self.__gui_style & GUIFRAME.MANAGER_ON
2350        if style == GUIFRAME.MANAGER_ON:
2351            #wait for button press from the data panel to set_data
2352            if self._data_panel is not None:
2353                self._mgr.GetPane(self._data_panel.window_name).Show(True)
2354                self._mgr.Update() 
2355        else:
2356            #automatically send that to the current perspective
2357            self.set_data(data_id=data_list.keys())
2358            self.on_close_welcome_panel()
2359       
2360    def set_data(self, data_id, theory_id=None): 
2361        """
2362        set data to current perspective
2363        """
2364        list_data, _ = self._data_manager.get_by_id(data_id)
2365        if self._current_perspective is not None:
2366            if self.cleanup_plots:
2367                for uid, panel in self.plot_panels.iteritems():
2368                    #panel = self.plot_panels[uid]
2369                    window = self._mgr.GetPane(panel.window_name)
2370                    # To hide all docked plot panels when set the data
2371                    if not window.IsFloating():
2372                        self.hide_panel(uid)
2373            self._current_perspective.set_data(list_data.values())
2374            self.on_close_welcome_panel()
2375        else:
2376            msg = "Guiframe does not have a current perspective"
2377            logging.info(msg)
2378           
2379    def set_theory(self, state_id, theory_id=None):
2380        """
2381        """
2382        _, list_theory = self._data_manager.get_by_id(theory_id)
2383        if self._current_perspective is not None:
2384            try:
2385                self._current_perspective.set_theory(list_theory.values())
2386            except:
2387                msg = "Guiframe set_theory: \n" + str(sys.exc_value)
2388                logging.info(msg)
2389                wx.PostEvent(self, StatusEvent(status=msg, info="error"))
2390        else:
2391            msg = "Guiframe does not have a current perspective"
2392            logging.info(msg)
2393           
2394    def plot_data(self,  state_id, data_id=None,
2395                  theory_id=None, append=False):
2396        """
2397        send a list of data to plot
2398        """
2399        total_plot_list = []
2400        data_list, _ = self._data_manager.get_by_id(data_id)
2401        _, temp_list_theory = self._data_manager.get_by_id(theory_id)
2402        total_plot_list = data_list.values()
2403        for item in temp_list_theory.values():
2404            theory_data, theory_state = item
2405            total_plot_list.append(theory_data)
2406        GROUP_ID = wx.NewId()
2407        for new_plot in total_plot_list:
2408            if append:
2409                if self.panel_on_focus is None:
2410                    message = "cannot append plot. No plot panel on focus!"
2411                    message += "please click on any available plot to set focus"
2412                    wx.PostEvent(self, StatusEvent(status=message, 
2413                                                   info='warning'))
2414                    return 
2415                else:
2416                    if self.enable_add_data(new_plot):
2417                        new_plot.group_id = self.panel_on_focus.group_id
2418                    else:
2419                        message = "Only 1D Data can be append to"
2420                        message += " plot panel containing 1D data.\n"
2421                        message += "%s not be appended.\n" %str(new_plot.name)
2422                        message += "try new plot option.\n"
2423                        wx.PostEvent(self, StatusEvent(status=message, 
2424                                                   info='warning'))
2425            else:
2426                if self.cleanup_plots:
2427                    for id, panel in self.plot_panels.iteritems():
2428                        window = self._mgr.GetPane(panel.window_name)
2429                        # To hide all docked plot panels when set the data
2430                        if not window.IsFloating():
2431                            self.hide_panel(id)
2432                #if not append then new plot
2433                from sans.guiframe.dataFitting import Data2D
2434                if issubclass(Data2D, new_plot.__class__):
2435                    #for 2 D always plot in a separated new plot
2436                    new_plot.group_id = wx.NewId()
2437                else:
2438                    # plot all 1D in a new plot
2439                    new_plot.group_id = GROUP_ID
2440            title = "PLOT " + str(new_plot.title)
2441            wx.PostEvent(self, NewPlotEvent(plot=new_plot,
2442                                                  title=title,
2443                                                  group_id = new_plot.group_id))
2444           
2445    def remove_data(self, data_id, theory_id=None):
2446        """
2447        Delete data state if data_id is provide
2448        delete theory created with data of id data_id if theory_id is provide
2449        if delete all true: delete the all state
2450        else delete theory
2451        """
2452        temp = data_id + theory_id
2453        """
2454        value = [plug.is_in_use(temp) for plug in self.plugins]
2455        if len(value) > 0:
2456            print "value"
2457            return
2458            from data_panel import DataDialog
2459            dlg = DataDialog(data_list=data_list, nb_data=MAX_NBR_DATA)
2460            if dlg.ShowModal() == wx.ID_OK:
2461                selected_data_list = dlg.get_data()
2462            dlg.Destroy()
2463        """
2464        for plug in self.plugins:
2465            plug.delete_data(temp)
2466        total_plot_list = []
2467        data_list, _ = self._data_manager.get_by_id(data_id)
2468        _, temp_list_theory = self._data_manager.get_by_id(theory_id)
2469        total_plot_list = data_list.values()
2470        for item in temp_list_theory.values():
2471            theory_data, theory_state = item
2472            total_plot_list.append(theory_data)
2473        for new_plot in total_plot_list:
2474            id = new_plot.id
2475            for group_id in new_plot.list_group_id:
2476                wx.PostEvent(self, NewPlotEvent(id=id,
2477                                                   group_id=group_id,
2478                                                   action='remove'))
2479                #remove res plot: Todo: improve
2480                wx.CallAfter(self._remove_res_plot, id)
2481        self._data_manager.delete_data(data_id=data_id, 
2482                                       theory_id=theory_id)
2483       
2484    def _remove_res_plot(self, id):
2485        """
2486        Try to remove corresponding res plot
2487       
2488        : param id: id of the data
2489        """
2490        try:
2491            wx.PostEvent(self, NewPlotEvent(id=("res"+str(id)),
2492                                           group_id=("res"+str(id)),
2493                                           action='remove'))
2494        except:
2495            pass
2496   
2497    def save_data1d(self, data, fname):
2498        """
2499        Save data dialog
2500        """
2501        default_name = fname
2502        wildcard = "Text files (*.txt)|*.txt|"\
2503                    "CanSAS 1D files(*.xml)|*.xml" 
2504        path = None
2505        dlg = wx.FileDialog(self, "Choose a file",
2506                            self._default_save_location,
2507                            default_name, wildcard , wx.SAVE)
2508       
2509        if dlg.ShowModal() == wx.ID_OK:
2510            path = dlg.GetPath()
2511            # ext_num = 0 for .txt, ext_num = 1 for .xml
2512            # This is MAC Fix
2513            ext_num = dlg.GetFilterIndex()
2514            if ext_num == 0:
2515                format = '.txt'
2516            else:
2517                format = '.xml'
2518            path = os.path.splitext(path)[0] + format
2519            mypath = os.path.basename(path)
2520           
2521            #TODO: This is bad design. The DataLoader is designed
2522            #to recognize extensions.
2523            # It should be a simple matter of calling the .
2524            #save(file, data, '.xml') method
2525            # of the sans.dataloader.loader.Loader class.
2526            from sans.dataloader.loader import  Loader
2527            #Instantiate a loader
2528            loader = Loader() 
2529            format = ".txt"
2530            if os.path.splitext(mypath)[1].lower() == format:
2531                # Make sure the ext included in the file name
2532                # especially on MAC
2533                fName = os.path.splitext(path)[0] + format
2534                self._onsaveTXT(data, fName)
2535            format = ".xml"
2536            if os.path.splitext(mypath)[1].lower() == format:
2537                # Make sure the ext included in the file name
2538                # especially on MAC
2539                fName = os.path.splitext(path)[0] + format
2540                loader.save(fName, data, format)
2541            try:
2542                self._default_save_location = os.path.dirname(path)
2543            except:
2544                pass   
2545        dlg.Destroy()
2546       
2547       
2548    def _onsaveTXT(self, data, path):
2549        """
2550        Save file as txt 
2551        :TODO: Refactor and remove this method. See TODO in _onSave.
2552        """
2553        if not path == None:
2554            out = open(path, 'w')
2555            has_errors = True
2556            if data.dy == None or data.dy == []:
2557                has_errors = False
2558            # Sanity check
2559            if has_errors:
2560                try:
2561                    if len(data.y) != len(data.dy):
2562                        has_errors = False
2563                except:
2564                    has_errors = False
2565            if has_errors:
2566                if data.dx != None and data.dx != []:
2567                    out.write("<X>   <Y>   <dY>   <dX>\n")
2568                else:
2569                    out.write("<X>   <Y>   <dY>\n")
2570            else:
2571                out.write("<X>   <Y>\n")
2572               
2573            for i in range(len(data.x)):
2574                if has_errors:
2575                    if data.dx != None and data.dx != []:
2576                        out.write("%g  %g  %g  %g\n" % (data.x[i], 
2577                                                    data.y[i],
2578                                                    data.dy[i],
2579                                                    data.dx[i]))
2580                    else:
2581                        out.write("%g  %g  %g\n" % (data.x[i], 
2582                                                    data.y[i],
2583                                                    data.dy[i]))
2584                else:
2585                    out.write("%g  %g\n" % (data.x[i], 
2586                                            data.y[i]))
2587            out.close() 
2588                             
2589    def show_data1d(self, data, name):
2590        """
2591        Show data dialog
2592        """   
2593        text = data.__str__() 
2594        text += 'Data Min Max:\n'
2595        text += 'X_min = %s:  X_max = %s\n'% (min(data.x), max(data.x))
2596        text += 'Y_min = %s:  Y_max = %s\n'% (min(data.y), max(data.y))
2597        if data.dy != None:
2598            text += 'dY_min = %s:  dY_max = %s\n'% (min(data.dy), max(data.dy))
2599        text += '\nData Points:\n'
2600        x_st = "X"
2601        for index in range(len(data.x)):
2602            if data.dy != None:
2603                dy_val = data.dy[index]
2604            else:
2605                dy_val = 0.0
2606            if data.dx != None:
2607                dx_val = data.dx[index]
2608            else:
2609                dx_val = 0.0
2610            if data.dxl != None:
2611                if index == 0: x_st = "Xl"
2612                dx_val = data.dxl[index]
2613            elif data.dxw != None:
2614                if index == 0: x_st = "Xw"
2615                dx_val = data.dxw[index]
2616           
2617            if index == 0:
2618                text += "<index> \t<X> \t<Y> \t<dY> \t<d%s>\n"% x_st
2619            text += "%s \t%s \t%s \t%s \t%s\n" % (index,
2620                                            data.x[index], 
2621                                            data.y[index],
2622                                            dy_val,
2623                                            dx_val)
2624        from pdfview import TextFrame
2625        frame = TextFrame(None, -1, "Data Info: %s"% data.name, text) 
2626        # put icon
2627        self.put_icon(frame) 
2628        frame.Show(True) 
2629           
2630    def save_data2d(self, data, fname):   
2631        """
2632        Save data2d dialog
2633        """
2634        default_name = fname
2635        wildcard = "IGOR/DAT 2D file in Q_map (*.dat)|*.DAT"
2636        dlg = wx.FileDialog(self, "Choose a file",
2637                            self._default_save_location,
2638                            default_name, wildcard , wx.SAVE)
2639       
2640        if dlg.ShowModal() == wx.ID_OK:
2641            path = dlg.GetPath()
2642            # ext_num = 0 for .txt, ext_num = 1 for .xml
2643            # This is MAC Fix
2644            ext_num = dlg.GetFilterIndex()
2645            if ext_num == 0:
2646                format = '.dat'
2647            else:
2648                format = ''
2649            path = os.path.splitext(path)[0] + format
2650            mypath = os.path.basename(path)
2651           
2652            #TODO: This is bad design. The DataLoader is designed
2653            #to recognize extensions.
2654            # It should be a simple matter of calling the .
2655            #save(file, data, '.xml') method
2656            # of the DataLoader.loader.Loader class.
2657            from sans.dataloader.loader import  Loader
2658            #Instantiate a loader
2659            loader = Loader() 
2660
2661            format = ".dat"
2662            if os.path.splitext(mypath)[1].lower() == format:
2663                # Make sure the ext included in the file name
2664                # especially on MAC
2665                fileName = os.path.splitext(path)[0] + format
2666                loader.save(fileName, data, format)
2667            try:
2668                self._default_save_location = os.path.dirname(path)
2669            except:
2670                pass   
2671        dlg.Destroy() 
2672                             
2673    def show_data2d(self, data, name):
2674        """
2675        Show data dialog
2676        """   
2677
2678        wx.PostEvent(self, StatusEvent(status = "Gathering Data2D Info.", 
2679                                       type = 'start' ))
2680        text = data.__str__() 
2681        text += 'Data Min Max:\n'
2682        text += 'I_min = %s\n'% min(data.data)
2683        text += 'I_max = %s\n\n'% max(data.data)
2684        text += 'Data (First 2501) Points:\n'
2685        text += 'Data columns include err(I).\n'
2686        text += 'ASCII data starts here.\n'
2687        text += "<index> \t<Qx> \t<Qy> \t<I> \t<dI> \t<dQparal> \t<dQperp>\n"
2688        di_val = 0.0
2689        dx_val = 0.0
2690        dy_val = 0.0
2691        #mask_val = True
2692        len_data = len(data.qx_data)
2693        for index in xrange(0, len_data):
2694            x_val = data.qx_data[index]
2695            y_val = data.qy_data[index]
2696            i_val = data.data[index]
2697            if data.err_data != None: di_val = data.err_data[index]
2698            if data.dqx_data != None: dx_val = data.dqx_data[index]
2699            if data.dqy_data != None: dy_val = data.dqy_data[index]
2700            #if data.mask != None: mask_val = data.mask[index]
2701 
2702            text += "%s \t%s \t%s \t%s \t%s \t%s \t%s\n" % (index,
2703                                            x_val, 
2704                                            y_val,
2705                                            i_val,
2706                                            di_val,
2707                                            dx_val,
2708                                            dy_val)
2709            # Takes too long time for typical data2d: Break here
2710            if index >= 2500:
2711                text += ".............\n"
2712                break
2713
2714        from pdfview import TextFrame
2715        frame = TextFrame(None, -1, "Data Info: %s"% data.name, text) 
2716        # put icon
2717        self.put_icon(frame)
2718        frame.Show(True) 
2719        wx.PostEvent(self, StatusEvent(status = "Data2D Info Displayed", 
2720                                       type = 'stop' ))
2721                                 
2722    def set_current_perspective(self, perspective):
2723        """
2724        set the current active perspective
2725        """
2726        self._current_perspective = perspective
2727        name = "No current analysis selected"
2728        if self._current_perspective is not None:
2729            self._add_current_plugin_menu()
2730            for panel in self.panels.values():
2731                if hasattr(panel, 'CENTER_PANE') and panel.CENTER_PANE:
2732                    for name in self._current_perspective.get_perspective():
2733                        if name == panel.window_name:
2734                            panel.on_set_focus(event=None)
2735                            break               
2736            name = self._current_perspective.sub_menu
2737            if self._data_panel is not None:
2738                self._data_panel.set_active_perspective(name)
2739                self._check_applications_menu()
2740            #Set the SansView title
2741            self._set_title_name(name)
2742         
2743           
2744    def _set_title_name(self, name):
2745        """
2746        Set the SansView title w/ the current application name
2747       
2748        : param name: application name [string]
2749        """
2750        # Set SanView Window title w/ application anme
2751        title = self.title + "  - " + name + " -"
2752        self.SetTitle(title)
2753           
2754    def _check_applications_menu(self):
2755        """
2756        check the menu of the current application
2757        """
2758        if self._applications_menu is not None:
2759            for menu in self._applications_menu.GetMenuItems():
2760                if self._current_perspective is not None:
2761                    name = self._current_perspective.sub_menu
2762                    if menu.IsCheckable():
2763                        if menu.GetLabel() == name:
2764                            menu.Check(True)
2765                        else:
2766                             menu.Check(False) 
2767           
2768    def set_plotpanel_floating(self, event=None):
2769        """
2770        make the plot panel floatable
2771        """
2772       
2773        self.__gui_style &= (~GUIFRAME.FIXED_PANEL)
2774        self.__gui_style |= GUIFRAME.FLOATING_PANEL
2775        plot_panel = []
2776        id = event.GetId()
2777        menu = self._window_menu.FindItemById(id)
2778        if self._plotting_plugin is not None:
2779            plot_panel = self.plot_panels.values()
2780            for p in plot_panel:
2781                self._popup_floating_panel(p)
2782            menu.Check(True)
2783           
2784    def set_plotpanel_fixed(self, event=None):
2785        """
2786        make the plot panel fixed
2787        """
2788        self.__gui_style &= (~GUIFRAME.FLOATING_PANEL)
2789        self.__gui_style |= GUIFRAME.FIXED_PANEL
2790        plot_panel = []
2791        id = event.GetId()
2792        menu = self._window_menu.FindItemById(id)
2793        if self._plotting_plugin is not None:
2794            plot_panel = self.plot_panels.values()
2795            for p in plot_panel:
2796                self._popup_fixed_panel(p)
2797            menu.Check(True)
2798           
2799    def on_cleanup_dock(self, event=None):     
2800        """
2801        Set Cleanup Dock option
2802        """
2803        if event == None:
2804            return
2805        id = event.GetId()
2806        menu = self._window_menu.FindItemById(id)
2807        Flag = self.cleanup_plots
2808        if not Flag:
2809            menu.Check(True)
2810            self.cleanup_plots = True
2811            msg = "Cleanup-Dock option set to 'ON'."
2812        else:
2813            menu.Check(False)
2814            self.cleanup_plots = False
2815            msg = "Cleanup-Dock option set to 'OFF'."
2816
2817        wx.PostEvent(self, StatusEvent(status= msg))
2818         
2819    def _popup_fixed_panel(self, p):
2820        """
2821        """
2822        style = self.__gui_style & GUIFRAME.FIXED_PANEL
2823        if style == GUIFRAME.FIXED_PANEL:
2824            self._mgr.GetPane(p.window_name).Dock()
2825            self._mgr.GetPane(p.window_name).Floatable()
2826            self._mgr.GetPane(p.window_name).Right()
2827            self._mgr.GetPane(p.window_name).TopDockable(False)
2828            self._mgr.GetPane(p.window_name).BottomDockable(False)
2829            self._mgr.GetPane(p.window_name).LeftDockable(False)
2830            self._mgr.GetPane(p.window_name).RightDockable(True)
2831            self._mgr.Update()
2832           
2833    def _popup_floating_panel(self, p):
2834        """
2835        """
2836        style = self.__gui_style &  GUIFRAME.FLOATING_PANEL
2837        if style == GUIFRAME.FLOATING_PANEL: 
2838            self._mgr.GetPane(p.window_name).Floatable(True)
2839            self._mgr.GetPane(p.window_name).Float()
2840            self._mgr.GetPane(p.window_name).Dockable(False)
2841            self._mgr.Update()
2842           
2843    def enable_add_data(self, new_plot):
2844        """
2845        Enable append data on a plot panel
2846        """
2847
2848        if self.panel_on_focus not in self._plotting_plugin.plot_panels.values():
2849            return
2850        is_theory = len(self.panel_on_focus.plots) <= 1 and \
2851            self.panel_on_focus.plots.values()[0].__class__.__name__ == "Theory1D"
2852           
2853        is_data2d = hasattr(new_plot, 'data')
2854       
2855        is_data1d = self.panel_on_focus.__class__.__name__ == "ModelPanel1D"\
2856            and self.panel_on_focus.group_id is not None
2857        has_meta_data = hasattr(new_plot, 'meta_data')
2858       
2859        #disable_add_data if the data is being recovered from  a saved state file.
2860        is_state_data = False
2861        if has_meta_data:
2862            if 'invstate' in new_plot.meta_data: 
2863                is_state_data = True
2864            if  'prstate' in new_plot.meta_data: 
2865                is_state_data = True
2866            if  'fitstate' in new_plot.meta_data: 
2867                is_state_data = True
2868   
2869        return is_data1d and not is_data2d and not is_theory and not is_state_data
2870   
2871    def check_multimode(self, perspective=None):
2872        """
2873        Check the perspective have batch mode capablitity
2874        """
2875        if perspective == None or self._data_panel == None:
2876            return
2877        flag = perspective.get_batch_capable()
2878        flag_on = perspective.batch_on
2879        if flag:
2880            self._data_panel.rb_single_mode.SetValue(not flag_on)
2881            self._data_panel.rb_batch_mode.SetValue(flag_on)
2882        else:
2883            self._data_panel.rb_single_mode.SetValue(True)
2884            self._data_panel.rb_batch_mode.SetValue(False)
2885        self._data_panel.rb_single_mode.Enable(flag)
2886        self._data_panel.rb_batch_mode.Enable(flag)
2887               
2888
2889   
2890    def enable_edit_menu(self):
2891        """
2892        enable menu item under edit menu depending on the panel on focus
2893        """
2894        if self.cpanel_on_focus is not None and self._edit_menu is not None:
2895            flag = self.cpanel_on_focus.get_undo_flag()
2896            self._edit_menu.Enable(GUIFRAME_ID.UNDO_ID, flag)
2897            flag = self.cpanel_on_focus.get_redo_flag()
2898            self._edit_menu.Enable(GUIFRAME_ID.REDO_ID, flag)
2899            flag = self.cpanel_on_focus.get_copy_flag()
2900            self._edit_menu.Enable(GUIFRAME_ID.COPY_ID, flag)
2901            flag = self.cpanel_on_focus.get_paste_flag()
2902            self._edit_menu.Enable(GUIFRAME_ID.PASTE_ID, flag)
2903            #flag = self.cpanel_on_focus.get_print_flag()
2904            #self._edit_menu.Enable(GUIFRAME_ID.PRINT_ID, flag)
2905            flag = self.cpanel_on_focus.get_preview_flag()
2906            self._edit_menu.Enable(GUIFRAME_ID.PREVIEW_ID, flag)
2907            flag = self.cpanel_on_focus.get_reset_flag()
2908            self._edit_menu.Enable(GUIFRAME_ID.RESET_ID, flag)
2909        else:
2910            flag = False
2911            self._edit_menu.Enable(GUIFRAME_ID.UNDO_ID, flag)
2912            self._edit_menu.Enable(GUIFRAME_ID.REDO_ID, flag)
2913            self._edit_menu.Enable(GUIFRAME_ID.COPY_ID, flag)
2914            self._edit_menu.Enable(GUIFRAME_ID.PASTE_ID, flag)
2915            #self._edit_menu.Enable(GUIFRAME_ID.PRINT_ID, flag)
2916            self._edit_menu.Enable(GUIFRAME_ID.PREVIEW_ID, flag)
2917            self._edit_menu.Enable(GUIFRAME_ID.RESET_ID, flag)
2918           
2919    def on_undo_panel(self, event=None):
2920        """
2921        undo previous action of the last panel on focus if possible
2922        """
2923        if self.cpanel_on_focus is not None:
2924            self.cpanel_on_focus.on_undo(event)
2925           
2926    def on_redo_panel(self, event=None):
2927        """
2928        redo the last cancel action done on the last panel on focus
2929        """
2930        if self.cpanel_on_focus is not None:
2931            self.cpanel_on_focus.on_redo(event)
2932           
2933    def on_copy_panel(self, event=None):
2934        """
2935        copy the last panel on focus if possible
2936        """
2937        if self.cpanel_on_focus is not None:
2938            self.cpanel_on_focus.on_copy(event)
2939           
2940    def on_paste_panel(self, event=None):
2941        """
2942        paste clipboard to the last panel on focus
2943        """
2944        if self.cpanel_on_focus is not None:
2945            self.cpanel_on_focus.on_paste(event)
2946                   
2947    def on_bookmark_panel(self, event=None):
2948        """
2949        bookmark panel
2950        """
2951        if self.cpanel_on_focus is not None:
2952            self.cpanel_on_focus.on_bookmark(event)
2953           
2954    def append_bookmark(self, event=None):
2955        """
2956        Bookmark available information of the panel on focus
2957        """
2958        self._toolbar.append_bookmark(event)
2959           
2960    def on_save_panel(self, event=None):
2961        """
2962        save possible information on the current panel
2963        """
2964        if self.cpanel_on_focus is not None:
2965            self.cpanel_on_focus.on_save(event)
2966           
2967    def on_preview_panel(self, event=None):
2968        """
2969        preview information on the panel on focus
2970        """
2971        if self.cpanel_on_focus is not None:
2972            self.cpanel_on_focus.on_preview(event)
2973           
2974    def on_print_panel(self, event=None):
2975        """
2976        print available information on the last panel on focus
2977        """
2978        if self.cpanel_on_focus is not None:
2979            self.cpanel_on_focus.on_print(event)
2980           
2981    def on_zoom_panel(self, event=None):
2982        """
2983        zoom on the current panel if possible
2984        """
2985        if self.cpanel_on_focus is not None:
2986            self.cpanel_on_focus.on_zoom(event)
2987           
2988    def on_zoom_in_panel(self, event=None):
2989        """
2990        zoom in of the panel on focus
2991        """
2992        if self.cpanel_on_focus is not None:
2993            self.cpanel_on_focus.on_zoom_in(event)
2994           
2995    def on_zoom_out_panel(self, event=None):
2996        """
2997        zoom out on the panel on focus
2998        """
2999        if self.cpanel_on_focus is not None:
3000            self.cpanel_on_focus.on_zoom_out(event)
3001           
3002    def on_drag_panel(self, event=None):
3003        """
3004        drag apply to the panel on focus
3005        """
3006        if self.cpanel_on_focus is not None:
3007            self.cpanel_on_focus.on_drag(event)
3008           
3009    def on_reset_panel(self, event=None):
3010        """
3011        reset the current panel
3012        """
3013        if self.cpanel_on_focus is not None:
3014            self.cpanel_on_focus.on_reset(event)
3015           
3016    def on_change_caption(self, name, old_caption, new_caption):     
3017        """
3018        Change the panel caption
3019       
3020        :param name: window_name of the pane
3021        :param old_caption: current caption [string]
3022        :param new_caption: new caption [string]
3023        """
3024        # wx.aui.AuiPaneInfo
3025        pane_info = self.get_paneinfo(name) 
3026        # update the data_panel.cb_plotpanel
3027        if 'data_panel' in self.panels.keys():
3028            # remove from data_panel combobox
3029            data_panel = self.panels["data_panel"]
3030            if data_panel.cb_plotpanel is not None:
3031                # Check if any panel has the same caption
3032                has_newstring = data_panel.cb_plotpanel.FindString\
3033                                                            (str(new_caption)) 
3034                caption = new_caption
3035                if has_newstring != wx.NOT_FOUND:
3036                    captions = self._get_plotpanel_captions()
3037                    # Append nummber
3038                    inc = 1
3039                    while (1):
3040                        caption = new_caption + '_%s'% str(inc)
3041                        if caption not in captions:
3042                            break
3043                        inc += 1
3044                    # notify to users
3045                    msg = "Found Same Title: Added '_%s'"% str(inc)
3046                    wx.PostEvent(self, StatusEvent(status=msg))
3047                # update data_panel cb
3048                pos = data_panel.cb_plotpanel.FindString(str(old_caption)) 
3049                if pos != wx.NOT_FOUND:
3050                    data_panel.cb_plotpanel.SetString(pos, caption)
3051                    data_panel.cb_plotpanel.SetStringSelection(caption)
3052        # update window Show menu
3053        if self._window_menu != None:
3054            for item in self._window_menu.GetMenuItems():
3055                pos = self._window_menu.FindItem(old_caption)
3056                if self._window_menu.GetLabel(pos) == str(old_caption):
3057                    self._window_menu.SetLabel(pos, caption)
3058                break
3059        # New Caption
3060        pane_info.Caption(caption)
3061        # update aui manager
3062        self._mgr.Update()
3063        return caption
3064       
3065    def get_paneinfo(self, name):
3066        """
3067        Get pane Caption from window_name
3068       
3069        :param name: window_name in AuiPaneInfo
3070        : return: AuiPaneInfo of the name
3071        """
3072        return self._mgr.GetPane(name) 
3073   
3074    def enable_undo(self):
3075        """
3076        enable undo related control
3077        """
3078        if self.cpanel_on_focus is not None:
3079            self._toolbar.enable_undo(self.cpanel_on_focus)
3080           
3081    def enable_redo(self):
3082        """
3083        enable redo
3084        """
3085        if self.cpanel_on_focus is not None:
3086            self._toolbar.enable_redo(self.cpanel_on_focus)
3087           
3088    def enable_copy(self):
3089        """
3090        enable copy related control
3091        """
3092        if self.cpanel_on_focus is not None:
3093            self._toolbar.enable_copy(self.cpanel_on_focus)
3094           
3095    def enable_paste(self):
3096        """
3097        enable paste
3098        """
3099        if self.cpanel_on_focus is not None:
3100            self._toolbar.enable_paste(self.cpanel_on_focus)
3101                       
3102    def enable_bookmark(self):
3103        """
3104        Bookmark
3105        """
3106        if self.cpanel_on_focus is not None:
3107            self._toolbar.enable_bookmark(self.cpanel_on_focus)
3108           
3109    def enable_save(self):
3110        """
3111        save
3112        """
3113        if self.cpanel_on_focus is not None:
3114            self._toolbar.enable_save(self.cpanel_on_focus)
3115           
3116    def enable_preview(self):
3117        """
3118        preview
3119        """
3120        if self.cpanel_on_focus is not None:
3121            self._toolbar.enable_preview(self.cpanel_on_focus)
3122           
3123    def enable_print(self):
3124        """
3125        print
3126        """
3127        if self.cpanel_on_focus is not None:
3128            self._toolbar.enable_print(self.cpanel_on_focus)
3129           
3130    def enable_zoom(self):
3131        """
3132        zoom
3133        """
3134        if self.cpanel_on_focus is not None:
3135            self._toolbar.enable_zoom(self.panel_on_focus)
3136           
3137    def enable_zoom_in(self):
3138        """
3139        zoom in
3140        """
3141        if self.cpanel_on_focus is not None:
3142            self._toolbar.enable_zoom_in(self.panel_on_focus)
3143           
3144    def enable_zoom_out(self):
3145        """
3146        zoom out
3147        """
3148        if self.cpanel_on_focus is not None:
3149            self._toolbar.enable_zoom_out(self.panel_on_focus)
3150           
3151    def enable_drag(self, event=None):
3152        """
3153        drag
3154        """
3155        if self.cpanel_on_focus is not None:
3156            self._toolbar.enable_drag(self.panel_on_focus)
3157           
3158    def enable_reset(self):
3159        """
3160        reset the current panel
3161        """
3162        if self.cpanel_on_focus is not None:
3163            self._toolbar.enable_reset(self.panel_on_focus)
3164
3165    def set_schedule_full_draw(self, panel=None, func='del'):
3166        """
3167        Add/subtract the schedule full draw list with the panel given
3168       
3169        :param panel: plot panel
3170        :param func: append or del [string]
3171        """
3172
3173        # append this panel in the schedule list if not in yet
3174        if func == 'append':
3175            if not panel in self.schedule_full_draw_list:
3176                self.schedule_full_draw_list.append(panel) 
3177        # remove this panel from schedule list
3178        elif func == 'del':
3179            if len(self.schedule_full_draw_list) > 0:
3180                if panel in self.schedule_full_draw_list:
3181                    self.schedule_full_draw_list.remove(panel)
3182
3183        # reset the schdule
3184        if len(self.schedule_full_draw_list) == 0:
3185            self.schedule = False
3186        else:
3187            self.schedule = True   
3188       
3189    def full_draw(self):
3190        """
3191        Draw the panels with axes in the schedule to full dwar list
3192        """
3193        count = len(self.schedule_full_draw_list)
3194        #if not self.schedule:
3195        if count < 1:
3196            self.set_schedule(False)
3197            return
3198        else:
3199            ind = 0
3200            # if any of the panel is shown do full_draw
3201            for panel in self.schedule_full_draw_list:
3202                ind += 1
3203                if self._mgr.GetPane(panel.window_name).IsShown():
3204                    break
3205                # otherwise, return
3206                if ind == count:
3207                    return
3208
3209        #Simple redraw only for a panel shown
3210        def f_draw(panel):
3211            """
3212            Draw A panel in the full dwar list
3213            """
3214            try:
3215                # This checking of GetCapture is to stop redrawing
3216                # while any panel is capture.
3217                if self.GetCapture() == None:
3218                    # draw if possible
3219                    panel.set_resizing(False)
3220                    panel.Show(False)
3221                    panel.draw_plot()
3222                   
3223                    # Check if the panel is not shown
3224                    if not self._mgr.GetPane(panel.window_name).IsShown():
3225                        self._mgr.GetPane(panel.window_name).Hide()
3226                    else:
3227                        panel.Show(True)
3228            except:
3229                pass
3230       
3231        # Draw all panels       
3232        map(f_draw, self.schedule_full_draw_list)
3233       
3234        # Reset the attr 
3235        if len(self.schedule_full_draw_list) == 0:
3236            self.set_schedule(False)
3237        else:
3238            self.set_schedule(True)
3239        # do not update mgr
3240        #self._mgr.Update()
3241       
3242    def set_schedule(self, schedule=False): 
3243        """
3244        Set schedule
3245        """
3246        self.schedule = schedule
3247               
3248    def get_schedule(self): 
3249        """
3250        Get schedule
3251        """
3252        return self.schedule
3253   
3254    def on_set_plot_focus(self, panel):
3255        """
3256        Set focus on a plot panel
3257        """
3258        self.set_plot_unfocus()
3259        panel.on_set_focus(None) 
3260        # set focusing panel
3261        self.panel_on_focus = panel 
3262        self.set_panel_on_focus(None)
3263
3264    def set_plot_unfocus(self): 
3265        """
3266        Un focus all plot panels
3267        """
3268        for plot in self.plot_panels.values():
3269            plot.on_kill_focus(None)
3270
3271    def _onDrawIdle(self, *args, **kwargs):
3272        """
3273        ReDraw with axes
3274        """
3275        try:
3276            # check if it is time to redraw
3277            if self.GetCapture() == None:
3278                # Draw plot, changes resizing too
3279                self.full_draw()
3280        except:
3281            pass
3282           
3283        # restart idle       
3284        self._redraw_idle(*args, **kwargs)
3285
3286           
3287    def _redraw_idle(self, *args, **kwargs):
3288        """
3289        Restart Idle
3290        """
3291        # restart idle   
3292        self.idletimer.Restart(100*TIME_FACTOR, *args, **kwargs)
3293
3294       
3295class DefaultPanel(wx.Panel, PanelBase):
3296    """
3297    Defines the API for a panels to work with
3298    the GUI manager
3299    """
3300    ## Internal nickname for the window, used by the AUI manager
3301    window_name = "default"
3302    ## Name to appear on the window title bar
3303    window_caption = "Welcome panel"
3304    ## Flag to tell the AUI manager to put this panel in the center pane
3305    CENTER_PANE = True
3306    def __init__(self, parent, *args, **kwds):
3307        wx.Panel.__init__(self, parent, *args, **kwds)
3308        PanelBase.__init__(self, parent)
3309   
3310
3311
3312# Toy application to test this Frame
3313class ViewApp(wx.App):
3314    """
3315    """
3316    def OnInit(self):
3317        """
3318        """
3319        global GUIFRAME_WIDTH, GUIFRAME_HEIGHT 
3320       
3321        if (GUIFRAME_WIDTH > ((wx.DisplaySize()[0]/100)*90) | GUIFRAME_HEIGHT > ((wx.DisplaySize()[1]/100)*90) ):
3322            GUIFRAME_WIDTH = (wx.DisplaySize()[0]/100)*90
3323            GUIFRAME_HEIGHT = (wx.DisplaySize()[1]/100)*90
3324
3325        pos, size = self.window_placement((GUIFRAME_WIDTH, GUIFRAME_HEIGHT))     
3326        self.frame = ViewerFrame(parent=None, 
3327                             title=APPLICATION_NAME, 
3328                             pos=pos, 
3329                             gui_style = DEFAULT_STYLE,
3330                             size=size)
3331        self.frame.Hide()
3332        self.s_screen = None
3333
3334        try:
3335            self.open_file()
3336        except:
3337            msg = "%s Could not load " % str(APPLICATION_NAME)
3338            msg += "input file from command line.\n"
3339            logging.error(msg)
3340        # Display a splash screen on top of the frame.
3341        try:
3342            if os.path.isfile(SPLASH_SCREEN_PATH):
3343                self.s_screen = self.display_splash_screen(parent=self.frame, 
3344                                        path=SPLASH_SCREEN_PATH)
3345            else:
3346                self.frame.Show()   
3347        except:
3348            if self.s_screen is not None:
3349                self.s_screen.Close()
3350            msg = "Cannot display splash screen\n"
3351            msg += str (sys.exc_value)
3352            logging.error(msg)
3353            self.frame.Show()
3354 
3355        if hasattr(self.frame, 'special'):
3356            self.frame.special.SetCurrent()
3357        self.SetTopWindow(self.frame)
3358 
3359        return True
3360
3361    def open_file(self):
3362        """
3363        open a state file at the start of the application
3364        """
3365        input_file = None
3366        if len(sys.argv) >= 2:
3367            cmd = sys.argv[0].lower()
3368            basename  = os.path.basename(cmd)
3369            app_base = str(APPLICATION_NAME).lower()
3370            if os.path.isfile(cmd) or basename.lower() == app_base:
3371                app_py = app_base + '.py'
3372                app_exe = app_base + '.exe'
3373                app_app = app_base + '.app'
3374                if basename.lower() in [app_py, app_exe, app_app, app_base]:
3375                    data_base = sys.argv[1]
3376                    input_file = os.path.normpath(os.path.join(DATAPATH, 
3377                                                               data_base))
3378        if input_file is None:
3379            return
3380        if self.frame is not None:
3381            self.frame.set_input_file(input_file=input_file)
3382         
3383           
3384    def set_manager(self, manager):
3385        """
3386        Sets a reference to the application manager
3387        of the GUI manager (Frame)
3388        """
3389        self.frame.set_manager(manager)
3390       
3391    def build_gui(self):
3392        """
3393        Build the GUI
3394        """
3395        #try to load file at the start
3396        try:
3397            self.open_file()
3398        except:
3399            raise
3400        self.frame.build_gui()
3401        #if self.s_screen is not None and self.s_screen.IsShown():
3402        #    self.s_screen.Close()
3403       
3404    def set_welcome_panel(self, panel_class):
3405        """
3406        Set the welcome panel
3407       
3408        :param panel_class: class of the welcome panel to be instantiated
3409       
3410        """
3411        self.frame.set_welcome_panel(panel_class)
3412       
3413    def add_perspective(self, perspective):
3414        """
3415        Manually add a perspective to the application GUI
3416        """
3417        self.frame.add_perspective(perspective)
3418   
3419    def window_placement(self, size):
3420        """
3421        Determines the position and size of the application frame such that it
3422        fits on the user's screen without obstructing (or being obstructed by)
3423        the Windows task bar.  The maximum initial size in pixels is bounded by
3424        WIDTH x HEIGHT.  For most monitors, the application
3425        will be centered on the screen; for very large monitors it will be
3426        placed on the left side of the screen.
3427        """
3428        window_width, window_height = size
3429        screen_size = wx.GetDisplaySize()
3430        window_height = window_height if screen_size[1]>window_height else screen_size[1]-10
3431        window_width  = window_width if screen_size[0]> window_width else screen_size[0]-10
3432        xpos = ypos = 0
3433
3434        # Note that when running Linux and using an Xming (X11) server on a PC
3435        # with a dual  monitor configuration, the reported display size may be
3436        # that of both monitors combined with an incorrect display count of 1.
3437        # To avoid displaying this app across both monitors, we check for
3438        # screen 'too big'.  If so, we assume a smaller width which means the
3439        # application will be placed towards the left hand side of the screen.
3440
3441        _, _, x, y = wx.Display().GetClientArea() # size excludes task bar
3442        if len(sys.argv) > 1 and '--platform' in sys.argv[1:]:
3443            w, h = wx.DisplaySize()  # size includes task bar area
3444        # display on left side, not centered on screen
3445        if x > 1920 and x > (2*y): x = x / 2 
3446        if x > window_width:  xpos = (x - window_width)/2
3447        if y > window_height: ypos = (y - window_height)/2
3448
3449        # Return the suggested position and size for the application frame.
3450        return (xpos, ypos), (min(x, window_width), min(y, window_height))
3451   
3452    def display_splash_screen(self, parent, 
3453                              path=SPLASH_SCREEN_PATH):
3454        """Displays the splash screen.  It will exactly cover the main frame."""
3455       
3456        # Prepare the picture.  On a 2GHz intel cpu, this takes about a second.
3457        x, y = parent.GetSizeTuple()
3458        image = wx.Image(path, wx.BITMAP_TYPE_PNG)
3459        image.Rescale(SPLASH_SCREEN_WIDTH, 
3460                      SPLASH_SCREEN_HEIGHT, wx.IMAGE_QUALITY_HIGH)
3461        bm = image.ConvertToBitmap()
3462
3463        # Create and show the splash screen.  It will disappear only when the
3464        # program has entered the event loop AND either the timeout has expired
3465        # or the user has left clicked on the screen.  Thus any processing
3466        # performed in this routine (including sleeping) or processing in the
3467        # calling routine (including doing imports) will prevent the splash
3468        # screen from disappearing.
3469        #
3470        # Note that on Linux, the timeout appears to occur immediately in which
3471        # case the splash screen disappears upon entering the event loop.
3472        s_screen = wx.SplashScreen(bitmap=bm,
3473                         splashStyle=(wx.SPLASH_TIMEOUT|
3474                                              wx.SPLASH_CENTRE_ON_SCREEN),
3475                                 style=(wx.SIMPLE_BORDER|
3476                                        wx.FRAME_NO_TASKBAR|
3477                                        wx.STAY_ON_TOP),
3478                                       
3479                        milliseconds=SS_MAX_DISPLAY_TIME,
3480                        parent=parent,
3481                        id=wx.ID_ANY)
3482        from gui_statusbar import SPageStatusbar
3483        statusBar = SPageStatusbar(s_screen)
3484        s_screen.SetStatusBar(statusBar)
3485        s_screen.Bind(wx.EVT_CLOSE, self.on_close_splash_screen)
3486        s_screen.Show()
3487        return s_screen
3488       
3489       
3490    def on_close_splash_screen(self, event):
3491        """
3492        """
3493        self.frame.Show(True)
3494        event.Skip()
3495
3496if __name__ == "__main__": 
3497    app = ViewApp(0)
3498    app.MainLoop()
3499
3500             
Note: See TracBrowser for help on using the repository browser.