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

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

fixed recovering menu problem after maximize/restore size p_panel.

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