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

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

fixing the size problem for mac

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