source: sasview/guiframe/gui_manager.py @ 248b918

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 248b918 was b46b1b9, checked in by Jae Cho <jhjcho@…>, 14 years ago

reverting previous commit

  • Property mode set to 100644
File size: 92.7 KB
Line 
1
2################################################################################
3#This software was developed by the University of Tennessee as part of the
4#Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
5#project funded by the US National Science Foundation.
6#
7#See the license text in license.txt
8#
9#copyright 2008, University of Tennessee
10################################################################################
11
12
13import wx
14import wx.aui
15import os
16import sys
17import xml
18
19try:
20    # Try to find a local config
21    import imp
22    path = os.getcwd()
23    if(os.path.isfile("%s/%s.py" % (path, 'local_config'))) or \
24        (os.path.isfile("%s/%s.pyc" % (path, 'local_config'))):
25        fObj, path, descr = imp.find_module('local_config', [path])
26        config = imp.load_module('local_config', fObj, path, descr) 
27    else:
28        # Try simply importing local_config
29        import local_config as config
30except:
31    # Didn't find local config, load the default
32    import config
33   
34import warnings
35warnings.simplefilter("ignore")
36
37import logging
38
39from sans.guiframe.events import EVT_STATUS
40from sans.guiframe.events import EVT_APPEND_BOOKMARK
41from sans.guiframe.events import EVT_PANEL_ON_FOCUS
42from sans.guiframe.events import StatusEvent
43from sans.guiframe.events import NewPlotEvent
44from sans.guiframe.gui_style import GUIFRAME
45from sans.guiframe.gui_style import GUIFRAME_ID
46from sans.guiframe.events import NewLoadedDataEvent
47from sans.guiframe.data_panel import DataPanel
48from sans.guiframe.panel_base import PanelBase
49from sans.guiframe.gui_toolbar import GUIToolBar
50from DataLoader.loader import Loader
51
52
53#read some constants from config
54APPLICATION_STATE_EXTENSION = config.APPLICATION_STATE_EXTENSION
55APPLICATION_NAME = config.__appname__
56SPLASH_SCREEN_PATH = config.SPLASH_SCREEN_PATH
57DEFAULT_STYLE = config.DEFAULT_STYLE
58SPLASH_SCREEN_WIDTH = config.SPLASH_SCREEN_WIDTH
59SPLASH_SCREEN_HEIGHT = config.SPLASH_SCREEN_HEIGHT
60SS_MAX_DISPLAY_TIME = config.SS_MAX_DISPLAY_TIME
61PLOPANEL_WIDTH = config.PLOPANEL_WIDTH
62PLOPANEL_HEIGTH = config.PLOPANEL_HEIGTH
63GUIFRAME_WIDTH = config.GUIFRAME_WIDTH
64GUIFRAME_HEIGHT = config.GUIFRAME_HEIGHT
65DATAPANEL_WIDTH = 235
66PLUGIN_STATE_EXTENSIONS =  config.PLUGIN_STATE_EXTENSIONS
67extension_list = []
68if APPLICATION_STATE_EXTENSION is not None:
69    extension_list.append(APPLICATION_STATE_EXTENSION)
70EXTENSIONS = PLUGIN_STATE_EXTENSIONS + extension_list
71try:
72    PLUGINS_WLIST = '|'.join(config.PLUGINS_WLIST)
73except:
74    PLUGINS_WLIST = ''
75APPLICATION_WLIST = config.APPLICATION_WLIST
76if sys.platform.count("darwin")==0:
77    IS_WIN = True
78else:
79    IS_WIN = False
80   
81class ViewerFrame(wx.Frame):
82    """
83    Main application frame
84    """
85   
86    def __init__(self, parent, title, 
87                 size=(GUIFRAME_WIDTH, GUIFRAME_HEIGHT),
88                 gui_style=GUIFRAME.DEFAULT_STYLE, 
89                 pos=wx.DefaultPosition):
90        """
91        Initialize the Frame object
92        """
93       
94        wx.Frame.__init__(self, parent=parent, title=title, pos=pos,size=size)
95        # title
96        self.title = title
97        # Preferred window size
98        self._window_width, self._window_height = size
99        self.__gui_style = gui_style
100       
101        # Logging info
102        logging.basicConfig(level=logging.DEBUG,
103                    format='%(asctime)s %(levelname)s %(message)s',
104                    filename='sans_app.log',
105                    filemode='w')       
106        path = os.path.dirname(__file__)
107        temp_path = os.path.join(path,'images')
108        ico_file = os.path.join(temp_path,'ball.ico')
109        if os.path.isfile(ico_file):
110            self.SetIcon(wx.Icon(ico_file, wx.BITMAP_TYPE_ICO))
111        else:
112            temp_path = os.path.join(os.getcwd(),'images')
113            ico_file = os.path.join(temp_path,'ball.ico')
114            if os.path.isfile(ico_file):
115                self.SetIcon(wx.Icon(ico_file, wx.BITMAP_TYPE_ICO))
116            else:
117                ico_file = os.path.join(os.path.dirname(os.path.sys.path[0]),
118                             'images', 'ball.ico')
119                if os.path.isfile(ico_file):
120                    self.SetIcon(wx.Icon(ico_file, wx.BITMAP_TYPE_ICO))
121       
122        ## Application manager
123        self._input_file = None
124        self.app_manager = None
125        self._mgr = None
126        #add current perpsective
127        self._current_perspective = None
128        self._plotting_plugin = None
129        self._data_plugin = None
130        #Menu bar and item
131        self._menubar = None
132        self._file_menu = None
133        self._data_menu = None
134        self._view_menu = None
135        self._window_menu = None
136        self._data_panel_menu = None
137        self._help_menu = None
138        self._tool_menu = None
139        self._applications_menu_pos = -1
140        self._applications_menu_name = None
141        self._applications_menu = None
142        self._edit_menu = None
143        self._toolbar_menu = None
144        self._save_appl_menu = None
145        #tool bar
146        self._toolbar = None
147        # (un)-focus color
148        #self.color = '#b3b3b3'
149        ## Find plug-ins
150        # Modify this so that we can specify the directory to look into
151        self.plugins = []
152        #add local plugin
153        self.plugins += self._get_local_plugins()
154        self.plugins += self._find_plugins()
155        ## List of panels
156        self.panels = {}
157        # List of plot panels
158        self.plot_panels = {}
159
160        # Default locations
161        self._default_save_location = os.getcwd()       
162       
163        # Welcome panel
164        self.defaultPanel = None
165        #panel on focus
166        self.panel_on_focus = None
167        #control_panel on focus
168        self.cpanel_on_focus = None
169        self.loader = Loader()   
170        #data manager
171        from data_manager import DataManager
172        self._data_manager = DataManager()
173        self._data_panel = DataPanel(parent=self)
174        if self.panel_on_focus is not None:
175            self._data_panel.set_panel_on_focus(self.panel_on_focus.window_caption)
176        # list of plot panels in schedule to full redraw
177        self.schedule = False
178        #self.callback = True
179        self._idle_count = 0
180        self.schedule_full_draw_list = []
181        self.idletimer = wx.CallLater(1, self._onDrawIdle)
182
183        # Check for update
184        #self._check_update(None)
185        # Register the close event so it calls our own method
186        wx.EVT_CLOSE(self, self.Close)
187        # Register to status events
188        self.Bind(EVT_STATUS, self._on_status_event)
189        #Register add extra data on the same panel event on load
190        self.Bind(EVT_PANEL_ON_FOCUS, self.set_panel_on_focus)
191        self.Bind(EVT_APPEND_BOOKMARK, self.append_bookmark)
192       
193       
194    def get_current_perspective(self):
195        """
196        return the current perspective
197        """
198        return self._current_perspective
199   
200    def set_input_file(self, input_file):
201        """
202        :param input_file: file to read
203        """
204        self._input_file = input_file
205       
206    def get_data_manager(self):
207        """
208        """
209        return self._data_manager
210   
211    def get_toolbar(self):
212        """
213        """
214        return self._toolbar
215   
216    def set_panel_on_focus(self, event):
217        """
218        Store reference to the last panel on focus
219        update the toolbar if available
220        update edit menu if available
221        """
222        if event != None:
223            self.panel_on_focus = event.panel
224        panel_name = 'No panel on focus'
225        application_name = 'No Selected Analysis'
226        if self.panel_on_focus is not None:
227            if self.panel_on_focus not in self.plot_panels.values():
228                for ID in self.panels.keys():
229                    if self.panel_on_focus != self.panels[ID]:
230                        self.panels[ID].on_kill_focus(None)
231
232            if self._data_panel is not None and \
233                            self.panel_on_focus is not None:
234                panel_name = self.panel_on_focus.window_caption
235                ID = self.panel_on_focus.uid
236                self._data_panel.set_panel_on_focus(ID)
237                #update combo
238                if self.panel_on_focus in self.plot_panels.values():
239                    self._data_panel.cb_plotpanel.SetStringSelection(str\
240                                         (self.panel_on_focus.window_caption))
241                elif self.panel_on_focus != self._data_panel:
242                    cpanel = self.panel_on_focus
243                    if self.cpanel_on_focus != cpanel:
244                        self.cpanel_on_focus = self.panel_on_focus
245                #update toolbar
246                self._update_toolbar_helper()
247                #update edit menu
248                self.enable_edit_menu()
249
250    def reset_bookmark_menu(self, panel):
251        """
252        Reset Bookmark menu list
253       
254        : param panel: a control panel or tap where the bookmark is
255        """
256        cpanel = panel
257        if self._toolbar != None and cpanel._bookmark_flag:
258            for item in  self._toolbar.get_bookmark_items():
259                self._toolbar.remove_bookmark_item(item)
260            self._toolbar.add_bookmark_default()
261            pos = 0
262            for bitem in cpanel.popUpMenu.GetMenuItems():
263                pos += 1
264                if pos < 3:
265                    continue
266                id =  bitem.GetId()
267                label = bitem.GetLabel()
268                self._toolbar.append_bookmark_item(id, label)
269                wx.EVT_MENU(self, id, cpanel._back_to_bookmark)
270            self._toolbar.Realize()
271             
272
273    def build_gui(self):
274        """
275        """
276        # set tool bar
277        self._setup_tool_bar()
278        # Set up the layout
279        self._setup_layout()
280        # Set up the menu
281        self._setup_menus()
282       
283        try:
284            self.load_from_cmd(self._input_file)
285        except:
286            msg = "%s Cannot load file %s\n" %(str(APPLICATION_NAME), 
287                                             str(self._input_file))
288            msg += str(sys.exc_value) + '\n'
289            print msg
290        if self._data_panel is not None:
291            self._data_panel.fill_cbox_analysis(self.plugins)
292        self.post_init()
293        #self.show_welcome_panel(None)
294        #self.Show(True)
295        #self._check_update(None)
296             
297    def _setup_layout(self):
298        """
299        Set up the layout
300        """
301        # Status bar
302        from gui_statusbar import StatusBar
303        self.sb = StatusBar(self, wx.ID_ANY)
304        self.SetStatusBar(self.sb)
305        # Add panel
306        default_flag = wx.aui.AUI_MGR_DEFAULT#| wx.aui.AUI_MGR_ALLOW_ACTIVE_PANE
307        self._mgr = wx.aui.AuiManager(self, flags=default_flag)
308        self._mgr.SetDockSizeConstraint(0.5, 0.5)
309        # border color
310        #self.b_color = wx.aui.AUI_DOCKART_BORDER_COLOUR 
311        #self._mgr.GetArtProvider().SetColor(self.b_color, self.color)
312        #self._mgr.SetArtProvider(wx.aui.AuiDockArt(wx.AuiDefaultDockArt))
313        #print "set", self._dockart.GetColour(13)
314        # Load panels
315        self._load_panels()
316        self.set_default_perspective()
317        self._mgr.Update()
318       
319    def SetStatusText(self, *args, **kwds):
320        """
321        """
322        number = self.sb.get_msg_position()
323        wx.Frame.SetStatusText(number=number, *args, **kwds)
324       
325    def PopStatusText(self, *args, **kwds):
326        """
327        """
328        field = self.sb.get_msg_position()
329        wx.Frame.PopStatusText(field=field)
330       
331    def PushStatusText(self, *args, **kwds):
332        """
333        """
334        field = self.sb.get_msg_position()
335        wx.Frame.PushStatusText(self, field=field, string=string)
336
337    def add_perspective(self, plugin):
338        """
339        Add a perspective if it doesn't already
340        exist.
341        """
342        is_loaded = False
343        for item in self.plugins:
344            if plugin.__class__ == item.__class__:
345                msg = "Plugin %s already loaded" % plugin.sub_menu
346                logging.info(msg)
347                is_loaded = True   
348        if not is_loaded:
349            self.plugins.append(plugin)
350           
351     
352    def _get_local_plugins(self):
353        """
354        get plugins local to guiframe and others
355        """
356        plugins = []
357        #import guiframe local plugins
358        #check if the style contain guiframe.dataloader
359        style1 = self.__gui_style & GUIFRAME.DATALOADER_ON
360        style2 = self.__gui_style & GUIFRAME.PLOTTING_ON
361        if style1 == GUIFRAME.DATALOADER_ON:
362            try:
363                from sans.guiframe.local_perspectives.data_loader import data_loader
364                self._data_plugin = data_loader.Plugin()
365                plugins.append(self._data_plugin)
366            except:
367                msg = "ViewerFrame._get_local_plugins:"
368                msg += "cannot import dataloader plugin.\n %s" % sys.exc_value
369                logging.error(msg)
370        if style2 == GUIFRAME.PLOTTING_ON:
371            try:
372                from sans.guiframe.local_perspectives.plotting import plotting
373                self._plotting_plugin = plotting.Plugin()
374                plugins.append(self._plotting_plugin)
375            except:
376                msg = "ViewerFrame._get_local_plugins:"
377                msg += "cannot import plotting plugin.\n %s" % sys.exc_value
378                logging.error(msg)
379     
380        return plugins
381   
382    def _find_plugins(self, dir="perspectives"):
383        """
384        Find available perspective plug-ins
385       
386        :param dir: directory in which to look for plug-ins
387       
388        :return: list of plug-ins
389       
390        """
391        import imp
392        plugins = []
393        # Go through files in panels directory
394        try:
395            list = os.listdir(dir)
396            ## the default panel is the panel is the last plugin added
397            for item in list:
398                toks = os.path.splitext(os.path.basename(item))
399                name = ''
400                if not toks[0] == '__init__':
401                    if toks[1] == '.py' or toks[1] == '':
402                        name = toks[0]
403                    #check the validity of the module name parsed
404                    #before trying to import it
405                    if name is None or name.strip() == '':
406                        continue
407                    path = [os.path.abspath(dir)]
408                    file = ''
409                    try:
410                        if toks[1] == '':
411                            mod_path = '.'.join([dir, name])
412                            module = __import__(mod_path, globals(),
413                                                locals(), [name])
414                        else:
415                            (file, path, info) = imp.find_module(name, path)
416                            module = imp.load_module( name, file, item, info)
417                        if hasattr(module, "PLUGIN_ID"):
418                            try: 
419                                plug = module.Plugin()
420                                if plug.set_default_perspective():
421                                    self._current_perspective = plug
422                                plugins.append(plug)
423                                msg = "Found plug-in: %s" % module.PLUGIN_ID
424                                logging.info(msg)
425                            except:
426                                msg = "Error accessing PluginPanel"
427                                msg += " in %s\n  %s" % (name, sys.exc_value)
428                                config.printEVT(msg)
429                    except:
430                        msg = "ViewerFrame._find_plugins: %s" % sys.exc_value
431                        #print msg
432                        logging.error(msg)
433                    finally:
434                        if not file == None:
435                            file.close()
436        except:
437            # Should raise and catch at a higher level and
438            # display error on status bar
439            pass   
440        return plugins
441   
442    def set_welcome_panel(self, panel_class):
443        """
444        Sets the default panel as the given welcome panel
445       
446        :param panel_class: class of the welcome panel to be instantiated
447       
448        """
449        self.defaultPanel = panel_class(self, -1, style=wx.RAISED_BORDER)
450       
451    def _get_panels_size(self, p):
452        """
453        find the proper size of the current panel
454        get the proper panel width and height
455        """
456        panel_height_min = self._window_height
457        panel_width_min = self._window_width
458        style = self.__gui_style & (GUIFRAME.MANAGER_ON)
459        if self._data_panel is not None  and (p == self._data_panel):
460            panel_width_min = DATAPANEL_WIDTH
461            panel_height_min = self._window_height * 0.8
462            return panel_width_min, panel_height_min
463        if hasattr(p, "CENTER_PANE") and p.CENTER_PANE:
464            style = self.__gui_style & (GUIFRAME.PLOTTING_ON|GUIFRAME.MANAGER_ON)
465            if style == (GUIFRAME.PLOTTING_ON|GUIFRAME.MANAGER_ON):
466                panel_width_min = self._window_width -\
467                            (DATAPANEL_WIDTH +config.PLOPANEL_WIDTH)
468            return panel_width_min, panel_height_min
469        return panel_width_min, panel_height_min
470   
471    def _load_panels(self):
472        """
473        Load all panels in the panels directory
474        """
475       
476        # Look for plug-in panels
477        panels = []   
478        for item in self.plugins:
479            if hasattr(item, "get_panels"):
480                ps = item.get_panels(self)
481                panels.extend(ps)
482       
483        # Show a default panel with some help information
484        # It also sets the size of the application windows
485        #TODO: Use this for slpash screen
486        if self.defaultPanel is None:
487            self.defaultPanel = DefaultPanel(self, -1, style=wx.RAISED_BORDER)
488        # add a blank default panel always present
489        self.panels["default"] = self.defaultPanel
490        self._mgr.AddPane(self.defaultPanel, wx.aui.AuiPaneInfo().
491                              Name("default").
492                              CenterPane().
493                              #CloseButton(False).
494                              #MinimizeButton(False).
495                              # This is where we set the size of
496                              # the application window
497                              BestSize(wx.Size(self._window_width, 
498                                               self._window_height)).
499                              Show())
500
501        #add data panel
502        self.panels["data_panel"] = self._data_panel
503        w, h = self._get_panels_size(self._data_panel)
504        self._mgr.AddPane(self._data_panel, wx.aui.AuiPaneInfo().
505                              Name(self._data_panel.window_name).
506                              Caption(self._data_panel.window_caption).
507                              Left().
508                              MinimizeButton().
509                              CloseButton(IS_WIN).
510                              TopDockable(False).
511                              BottomDockable(False).
512                              LeftDockable(True).
513                              RightDockable(False).
514                              BestSize(wx.Size(w, h)).
515                              Hide())
516
517        style = self.__gui_style & GUIFRAME.MANAGER_ON
518        data_pane = self._mgr.GetPane(self.panels["data_panel"].window_name)
519        if style != GUIFRAME.MANAGER_ON:
520            self._mgr.GetPane(self.panels["data_panel"].window_name).Hide()
521        else:
522            self._mgr.GetPane(self.panels["data_panel"].window_name).Show()
523           
524        # Add the panels to the AUI manager
525        for panel_class in panels:
526            p = panel_class
527            id = wx.NewId()
528            #w, h = self._get_panels_size(p)
529            # Check whether we need to put this panel
530            # in the center pane
531            if hasattr(p, "CENTER_PANE") and p.CENTER_PANE:
532                w, h = self._get_panels_size(p)
533                if p.CENTER_PANE:
534                    self.panels[str(id)] = p
535                    self._mgr.AddPane(p, wx.aui.AuiPaneInfo().
536                                          Name(p.window_name).
537                                          CenterPane().
538                                          Center().
539                                          CloseButton(False).
540                                          Hide())
541            else:
542                self.panels[str(id)] = p
543                self._mgr.AddPane(p, wx.aui.AuiPaneInfo().
544                                  Name(p.window_name).Caption(p.window_caption).
545                                  Right().
546                                  Dock().
547                                  TopDockable().
548                                  BottomDockable().
549                                  LeftDockable().
550                                  RightDockable().
551                                  MinimizeButton().
552                                  Hide())       
553     
554    def update_data(self, prev_data, new_data):
555        """
556        """
557        prev_id, data_state = self._data_manager.update_data(prev_data=prev_data, 
558                                       new_data=new_data)
559       
560        self._data_panel.remove_by_id(prev_id)
561        self._data_panel.load_data_list(data_state)
562       
563    def update_theory(self, data_id, theory, state=None):
564        """
565        """ 
566        data_state = self._data_manager.update_theory(data_id=data_id, 
567                                         theory=theory,
568                                         state=state) 
569        self._data_panel.load_data_list(data_state)
570       
571    def onfreeze(self, theory_id):
572        """
573        """
574        data_state_list = self._data_manager.freeze(theory_id)
575        self._data_panel.load_data_list(list=data_state_list)
576        for data_state in data_state_list.values():
577            new_plot = data_state.get_data()
578           
579            wx.PostEvent(self, NewPlotEvent(plot=new_plot,
580                                             title=new_plot.title))
581       
582    def freeze(self, data_id, theory_id):
583        """
584        """
585        data_state_list = self._data_manager.freeze_theory(data_id=data_id, 
586                                                theory_id=theory_id)
587        self._data_panel.load_data_list(list=data_state_list)
588        for data_state in data_state_list.values():
589            new_plot = data_state.get_data()
590            wx.PostEvent(self, NewPlotEvent(plot=new_plot,
591                                             title=new_plot.title))
592       
593    def delete_data(self, data):
594        """
595        """
596        self._current_perspective.delete_data(data)
597       
598   
599    def get_context_menu(self, plotpanel=None):
600        """
601        Get the context menu items made available
602        by the different plug-ins.
603        This function is used by the plotting module
604        """
605        if plotpanel is None:
606            return
607        menu_list = []
608        for item in self.plugins:
609            menu_list.extend(item.get_context_menu(plotpanel=plotpanel))
610        return menu_list
611       
612    def popup_panel(self, p):
613        """
614        Add a panel object to the AUI manager
615       
616        :param p: panel object to add to the AUI manager
617       
618        :return: ID of the event associated with the new panel [int]
619       
620        """
621        ID = wx.NewId()
622        self.panels[str(ID)] = p
623        count = 0
624        for item in self.panels:
625            if self.panels[item].window_name.startswith(p.window_name): 
626                count += 1
627        windowname = p.window_name
628        caption = p.window_caption
629        if count > 0:
630            windowname += str(count+1)
631            caption += (' '+str(count))
632        p.window_name = windowname
633        p.window_caption = caption
634           
635        style1 = self.__gui_style & GUIFRAME.FIXED_PANEL
636        style2 = self.__gui_style & GUIFRAME.FLOATING_PANEL
637        if style1 == GUIFRAME.FIXED_PANEL:
638            self._mgr.AddPane(p, wx.aui.AuiPaneInfo().
639                              Name(windowname).
640                              Caption(caption).
641                              Position(10).
642                              Floatable().
643                              Right().
644                              Dock().
645                              MinimizeButton().
646                              Resizable(True).
647                              # Use a large best size to make sure the AUI
648                              # manager takes all the available space
649                              BestSize(wx.Size(PLOPANEL_WIDTH, 
650                                               PLOPANEL_HEIGTH)))
651                       
652            self._popup_fixed_panel(p)
653   
654        elif style2 == GUIFRAME.FLOATING_PANEL:
655            self._mgr.AddPane(p, wx.aui.AuiPaneInfo().
656                              Name(windowname).Caption(caption).
657                              MinimizeButton().
658                              Resizable(True).
659                              # Use a large best size to make sure the AUI
660                              #  manager takes all the available space
661                              BestSize(wx.Size(PLOPANEL_WIDTH, 
662                                               PLOPANEL_HEIGTH)))
663            self._popup_floating_panel(p)
664           
665        pane = self._mgr.GetPane(windowname)
666        self._mgr.MaximizePane(pane)
667        self._mgr.RestoreMaximizedPane()
668        # Register for showing/hiding the panel
669        wx.EVT_MENU(self, ID, self.on_view)
670        if p not in self.plot_panels.values():
671            self.plot_panels[ID] = p
672            if len(self.plot_panels) == 1:
673                self.panel_on_focus = p
674                self.set_panel_on_focus(None)
675            if self._data_panel is not None and \
676                self._plotting_plugin is not None:
677                ind = self._data_panel.cb_plotpanel.FindString('None')
678                if ind != wx.NOT_FOUND:
679                    self._data_panel.cb_plotpanel.Delete(ind)
680                if caption not in self._data_panel.cb_plotpanel.GetItems():
681                    self._data_panel.cb_plotpanel.Append(str(caption), p)
682
683        self._mgr.Update()
684        return ID
685       
686    def _setup_menus(self):
687        """
688        Set up the application menus
689        """
690        # Menu
691        self._menubar = wx.MenuBar()
692        self._add_menu_file()
693        self._add_menu_edit()
694        self._add_menu_view()
695        #self._add_menu_data()
696        self._add_menu_application()
697        self._add_menu_tool()
698        self._add_current_plugin_menu()
699        self._add_menu_window()
700        self._add_help_menu()
701        self.SetMenuBar(self._menubar)
702       
703    def _setup_tool_bar(self):
704        """
705        add toolbar to the frame
706        """
707        #set toolbar
708        self._toolbar = GUIToolBar(self, -1)
709        self.SetToolBar(self._toolbar)
710        self._update_toolbar_helper()
711        self._on_toggle_toolbar(event=None)
712   
713    def _update_toolbar_helper(self):
714        """
715        """
716        application_name = 'No Selected Analysis'
717        panel_name = 'No Panel on Focus'
718        if self._toolbar is  None:
719            return
720        if self.cpanel_on_focus is not None:
721            self.reset_bookmark_menu(self.cpanel_on_focus)
722        self._toolbar.update_toolbar(self.cpanel_on_focus)
723        if self._current_perspective is not None:
724            application_name = self._current_perspective.sub_menu
725        if self.cpanel_on_focus is not None:
726            panel_name = self.cpanel_on_focus.window_caption
727           
728        self._toolbar.update_button(application_name=application_name, 
729                                        panel_name=panel_name)
730       
731        self._toolbar.Realize()
732       
733    def _add_menu_tool(self):
734        """
735        Tools menu
736        Go through plug-ins and find tools to populate the tools menu
737        """
738        style = self.__gui_style & GUIFRAME.CALCULATOR_ON
739        if style == GUIFRAME.CALCULATOR_ON:
740            self._tool_menu = None
741            for item in self.plugins:
742                if hasattr(item, "get_tools"):
743                    for tool in item.get_tools():
744                        # Only create a menu if we have at least one tool
745                        if self._tool_menu is None:
746                            self._tool_menu = wx.Menu()
747                        id = wx.NewId()
748                        self._tool_menu.Append(id, tool[0], tool[1])
749                        wx.EVT_MENU(self, id, tool[2])
750            if self._tool_menu is not None:
751                self._menubar.Append(self._tool_menu, '&Tool')
752               
753    def _add_current_plugin_menu(self):
754        """
755        add current plugin menu
756        Look for plug-in menus
757        Add available plug-in sub-menus.
758        """
759        if (self._menubar is None) or (self._current_perspective is None):
760            return
761        #replace or add a new menu for the current plugin
762       
763        pos = self._menubar.FindMenu(str(self._applications_menu_name))
764        if pos != -1:
765            menu_list = self._current_perspective.populate_menu(self)
766            if menu_list:
767                for (menu, name) in menu_list:
768                    hidden_menu = self._menubar.Replace(pos, menu, name) 
769                    self._applications_menu_name = name
770                #self._applications_menu_pos = pos
771            else:
772                hidden_menu = self._menubar.Remove(pos)
773                self._applications_menu_name = None
774            #get the position of the menu when it first added
775            self._applications_menu_pos = pos
776           
777        else:
778            menu_list = self._current_perspective.populate_menu(self)
779            if menu_list:
780                for (menu,name) in menu_list:
781                    if self._applications_menu_pos == -1:
782                        self._menubar.Append(menu, name)
783                    else:
784                        self._menubar.Insert(self._applications_menu_pos, menu, name)
785                    self._applications_menu_name = name
786                 
787    def _add_help_menu(self):
788        """
789        add help menu
790        """
791        # Help menu
792        self._help_menu = wx.Menu()
793        style = self.__gui_style & GUIFRAME.WELCOME_PANEL_ON
794        if style == GUIFRAME.WELCOME_PANEL_ON:
795            # add the welcome panel menu item
796            if self.defaultPanel is not None:
797                id = wx.NewId()
798                self._help_menu.Append(id, '&Welcome', '')
799                self._help_menu.AppendSeparator()
800                wx.EVT_MENU(self, id, self.show_welcome_panel)
801        # Look for help item in plug-ins
802        for item in self.plugins:
803            if hasattr(item, "help"):
804                id = wx.NewId()
805                self._help_menu.Append(id,'&%s Help' % item.sub_menu, '')
806                wx.EVT_MENU(self, id, item.help)
807        if config._do_aboutbox:
808            id = wx.NewId()
809            self._help_menu.Append(id,'&About', 'Software information')
810            wx.EVT_MENU(self, id, self._onAbout)
811       
812        # Checking for updates needs major refactoring to work with py2exe
813        # We need to make sure it doesn't hang the application if the server
814        # is not up. We also need to make sure there's a proper executable to
815        # run if we spawn a new background process.
816        #id = wx.NewId()
817        #self._help_menu.Append(id,'&Check for update',
818        #'Check for the latest version of %s' % config.__appname__)
819        #wx.EVT_MENU(self, id, self._check_update)
820        self._menubar.Append(self._help_menu, '&Help')
821           
822    def _add_menu_view(self):
823        """
824        add menu items under view menu
825        """
826        self._view_menu = wx.Menu()
827        style = self.__gui_style & GUIFRAME.MANAGER_ON
828        id = wx.NewId()
829        self._data_panel_menu = self._view_menu.Append(id,
830                                                '&Data Explorer ON', '')
831        wx.EVT_MENU(self, id, self.show_data_panel)
832        if style == GUIFRAME.MANAGER_ON:
833            self._data_panel_menu.SetText('Data Explorer OFF')
834        else:
835            self._data_panel_menu.SetText('Data Explorer ON')
836        self._view_menu.AppendSeparator()
837        id = wx.NewId()
838        style1 = self.__gui_style & GUIFRAME.TOOLBAR_ON
839        if style1 == GUIFRAME.TOOLBAR_ON:
840            self._toolbar_menu = self._view_menu.Append(id,'&Hide Toolbar', '')
841        else:
842            self._toolbar_menu = self._view_menu.Append(id,'&Show Toolbar', '')
843        wx.EVT_MENU(self, id, self._on_toggle_toolbar)
844        self._menubar.Append(self._view_menu, '&View')
845       
846    def _add_menu_window(self):
847        """
848        add a menu window to the menu bar
849        Window menu
850        Attach a menu item for each panel in our
851        panel list that also appears in a plug-in.
852       
853        Only add the panel menu if there is only one perspective and
854        it has more than two panels.
855        Note: the first plug-in is always the plotting plug-in.
856        The first application
857        #plug-in is always the second one in the list.
858        """
859        self._window_menu = wx.Menu()
860        if self._plotting_plugin is not None:
861            for (menu, name) in self._plotting_plugin.populate_menu(self):
862                self._window_menu.AppendSubMenu(menu, name)
863        self._menubar.Append(self._window_menu, '&Graph')
864
865        style = self.__gui_style & GUIFRAME.PLOTTING_ON
866        if style == GUIFRAME.PLOTTING_ON:
867            self._window_menu.AppendSeparator()
868            id = wx.NewId()
869            preferences_menu = wx.Menu()
870            hint = "All plot panels will floating"
871            preferences_menu.Append(id, '&Float', hint)
872            wx.EVT_MENU(self, id, self.set_plotpanel_floating)
873            id = wx.NewId()
874            hint = "All plot panels will displayed within the frame"
875            preferences_menu.Append(id, '&Dock', hint)
876            wx.EVT_MENU(self, id, self.set_plotpanel_fixed)
877
878            self._window_menu.AppendSubMenu(preferences_menu,'&Preferences')
879        if self._window_menu.GetMenuItemCount() == 0:
880            pos = self._menubar.FindMenu('Graph')
881            self._menubar.Remove(pos)
882        #wx.EVT_MENU(self, id, self.show_preferences_panel)   
883        """
884        if len(self.plugins) == 2:
885            plug = self.plugins[1]
886            pers = plug.get_perspective()
887       
888            if len(pers) > 1:
889                self._window_menu = wx.Menu()
890                for item in self.panels:
891                    if item == 'default':
892                        continue
893                    panel = self.panels[item]
894                    if panel.window_name in pers:
895                        self._window_menu.Append(int(item),
896                                                  panel.window_caption,
897                                        "Show %s window" % panel.window_caption)
898                        wx.EVT_MENU(self, int(item), self.on_view)
899                self._menubar.Append(self._window_menu, '&Window')
900                """
901               
902    def _add_menu_application(self):
903        """
904       
905        # Attach a menu item for each defined perspective or application.
906        # Only add the perspective menu if there are more than one perspectives
907        add menu application
908        """
909        style = self.__gui_style & GUIFRAME.MULTIPLE_APPLICATIONS
910        if style == GUIFRAME.MULTIPLE_APPLICATIONS:
911            plug_data_count = False
912            plug_no_data_count = False
913            self._applications_menu = wx.Menu()
914            pos = 0
915            separator = self._applications_menu.AppendSeparator()
916            for plug in self.plugins:
917                if len(plug.get_perspective()) > 0:
918                    id = wx.NewId()
919                    if plug.use_data():
920                       
921                        self._applications_menu.InsertCheckItem(pos, id, plug.sub_menu,
922                                      "Switch to analysis: %s" % plug.sub_menu)
923                        plug_data_count = True
924                        pos += 1
925                    else:
926                        plug_no_data_count = True
927                        self._applications_menu.AppendCheckItem(id, plug.sub_menu,
928                                      "Switch to analysis: %s" % plug.sub_menu)
929                    wx.EVT_MENU(self, id, plug.on_perspective)
930            #self._applications_menu.
931            if (not plug_data_count or not plug_no_data_count):
932                self._applications_menu.RemoveItem(separator)
933            self._menubar.Append(self._applications_menu, '&Analysis')
934            self._check_applications_menu()
935           
936    def _populate_file_menu(self):
937        """
938        Insert menu item under file menu
939        """
940        for plugin in self.plugins:
941            if len(plugin.populate_file_menu()) > 0:
942                for item in plugin.populate_file_menu():
943                    m_name, m_hint, m_handler = item
944                    id = wx.NewId()
945                    self._file_menu.Append(id, m_name, m_hint)
946                    wx.EVT_MENU(self, id, m_handler)
947                self._file_menu.AppendSeparator()
948               
949    def _add_menu_file(self):
950        """
951        add menu file
952        """
953       
954         # File menu
955        self._file_menu = wx.Menu()
956        #append item from plugin under menu file if necessary
957        self._populate_file_menu()
958        style = self.__gui_style & GUIFRAME.DATALOADER_ON
959        style1 = self.__gui_style & GUIFRAME.MULTIPLE_APPLICATIONS
960        if style == GUIFRAME.DATALOADER_ON:
961            id = wx.NewId()
962            hint_load_file = "read all analysis states save previously"
963            self._save_appl_menu = self._file_menu.Append(id, 
964                                    '&Open Project', hint_load_file)
965            wx.EVT_MENU(self, id, self._on_open_state_project)
966           
967            if style1 == GUIFRAME.MULTIPLE_APPLICATIONS:
968                # some menu of plugin to be seen under file menu
969                hint_load_file = "Read a status files and load"
970                hint_load_file += " them into the analysis"
971                id = wx.NewId()
972                self._save_appl_menu = self._file_menu.Append(id, 
973                                        '&Open Analysis', hint_load_file)
974                wx.EVT_MENU(self, id, self._on_open_state_application)
975               
976            self._file_menu.AppendSeparator()
977            id = wx.NewId()
978            self._file_menu.Append(id, '&Save Project',
979                                 'Save the state of the whole analysis')
980           
981            wx.EVT_MENU(self, id, self._on_save_project)
982            if style1 == GUIFRAME.MULTIPLE_APPLICATIONS:
983                #self._file_menu.AppendSeparator()
984                id = wx.NewId()
985                self._save_appl_menu = self._file_menu.Append(id, 
986                                                          '&Save Analysis',
987                            'Save state of the current active analysis panel')
988                wx.EVT_MENU(self, id, self._on_save_application)
989           
990            self._file_menu.AppendSeparator()
991       
992        id = wx.NewId()
993        self._file_menu.Append(id, '&Quit', 'Exit') 
994        wx.EVT_MENU(self, id, self.Close)
995        # Add sub menus
996        self._menubar.Append(self._file_menu, '&File')
997       
998    def _add_menu_edit(self):
999        """
1000        add menu edit
1001        """
1002        # Edit Menu
1003        self._edit_menu = wx.Menu()
1004        self._edit_menu.Append(GUIFRAME_ID.UNDO_ID, '&Undo', 
1005                               'Undo the previous action')
1006        wx.EVT_MENU(self, GUIFRAME_ID.UNDO_ID, self.on_undo_panel)
1007        self._edit_menu.Append(GUIFRAME_ID.REDO_ID, '&Redo', 
1008                               'Redo the previous action')
1009        wx.EVT_MENU(self, GUIFRAME_ID.REDO_ID, self.on_redo_panel)
1010        self._edit_menu.AppendSeparator()
1011        self._edit_menu.Append(GUIFRAME_ID.PREVIEW_ID, '&Report',
1012                               'Preview current panel')
1013        wx.EVT_MENU(self, GUIFRAME_ID.PREVIEW_ID, self.on_preview_panel)
1014        self._edit_menu.Append(GUIFRAME_ID.PRINT_ID, '&Print',
1015                               'Print current panel')
1016        wx.EVT_MENU(self, GUIFRAME_ID.PRINT_ID, self.on_print_panel)
1017        self._edit_menu.Append(GUIFRAME_ID.RESET_ID, '&Reset', 
1018                               'Reset current panel')
1019        wx.EVT_MENU(self, GUIFRAME_ID.RESET_ID, self.on_reset_panel)
1020   
1021        self._menubar.Append(self._edit_menu,  '&Edit')
1022        self.enable_edit_menu()
1023       
1024    def get_style(self):
1025        """
1026        """
1027        return  self.__gui_style
1028   
1029    def _add_menu_data(self):
1030        """
1031        Add menu item item data to menu bar
1032        """
1033        if self._data_plugin is not None:
1034            menu_list = self._data_plugin.populate_menu(self)
1035            if menu_list:
1036                for (menu, name) in menu_list:
1037                    self._menubar.Append(menu, name)
1038       
1039                       
1040    def _on_toggle_toolbar(self, event=None):
1041        """
1042        hide or show toolbar
1043        """
1044        if self._toolbar is None:
1045            return
1046        if self._toolbar.IsShown():
1047            if self._toolbar_menu is not None:
1048                self._toolbar_menu.SetItemLabel('Show Toolbar')
1049            self._toolbar.Hide()
1050        else:
1051            if self._toolbar_menu is not None:
1052                self._toolbar_menu.SetItemLabel('Hide Toolbar')
1053            self._toolbar.Show()
1054        self._toolbar.Realize()
1055       
1056    def _on_status_event(self, evt):
1057        """
1058        Display status message
1059        """
1060        self.sb.set_status(event=evt)
1061       
1062    def on_view(self, evt):
1063        """
1064        A panel was selected to be shown. If it's not already
1065        shown, display it.
1066       
1067        :param evt: menu event
1068       
1069        """
1070        panel_id = str(evt.GetId())
1071        self.on_set_plot_focus(self.panels[panel_id])
1072        self.show_panel(evt.GetId(), 'on')     
1073        wx.CallLater(5, self.set_schedule(True))
1074        self.set_plot_unfocus()
1075       
1076    def on_close_welcome_panel(self):
1077        """
1078        Close the welcome panel
1079        """
1080        if self.defaultPanel is None:
1081            return 
1082        default_panel = self._mgr.GetPane(self.panels["default"].window_name)
1083        if default_panel.IsShown():
1084            default_panel.Hide()
1085            # Recover current perspective
1086            perspective = self._current_perspective
1087            perspective.on_perspective(event=None)
1088            self._mgr.Update()
1089            # Show toolbar
1090            style = self.__gui_style & GUIFRAME.TOOLBAR_ON
1091            if (style == GUIFRAME.TOOLBAR_ON) & (not self._toolbar.IsShown()):
1092                self._on_toggle_toolbar()
1093           
1094    def show_welcome_panel(self, event):
1095        """   
1096        Display the welcome panel
1097        """
1098        if self.defaultPanel is None:
1099            return 
1100        for id, panel in self.panels.iteritems():
1101            if id  ==  'default':
1102                # Show default panel
1103                if not self._mgr.GetPane(self.panels["default"].window_name).IsShown():
1104                    self._mgr.GetPane(self.panels["default"].window_name).Show(True)
1105            elif id == "data_panel":
1106                flag = self._mgr.GetPane(self.panels["data_panel"].window_name).IsShown()
1107                self._mgr.GetPane(self.panels["data_panel"].window_name).Show(flag)
1108            elif panel not in self.plot_panels.values() :
1109                self._mgr.GetPane(self.panels[id].window_name).IsShown()
1110                self._mgr.GetPane(self.panels[id].window_name).Hide()
1111            #if self._toolbar != None and not self._toolbar.IsShown():
1112            #    self._toolbar.Show(True)
1113            #self._on_toggle_toolbar()
1114
1115        self._mgr.Update()
1116       
1117    def show_panel(self, uid, show=None):
1118        """
1119        Shows the panel with the given id
1120       
1121        :param uid: unique ID number of the panel to show
1122       
1123        """
1124        ID = str(uid)
1125        config.printEVT("show_panel: %s" % ID)
1126        if ID in self.panels.keys():
1127            if not self._mgr.GetPane(self.panels[ID].window_name).IsShown(): 
1128                if show == 'on':
1129                    self._mgr.GetPane(self.panels[ID].window_name).Show()   
1130                elif self.panels[ID].window_caption.split(" ")[0] == \
1131                                                            "Residuals":
1132                    self._mgr.GetPane(self.panels[ID].window_name).Hide()
1133                else:
1134                    self._mgr.GetPane(self.panels[ID].window_name).Show()
1135                # Hide default panel
1136                self._mgr.GetPane(self.panels["default"].window_name).Hide()
1137        self._mgr.Update()     
1138        self._redraw_idle()
1139                   
1140    def hide_panel(self, uid):
1141        """
1142        hide panel
1143        """
1144        ID = str(uid)
1145        caption = self.panels[ID].window_caption
1146        config.printEVT("hide_panel: %s" % ID)
1147        if ID in self.panels.keys():
1148            if self._mgr.GetPane(self.panels[ID].window_name).IsShown():
1149                self._mgr.GetPane(self.panels[ID].window_name).Hide()
1150                if self._data_panel is not None and \
1151                            ID in self.plot_panels.keys():
1152                    self._data_panel.cb_plotpanel.Append(str(caption), p)
1153                # Hide default panel
1154                self._mgr.GetPane(self.panels["default"].window_name).Hide()
1155            self._mgr.Update()
1156               
1157    def delete_panel(self, uid):
1158        """
1159        delete panel given uid
1160        """
1161        ID = str(uid)
1162        config.printEVT("delete_panel: %s" % ID)
1163        caption = self.panels[ID].window_caption
1164        if ID in self.panels.keys():
1165            self.panel_on_focus = None
1166            panel = self.panels[ID]
1167            self._plotting_plugin.delete_panel(panel.group_id)
1168            self._mgr.DetachPane(panel)
1169            panel.Hide()
1170            panel.clear()
1171            panel.Close()
1172            self._mgr.Update()
1173            return 
1174            if ID in self.panels.keys():
1175                del self.panels[ID]
1176            if ID in self.plot_panels.keys():
1177                del self.plot_panels[ID]
1178            if self._data_panel is not None:
1179                ind = self._data_panel.cb_plotpanel.FindString(str(caption))
1180                if ind != wx.NOT_FOUND:
1181                   self._data_panel.cb_plotpanel.Delete(ind)
1182           
1183            self._mgr.Update()
1184 
1185     
1186    def clear_panel(self):
1187        """
1188        """
1189        for item in self.panels:
1190            try:
1191                self.panels[item].clear_panel()
1192            except:
1193                pass
1194           
1195    def create_gui_data(self, data, path=None):
1196        """
1197        """
1198        return self._data_manager.create_gui_data(data, path)
1199   
1200    def get_data(self, path):
1201        """
1202        """
1203        message = ""
1204        log_msg = ''
1205        output = []
1206        error_message = ""
1207        basename  = os.path.basename(path)
1208        root, extension = os.path.splitext(basename)
1209        if extension.lower() not in EXTENSIONS:
1210            log_msg = "File Loader cannot "
1211            log_msg += "load: %s\n" % str(basename)
1212            log_msg += "Try Data opening...."
1213            logging.info(log_msg)
1214            self.load_complete(output=output, error_message=error_message,
1215                   message=log_msg, path=path)   
1216            return
1217       
1218        #reading a state file
1219        for plug in self.plugins:
1220            reader, ext = plug.get_extensions()
1221            if reader is not None:
1222                #read the state of the single plugin
1223                if extension == ext:
1224                    reader.read(path)
1225                    return
1226                elif extension == APPLICATION_STATE_EXTENSION:
1227                    reader.read(path)
1228       
1229        style = self.__gui_style & GUIFRAME.MANAGER_ON
1230        if style == GUIFRAME.MANAGER_ON:
1231            if self._data_panel is not None:
1232                #data_state = self._data_manager.get_selected_data()
1233                #self._data_panel.load_data_list(data_state)
1234                self._mgr.GetPane(self._data_panel.window_name).Show(True)
1235     
1236    def load_from_cmd(self,  path):   
1237        """
1238        load data from cmd or application
1239        """ 
1240        if path is None:
1241            return
1242        else:
1243            path = os.path.abspath(path)
1244            if not os.path.isfile(path):
1245               return
1246        basename  = os.path.basename(path)
1247        root, extension = os.path.splitext(basename)
1248        if extension.lower() not in EXTENSIONS:
1249            self.load_data(path)
1250        else:
1251            self.load_state(path)
1252         
1253    def load_state(self, path):   
1254        """
1255        load data from command line or application
1256        """
1257        if path and (path is not None) and os.path.isfile(path):
1258            basename  = os.path.basename(path)
1259            if APPLICATION_STATE_EXTENSION is not None \
1260                and basename.endswith(APPLICATION_STATE_EXTENSION):
1261                #Hide current plot_panels i
1262                for ID in self.plot_panels.keys():
1263                    panel = self._mgr.GetPane(self.plot_panels[ID].window_name)
1264                    if panel.IsShown():
1265                        panel.Hide()
1266            self.get_data(path)
1267        if self.defaultPanel is not None and \
1268            self._mgr.GetPane(self.panels["default"].window_name).IsShown():
1269            self.on_close_welcome_panel()
1270           
1271    def load_data(self, path):
1272        """
1273        load data from command line
1274        """
1275        if not os.path.isfile(path):
1276            return
1277        basename  = os.path.basename(path)
1278        root, extension = os.path.splitext(basename)
1279        if extension.lower() in EXTENSIONS:
1280            log_msg = "Data Loader cannot "
1281            log_msg += "load: %s\n" % str(path)
1282            log_msg += "Try File opening ...."
1283            print log_msg
1284            return
1285        message = ""
1286        log_msg = ''
1287        output = {}
1288        error_message = ""
1289        try:
1290            print "Loading Data...:\n" + str(path) + "\n"
1291            temp =  self.loader.load(path)
1292            if temp.__class__.__name__ == "list":
1293                for item in temp:
1294                    data = self.create_gui_data(item, path)
1295                    output[data.id] = data
1296            else:
1297                data = self.create_gui_data(temp, path)
1298                output[data.id] = data
1299           
1300            self.add_data(data_list=output)
1301        except:
1302            error_message = "Error while loading"
1303            error_message += " Data from cmd:\n %s\n" % str(path)
1304            error_message += str(sys.exc_value) + "\n"
1305            print error_message
1306           
1307     
1308    def _on_open_state_application(self, event):
1309        """
1310        """
1311        path = None
1312        if self._default_save_location == None:
1313            self._default_save_location = os.getcwd()
1314       
1315        plug_wlist = self._on_open_state_app_helper()
1316        dlg = wx.FileDialog(self, 
1317                            "Choose a file", 
1318                            self._default_save_location, "",
1319                            plug_wlist)
1320        if dlg.ShowModal() == wx.ID_OK:
1321            path = dlg.GetPath()
1322            if path is not None:
1323                self._default_save_location = os.path.dirname(path)
1324        dlg.Destroy()
1325        self.load_state(path=path) 
1326   
1327    def _on_open_state_app_helper(self):
1328        """
1329        Helps '_on_open_state_application()' to find the extension of
1330        the current perspective/application
1331        """
1332        # No current perspective or no extension attr
1333        if self._current_perspective is None:
1334            return PLUGINS_WLIST
1335        try:
1336            # Find the extension of the perspective and get that as 1st item in list
1337            ind = None
1338            app_ext = self._current_perspective._extensions
1339            plug_wlist = config.PLUGINS_WLIST
1340            for ext in set(plug_wlist):
1341                if ext.count(app_ext) > 0:
1342                    ind = ext
1343                    break
1344            # Found the extension
1345            if ind != None:
1346                plug_wlist.remove(ind)
1347                plug_wlist.insert(0, ind)
1348                try:
1349                    plug_wlist ='|'.join(plug_wlist)
1350                except:
1351                    plug_wlist = ''
1352
1353        except:
1354            plug_wlist = PLUGINS_WLIST
1355           
1356        return plug_wlist
1357           
1358    def _on_open_state_project(self, event):
1359        """
1360        """
1361        path = None
1362        if self._default_save_location == None:
1363            self._default_save_location = os.getcwd()
1364       
1365        dlg = wx.FileDialog(self, 
1366                            "Choose a file", 
1367                            self._default_save_location, "",
1368                             APPLICATION_WLIST)
1369        if dlg.ShowModal() == wx.ID_OK:
1370            path = dlg.GetPath()
1371            if path is not None:
1372                self._default_save_location = os.path.dirname(path)
1373        dlg.Destroy()
1374       
1375        #try:   
1376        #    os.popen(path)
1377        #    #self.Close()
1378        #except:
1379        self.load_state(path=path)
1380       
1381    def _on_save_application(self, event):
1382        """
1383        save the state of the current active application
1384        """
1385        if self.cpanel_on_focus is not None:
1386            self.cpanel_on_focus.on_save(event)
1387           
1388    def _on_save_project(self, event):
1389        """
1390        save the state of the SansView as *.svs
1391        """
1392        ## Default file location for save
1393        self._default_save_location = os.getcwd()
1394        if self._current_perspective is  None:
1395            return
1396        reader, ext = self._current_perspective.get_extensions()
1397        path = None
1398        extension = '*' + APPLICATION_STATE_EXTENSION
1399        dlg = wx.FileDialog(self, "Save Project file",
1400                            self._default_save_location, "",
1401                             extension, 
1402                             wx.SAVE)
1403        if dlg.ShowModal() == wx.ID_OK:
1404            path = dlg.GetPath()
1405            self._default_save_location = os.path.dirname(path)
1406        else:
1407            return None
1408        dlg.Destroy()
1409        if path is None:
1410            return
1411        # default cansas xml doc
1412        doc = None
1413        for panel in self.panels.values():
1414            temp = panel.save_project(doc)
1415            if temp is not None:
1416                doc = temp
1417         
1418        # Write the XML document
1419        extens = APPLICATION_STATE_EXTENSION
1420        fName = os.path.splitext(path)[0] + extens
1421        if doc != None:
1422            fd = open(fName, 'w')
1423            fd.write(doc.toprettyxml())
1424            fd.close()
1425        else:
1426            msg = "%s cannot read %s\n" % (str(APPLICATION_NAME), str(path))
1427            logging.error(msg)
1428                   
1429    def on_save_helper(self, doc, reader, panel, path):
1430        """
1431        Save state into a file
1432        """
1433        try:
1434            if reader is not None:
1435                # case of a panel with multi-pages
1436                if hasattr(panel, "opened_pages"):
1437                    for uid, page in panel.opened_pages.iteritems():
1438                        data = page.get_data()
1439                        # state must be cloned
1440                        state = page.get_state().clone()
1441                        if data is not None:
1442                            new_doc = reader.write_toXML(data, state)
1443                            if doc != None and hasattr(doc, "firstChild"):
1444                                child = new_doc.firstChild.firstChild
1445                                doc.firstChild.appendChild(child) 
1446                            else:
1447                                doc = new_doc
1448                # case of only a panel
1449                else:
1450                    data = panel.get_data()
1451                    state = panel.get_state()
1452                    if data is not None:
1453                        new_doc = reader.write_toXML(data, state)
1454                        if doc != None and hasattr(doc, "firstChild"):
1455                            child = new_doc.firstChild.firstChild
1456                            doc.firstChild.appendChild(child) 
1457                        else:
1458                            doc = new_doc
1459        except: 
1460            raise
1461            #pass
1462
1463        return doc
1464
1465    def quit_guiframe(self):
1466        """
1467        Pop up message to make sure the user wants to quit the application
1468        """
1469        message = "Do you really want to quit \n"
1470        message += "this application?"
1471        dial = wx.MessageDialog(self, message, 'Question',
1472                           wx.YES_NO|wx.YES_DEFAULT|wx.ICON_QUESTION)
1473        if dial.ShowModal() == wx.ID_YES:
1474            return True
1475        else:
1476            return False   
1477       
1478    def Close(self, event=None):
1479        """
1480        Quit the application
1481        """
1482        #flag = self.quit_guiframe()
1483        if True:
1484            wx.Exit()
1485            sys.exit()
1486
1487    def _check_update(self, event=None): 
1488        """
1489        Check with the deployment server whether a new version
1490        of the application is available.
1491        A thread is started for the connecting with the server. The thread calls
1492        a call-back method when the current version number has been obtained.
1493        """
1494        if hasattr(config, "__update_URL__"):
1495            import version
1496            checker = version.VersionThread(config.__update_URL__,
1497                                            self._process_version,
1498                                            baggage=event==None)
1499            checker.start() 
1500   
1501    def _process_version(self, version, standalone=True):
1502        """
1503        Call-back method for the process of checking for updates.
1504        This methods is called by a VersionThread object once the current
1505        version number has been obtained. If the check is being done in the
1506        background, the user will not be notified unless there's an update.
1507       
1508        :param version: version string
1509        :param standalone: True of the update is being checked in
1510           the background, False otherwise.
1511           
1512        """
1513        try:
1514            if cmp(version, config.__version__) > 0:
1515                msg = "Version %s is available! See the Help "
1516                msg += "menu to download it." % version
1517                self.SetStatusText(msg)
1518                if not standalone:
1519                    import webbrowser
1520                    webbrowser.open(config.__download_page__)
1521            else:
1522                if not standalone:
1523                    msg = "You have the latest version"
1524                    msg += " of %s" % config.__appname__
1525                    self.SetStatusText(msg)
1526        except:
1527            msg = "guiframe: could not get latest application"
1528            msg += " version number\n  %s" % sys.exc_value
1529            logging.error(msg)
1530            if not standalone:
1531                msg = "Could not connect to the application server."
1532                msg += " Please try again later."
1533                self.SetStatusText(msg)
1534                   
1535    def _onAbout(self, evt):
1536        """
1537        Pop up the about dialog
1538       
1539        :param evt: menu event
1540       
1541        """
1542        if config._do_aboutbox:
1543            import aboutbox 
1544            dialog = aboutbox.DialogAbout(None, -1, "")
1545            dialog.ShowModal()           
1546           
1547    def set_manager(self, manager):
1548        """
1549        Sets the application manager for this frame
1550       
1551        :param manager: frame manager
1552        """
1553        self.app_manager = manager
1554       
1555    def post_init(self):
1556        """
1557        This initialization method is called after the GUI
1558        has been created and all plug-ins loaded. It calls
1559        the post_init() method of each plug-in (if it exists)
1560        so that final initialization can be done.
1561        """
1562        for item in self.plugins:
1563            if hasattr(item, "post_init"):
1564                item.post_init()
1565       
1566    def set_default_perspective(self):
1567        """
1568        Choose among the plugin the first plug-in that has
1569        "set_default_perspective" method and its return value is True will be
1570        as a default perspective when the welcome page is closed
1571        """
1572        for item in self.plugins:
1573            if hasattr(item, "set_default_perspective"):
1574                if item.set_default_perspective():
1575                    item.on_perspective(event=None)
1576                    return 
1577       
1578    def set_perspective(self, panels):
1579        """
1580        Sets the perspective of the GUI.
1581        Opens all the panels in the list, and closes
1582        all the others.
1583       
1584        :param panels: list of panels
1585        """
1586        style = self.__gui_style & GUIFRAME.TOOLBAR_ON
1587        if (style == GUIFRAME.TOOLBAR_ON) & (not self._toolbar.IsShown()):
1588            self._on_toggle_toolbar()
1589        for item in self.panels:
1590            # Check whether this is a sticky panel
1591            if hasattr(self.panels[item], "ALWAYS_ON"):
1592                if self.panels[item].ALWAYS_ON:
1593                    continue 
1594           
1595            if self.panels[item].window_name in panels:
1596                if not self._mgr.GetPane(self.panels[item].window_name).IsShown():
1597                    self._mgr.GetPane(self.panels[item].window_name).Show()
1598            else:
1599                # always show the data panel if enable
1600                style = self.__gui_style & GUIFRAME.MANAGER_ON
1601                if (style == GUIFRAME.MANAGER_ON) and self.panels[item] == self._data_panel:
1602                    if 'data_panel' in self.panels.keys():
1603                        flag = self._mgr.GetPane(self.panels['data_panel'].window_name).IsShown()
1604                        self._mgr.GetPane(self.panels['data_panel'].window_name).Show(flag)
1605                else:
1606                    if self._mgr.GetPane(self.panels[item].window_name).IsShown():
1607                        self._mgr.GetPane(self.panels[item].window_name).Hide()
1608               
1609        self._mgr.Update()
1610       
1611    def show_data_panel(self, event=None, action=True):
1612        """
1613        show the data panel
1614        """
1615        if self._data_panel_menu == None:
1616            return
1617        label = self._data_panel_menu.GetText()
1618        if label == 'Data Explorer ON':
1619            pane = self._mgr.GetPane(self.panels["data_panel"].window_name)
1620            #if not pane.IsShown():
1621            if action: 
1622                pane.Show(True)
1623                self._mgr.Update()
1624            self.__gui_style = self.__gui_style | GUIFRAME.MANAGER_ON
1625           
1626            self._data_panel_menu.SetText('Data Explorer OFF')
1627        else:
1628            pane = self._mgr.GetPane(self.panels["data_panel"].window_name)
1629            #if not pane.IsShown():
1630            if action:
1631                pane.Show(False)
1632                self._mgr.Update()
1633            self.__gui_style = self.__gui_style & (~GUIFRAME.MANAGER_ON)
1634            self._data_panel_menu.SetText('Data Explorer ON')
1635   
1636    def add_data_helper(self, data_list):
1637        """
1638        """
1639        if self._data_manager is not None:
1640            self._data_manager.add_data(data_list)
1641       
1642    def add_data(self, data_list):
1643        """
1644        receive a dictionary of data from loader
1645        store them its data manager if possible
1646        send to data the current active perspective if the data panel
1647        is not active.
1648        :param data_list: dictionary of data's ID and value Data
1649        """
1650        #Store data into manager
1651        self.add_data_helper(data_list)
1652        # set data in the data panel
1653        if self._data_panel is not None:
1654            data_state = self._data_manager.get_data_state(data_list.keys())
1655            self._data_panel.load_data_list(data_state)
1656        #if the data panel is shown wait for the user to press a button
1657        #to send data to the current perspective. if the panel is not
1658        #show  automatically send the data to the current perspective
1659        style = self.__gui_style & GUIFRAME.MANAGER_ON
1660        if style == GUIFRAME.MANAGER_ON:
1661            #wait for button press from the data panel to set_data
1662            if self._data_panel is not None:
1663                self._mgr.GetPane(self._data_panel.window_name).Show(True)
1664                self._mgr.Update() 
1665        else:
1666            #automatically send that to the current perspective
1667            self.set_data(data_id=data_list.keys())
1668            self.on_close_welcome_panel()
1669       
1670    def set_data(self, data_id, theory_id=None): 
1671        """
1672        set data to current perspective
1673        """
1674        list_data, _ = self._data_manager.get_by_id(data_id)
1675        if self._current_perspective is not None:
1676            for uid, panel in self.plot_panels.iteritems() :
1677                #panel = self.plot_panels[uid]
1678                window = self._mgr.GetPane(panel.window_name)
1679                # To hide all docked plot panels when set the data
1680                #if not window.IsFloating():
1681                #    self.hide_panel(uid)
1682            self._current_perspective.set_data(list_data.values())
1683            self.on_close_welcome_panel()
1684        else:
1685            msg = "Guiframe does not have a current perspective"
1686            logging.info(msg)
1687           
1688    def set_theory(self, state_id, theory_id=None):
1689        """
1690        """
1691        _, list_theory = self._data_manager.get_by_id(theory_id)
1692        if self._current_perspective is not None:
1693            try:
1694                self._current_perspective.set_theory(list_theory.values())
1695            except:
1696                msg = "Guiframe set_theory: \n" + str(sys.exc_value)
1697                logging.info(msg)
1698                wx.PostEvent(self, StatusEvent(status=msg, info="error"))
1699        else:
1700            msg = "Guiframe does not have a current perspective"
1701            logging.info(msg)
1702           
1703    def plot_data(self,  state_id, data_id=None,
1704                  theory_id=None, append=False):
1705        """
1706        send a list of data to plot
1707        """
1708        total_plot_list = []
1709        data_list, _ = self._data_manager.get_by_id(data_id)
1710        _, temp_list_theory = self._data_manager.get_by_id(theory_id)
1711        total_plot_list = data_list.values()
1712        for item in temp_list_theory.values():
1713            theory_data, theory_state = item
1714            total_plot_list.append(theory_data)
1715        GROUP_ID = wx.NewId()
1716        for new_plot in total_plot_list:
1717            if append:
1718                if self.panel_on_focus is None:
1719                    message = "cannot append plot. No plot panel on focus!"
1720                    message += "please click on any available plot to set focus"
1721                    wx.PostEvent(self, StatusEvent(status=message, 
1722                                                   info='warning'))
1723                    return 
1724                else:
1725                    if self.enable_add_data(new_plot):
1726                        new_plot.group_id = self.panel_on_focus.group_id
1727                    else:
1728                        message = "Only 1D Data can be append to"
1729                        message += " plot panel containing 1D data.\n"
1730                        message += "%s not be appended.\n" %str(new_plot.name)
1731                        message += "try new plot option.\n"
1732                        wx.PostEvent(self, StatusEvent(status=message, 
1733                                                   info='warning'))
1734            else:
1735                #if not append then new plot
1736                from sans.guiframe.dataFitting import Data2D
1737                if issubclass(Data2D, new_plot.__class__):
1738                    #for 2 D always plot in a separated new plot
1739                    new_plot.group_id = wx.NewId()
1740                else:
1741                    # plot all 1D in a new plot
1742                    new_plot.group_id = GROUP_ID
1743            title = "PLOT " + str(new_plot.title)
1744            wx.PostEvent(self, NewPlotEvent(plot=new_plot,
1745                                                  title=title,
1746                                                  group_id = new_plot.group_id))
1747           
1748    def remove_data(self, data_id, theory_id=None):
1749        """
1750        Delete data state if data_id is provide
1751        delete theory created with data of id data_id if theory_id is provide
1752        if delete all true: delete the all state
1753        else delete theory
1754        """
1755        for plug in self.plugins:
1756            plug.delete_data(data_id)
1757        total_plot_list = []
1758        data_list, _ = self._data_manager.get_by_id(data_id)
1759        _, temp_list_theory = self._data_manager.get_by_id(theory_id)
1760        total_plot_list = data_list.values()
1761        for item in temp_list_theory.values():
1762            theory_data, theory_state = item
1763            total_plot_list.append(theory_data)
1764        for new_plot in total_plot_list:
1765            id = new_plot.id
1766            for group_id in new_plot.list_group_id:
1767                wx.PostEvent(self, NewPlotEvent(id=id,
1768                                                   group_id=group_id,
1769                                                   action='remove'))
1770        self._data_manager.delete_data(data_id=data_id, 
1771                                       theory_id=theory_id)
1772           
1773       
1774    def set_current_perspective(self, perspective):
1775        """
1776        set the current active perspective
1777        """
1778        self._current_perspective = perspective
1779        name = "No current analysis selected"
1780        if self._current_perspective is not None:
1781            self._add_current_plugin_menu()
1782            for panel in self.panels.values():
1783                if hasattr(panel, 'CENTER_PANE') and panel.CENTER_PANE:
1784                    for name in self._current_perspective.get_perspective():
1785                        if name == panel.window_name:
1786                            panel.on_set_focus(event=None)
1787                            break               
1788            name = self._current_perspective.sub_menu
1789            if self._data_panel is not None:
1790                self._data_panel.set_active_perspective(name)
1791                self._check_applications_menu()
1792            #Set the SansView title
1793            self._set_title_name(name)
1794         
1795           
1796    def _set_title_name(self, name):
1797        """
1798        Set the SansView title w/ the current application name
1799       
1800        : param name: application name [string]
1801        """
1802        # Set SanView Window title w/ application anme
1803        title = self.title + "  - " + name + " -"
1804        self.SetTitle(title)
1805           
1806    def _check_applications_menu(self):
1807        """
1808        check the menu of the current application
1809        """
1810        if self._applications_menu is not None:
1811            for menu in self._applications_menu.GetMenuItems():
1812                if self._current_perspective is not None:
1813                    name = self._current_perspective.sub_menu
1814                    if menu.IsCheckable():
1815                        if menu.GetLabel() == name:
1816                            menu.Check(True)
1817                        else:
1818                             menu.Check(False) 
1819           
1820    def set_plotpanel_floating(self, event=None):
1821        """
1822        make the plot panel floatable
1823        """
1824        self.__gui_style &= (~GUIFRAME.FIXED_PANEL)
1825        self.__gui_style |= GUIFRAME.FLOATING_PANEL
1826        for p in self.panels.values():
1827            plot_panel = self._plotting_plugin.plot_panels.values()
1828            for p in self.panels.values():
1829                if p in plot_panel:
1830                    self._popup_floating_panel(p)
1831       
1832    def set_plotpanel_fixed(self, event=None):
1833        """
1834        make the plot panel fixed
1835        """
1836        self.__gui_style &= (~GUIFRAME.FLOATING_PANEL)
1837        self.__gui_style |= GUIFRAME.FIXED_PANEL
1838        plot_panel = []
1839        if self._plotting_plugin is not None:
1840            plot_panel = self._plotting_plugin.plot_panels.values()
1841            for p in self.panels.values():
1842                if p in plot_panel:
1843                    self._popup_fixed_panel(p)
1844                   
1845    def _popup_fixed_panel(self, p):
1846        """
1847        """
1848        style = self.__gui_style & GUIFRAME.FIXED_PANEL
1849        if style == GUIFRAME.FIXED_PANEL:
1850            self._mgr.GetPane(p.window_name).Dock()
1851            self._mgr.GetPane(p.window_name).Floatable()
1852            self._mgr.GetPane(p.window_name).Right()
1853            self._mgr.GetPane(p.window_name).TopDockable(False)
1854            self._mgr.GetPane(p.window_name).BottomDockable(False)
1855            self._mgr.GetPane(p.window_name).LeftDockable(False)
1856            self._mgr.GetPane(p.window_name).RightDockable(True)
1857            flag = self._mgr.GetPane(p.window_name).IsShown()
1858            self._mgr.GetPane(p.window_name).Show(flag)
1859            self._mgr.Update()
1860           
1861    def _popup_floating_panel(self, p):
1862        """
1863        """
1864        style = self.__gui_style &  GUIFRAME.FLOATING_PANEL
1865        if style == GUIFRAME.FLOATING_PANEL: 
1866            self._mgr.GetPane(p.window_name).Floatable(True)
1867            self._mgr.GetPane(p.window_name).Float()
1868            self._mgr.GetPane(p.window_name).Dockable(False)
1869            flag = self._mgr.GetPane(p.window_name).IsShown()
1870            self._mgr.GetPane(p.window_name).Show(flag)
1871            self._mgr.Update()
1872           
1873    def enable_add_data(self, new_plot):
1874        """
1875        Enable append data on a plot panel
1876        """
1877
1878        if self.panel_on_focus not in self._plotting_plugin.plot_panels.values():
1879            return
1880        is_theory = len(self.panel_on_focus.plots) <= 1 and \
1881            self.panel_on_focus.plots.values()[0].__class__.__name__ == "Theory1D"
1882           
1883        is_data2d = hasattr(new_plot, 'data')
1884       
1885        is_data1d = self.panel_on_focus.__class__.__name__ == "ModelPanel1D"\
1886            and self.panel_on_focus.group_id is not None
1887        has_meta_data = hasattr(new_plot, 'meta_data')
1888       
1889        #disable_add_data if the data is being recovered from  a saved state file.
1890        is_state_data = False
1891        if has_meta_data:
1892            if 'invstate' in new_plot.meta_data: is_state_data = True
1893            if  'prstate' in new_plot.meta_data: is_state_data = True
1894            if  'fitstate' in new_plot.meta_data: is_state_data = True
1895   
1896        return is_data1d and not is_data2d and not is_theory and not is_state_data
1897   
1898    def enable_edit_menu(self):
1899        """
1900        enable menu item under edit menu depending on the panel on focus
1901        """
1902        if self.cpanel_on_focus is not None and self._edit_menu is not None:
1903            flag = self.cpanel_on_focus.get_undo_flag()
1904            self._edit_menu.Enable(GUIFRAME_ID.UNDO_ID, flag)
1905            flag = self.cpanel_on_focus.get_redo_flag()
1906            self._edit_menu.Enable(GUIFRAME_ID.REDO_ID, flag)
1907            flag = self.cpanel_on_focus.get_print_flag()
1908            self._edit_menu.Enable(GUIFRAME_ID.PRINT_ID, flag)
1909            flag = self.cpanel_on_focus.get_preview_flag()
1910            self._edit_menu.Enable(GUIFRAME_ID.PREVIEW_ID, flag)
1911            flag = self.cpanel_on_focus.get_reset_flag()
1912            self._edit_menu.Enable(GUIFRAME_ID.RESET_ID, flag)
1913        else:
1914            flag = False
1915            self._edit_menu.Enable(GUIFRAME_ID.UNDO_ID, flag)
1916            self._edit_menu.Enable(GUIFRAME_ID.REDO_ID, flag)
1917            self._edit_menu.Enable(GUIFRAME_ID.PRINT_ID, flag)
1918            self._edit_menu.Enable(GUIFRAME_ID.PREVIEW_ID, flag)
1919            self._edit_menu.Enable(GUIFRAME_ID.RESET_ID, flag)
1920           
1921    def on_undo_panel(self, event=None):
1922        """
1923        undo previous action of the last panel on focus if possible
1924        """
1925        if self.cpanel_on_focus is not None:
1926            self.cpanel_on_focus.on_undo(event)
1927           
1928    def on_redo_panel(self, event=None):
1929        """
1930        redo the last cancel action done on the last panel on focus
1931        """
1932        if self.cpanel_on_focus is not None:
1933            self.cpanel_on_focus.on_redo(event)
1934           
1935    def on_bookmark_panel(self, event=None):
1936        """
1937        bookmark panel
1938        """
1939        if self.cpanel_on_focus is not None:
1940            self.cpanel_on_focus.on_bookmark(event)
1941           
1942    def append_bookmark(self, event=None):
1943        """
1944        Bookmark available information of the panel on focus
1945        """
1946        self._toolbar.append_bookmark(event)
1947           
1948    def on_save_panel(self, event=None):
1949        """
1950        save possible information on the current panel
1951        """
1952        if self.cpanel_on_focus is not None:
1953            self.cpanel_on_focus.on_save(event)
1954           
1955    def on_preview_panel(self, event=None):
1956        """
1957        preview information on the panel on focus
1958        """
1959        if self.cpanel_on_focus is not None:
1960            self.cpanel_on_focus.on_preview(event)
1961           
1962    def on_print_panel(self, event=None):
1963        """
1964        print available information on the last panel on focus
1965        """
1966        if self.cpanel_on_focus is not None:
1967            self.cpanel_on_focus.on_print(event)
1968           
1969    def on_zoom_panel(self, event=None):
1970        """
1971        zoom on the current panel if possible
1972        """
1973        if self.cpanel_on_focus is not None:
1974            self.cpanel_on_focus.on_zoom(event)
1975           
1976    def on_zoom_in_panel(self, event=None):
1977        """
1978        zoom in of the panel on focus
1979        """
1980        if self.cpanel_on_focus is not None:
1981            self.cpanel_on_focus.on_zoom_in(event)
1982           
1983    def on_zoom_out_panel(self, event=None):
1984        """
1985        zoom out on the panel on focus
1986        """
1987        if self.cpanel_on_focus is not None:
1988            self.cpanel_on_focus.on_zoom_out(event)
1989           
1990    def on_drag_panel(self, event=None):
1991        """
1992        drag apply to the panel on focus
1993        """
1994        if self.cpanel_on_focus is not None:
1995            self.cpanel_on_focus.on_drag(event)
1996           
1997    def on_reset_panel(self, event=None):
1998        """
1999        reset the current panel
2000        """
2001        if self.cpanel_on_focus is not None:
2002            self.cpanel_on_focus.on_reset(event)
2003           
2004    def enable_undo(self):
2005        """
2006        enable undo related control
2007        """
2008        if self.cpanel_on_focus is not None:
2009            self._toolbar.enable_undo(self.cpanel_on_focus)
2010           
2011    def enable_redo(self):
2012        """
2013        enable redo
2014        """
2015        if self.cpanel_on_focus is not None:
2016            self._toolbar.enable_redo(self.cpanel_on_focus)
2017           
2018    def enable_bookmark(self):
2019        """
2020        Bookmark
2021        """
2022        if self.cpanel_on_focus is not None:
2023            self._toolbar.enable_bookmark(self.cpanel_on_focus)
2024           
2025    def enable_save(self):
2026        """
2027        save
2028        """
2029        if self.cpanel_on_focus is not None:
2030            self._toolbar.enable_save(self.cpanel_on_focus)
2031           
2032    def enable_preview(self):
2033        """
2034        preview
2035        """
2036        if self.cpanel_on_focus is not None:
2037            self._toolbar.enable_preview(self.cpanel_on_focus)
2038           
2039    def enable_print(self):
2040        """
2041        print
2042        """
2043        if self.cpanel_on_focus is not None:
2044            self._toolbar.enable_print(self.cpanel_on_focus)
2045           
2046    def enable_zoom(self):
2047        """
2048        zoom
2049        """
2050        if self.cpanel_on_focus is not None:
2051            self._toolbar.enable_zoom(self.panel_on_focus)
2052           
2053    def enable_zoom_in(self):
2054        """
2055        zoom in
2056        """
2057        if self.cpanel_on_focus is not None:
2058            self._toolbar.enable_zoom_in(self.panel_on_focus)
2059           
2060    def enable_zoom_out(self):
2061        """
2062        zoom out
2063        """
2064        if self.cpanel_on_focus is not None:
2065            self._toolbar.enable_zoom_out(self.panel_on_focus)
2066           
2067    def enable_drag(self, event=None):
2068        """
2069        drag
2070        """
2071        if self.cpanel_on_focus is not None:
2072            self._toolbar.enable_drag(self.panel_on_focus)
2073           
2074    def enable_reset(self):
2075        """
2076        reset the current panel
2077        """
2078        if self.cpanel_on_focus is not None:
2079            self._toolbar.enable_reset(self.panel_on_focus)
2080
2081    def set_schedule_full_draw(self, panel=None, func='del'):
2082        """
2083        Add/subtract the schedule full draw list with the panel given
2084       
2085        :param panel: plot panel
2086        :param func: append or del [string]
2087        """
2088
2089        # append this panel in the schedule list if not in yet
2090        if func == 'append':
2091            if not panel in self.schedule_full_draw_list:
2092                self.schedule_full_draw_list.append(panel) 
2093        # remove this panel from schedule list
2094        elif func == 'del':
2095            if len(self.schedule_full_draw_list) > 0:
2096                if panel in self.schedule_full_draw_list:
2097                    self.schedule_full_draw_list.remove(panel)
2098
2099        # reset the schdule
2100        if len(self.schedule_full_draw_list) == 0:
2101            self.schedule = False
2102        else:
2103            self.schedule = True   
2104       
2105    def full_draw(self):
2106        """
2107        Draw the panels with axes in the schedule to full dwar list
2108        """
2109        count = len(self.schedule_full_draw_list)
2110        #if not self.schedule:
2111        if count < 1:
2112            self.set_schedule(False)
2113            return
2114        else:
2115            ind = 0
2116            # if any of the panel is shown do full_draw
2117            for panel in self.schedule_full_draw_list:
2118                ind += 1
2119                if self._mgr.GetPane(panel.window_name).IsShown():
2120                    break
2121                # otherwise, return
2122                if ind == count:
2123                    return
2124
2125        #Simple redraw only for a panel shown
2126        def f_draw(panel):
2127            """
2128            Draw A panel in the full dwar list
2129            """
2130            try:
2131                # This checking of GetCapture is to stop redrawing
2132                # while any panel is capture.
2133                if self.GetCapture() == None:
2134                    # draw if possible
2135                    panel.set_resizing(False)
2136                    panel.draw_plot()
2137                    # Check if the panel is not shown
2138                    if not self._mgr.GetPane(panel.window_name).IsShown():
2139                        self._mgr.GetPane(panel.window_name).Hide()
2140            except:
2141                pass
2142        #print self.callback,self.schedule,self.schedule_full_draw_list
2143       
2144        # Draw all panels       
2145        map(f_draw, self.schedule_full_draw_list)
2146       
2147        # Reset the attr 
2148        if len(self.schedule_full_draw_list) == 0:
2149            self.set_schedule(False)
2150        else:
2151            self.set_schedule(True)
2152        # do not update mgr
2153        #self._mgr.Update()
2154       
2155    def set_schedule(self, schedule=False): 
2156        """
2157        Set schedule
2158        """
2159        self.schedule = schedule
2160               
2161    def get_schedule(self): 
2162        """
2163        Get schedule
2164        """
2165        return self.schedule
2166   
2167    def on_set_plot_focus(self, panel):
2168        """
2169        Set focus on a plot panel
2170        """
2171        self.set_plot_unfocus()
2172        panel.on_set_focus(None) 
2173        # set focusing panel
2174        self.panel_on_focus = panel 
2175        self.set_panel_on_focus(None)
2176   
2177    def set_plot_unfocus(self): 
2178        """
2179        Un focus all plot panels
2180        """
2181        for plot in self.plot_panels.values():
2182            plot.on_kill_focus(None)
2183
2184    def _onDrawIdle(self, *args, **kwargs):
2185        """
2186        ReDraw with axes
2187        """
2188        # check if it is time to redraw
2189        if self.GetCapture() == None:
2190            # Draw plot, changes resizing too
2191            self.full_draw()
2192           
2193        # restart idle       
2194        self._redraw_idle(*args, **kwargs)
2195
2196           
2197    def _redraw_idle(self, *args, **kwargs):
2198        """
2199        Restart Idle
2200        """
2201        # restart idle   
2202        self.idletimer.Restart(55, *args, **kwargs)
2203
2204       
2205class DefaultPanel(wx.Panel, PanelBase):
2206    """
2207    Defines the API for a panels to work with
2208    the GUI manager
2209    """
2210    ## Internal nickname for the window, used by the AUI manager
2211    window_name = "default"
2212    ## Name to appear on the window title bar
2213    window_caption = "Welcome panel"
2214    ## Flag to tell the AUI manager to put this panel in the center pane
2215    CENTER_PANE = True
2216    def __init__(self, parent, *args, **kwds):
2217        wx.Panel.__init__(self, parent, *args, **kwds)
2218        PanelBase.__init__(self, parent)
2219   
2220
2221
2222# Toy application to test this Frame
2223class ViewApp(wx.App):
2224    """
2225    """
2226    def OnInit(self):
2227        """
2228        """
2229        pos, size = self.window_placement((GUIFRAME_WIDTH, GUIFRAME_HEIGHT))
2230        self.frame = ViewerFrame(parent=None, 
2231                                 title=APPLICATION_NAME, 
2232                                 pos=pos, 
2233                                 gui_style = DEFAULT_STYLE,
2234                                 size=size) 
2235        self.frame.Hide()
2236        self.s_screen = None
2237        try:
2238            # make sure the current dir is App dir when it starts
2239            temp_path = os.path.dirname(os.path.sys.path[0])
2240            os.chdir(temp_path)
2241        except:
2242            pass
2243        # Display a splash screen on top of the frame.
2244        if len(sys.argv) > 1 and '--time' in sys.argv[1:]:
2245            log_time("Starting to display the splash screen")
2246        try:
2247            if os.path.isfile(SPLASH_SCREEN_PATH):
2248                self.s_screen = self.display_splash_screen(parent=self.frame, 
2249                                        path=SPLASH_SCREEN_PATH)
2250            else:
2251                self.frame.Show()   
2252        except:
2253            if self.s_screen is not None:
2254                self.s_screen.Close()
2255            msg = "Cannot display splash screen\n"
2256            msg += str (sys.exc_value)
2257            logging.error(msg)
2258            self.frame.Show()
2259           
2260        if hasattr(self.frame, 'special'):
2261            self.frame.special.SetCurrent()
2262        self.SetTopWindow(self.frame)
2263        try:
2264            self.open_file()
2265        except:
2266            msg = "%s Could not load " % str(APPLICATION_NAME)
2267            msg += "input file from command line.\n"
2268            logging.error(msg)
2269        return True
2270
2271    def open_file(self):
2272        """
2273        open a state file at the start of the application
2274        """
2275        input_file = None
2276        if len(sys.argv) >= 2:
2277            cmd = sys.argv[0].lower()
2278            if os.path.isfile(cmd):
2279                basename  = os.path.basename(cmd)
2280                app_py = str(APPLICATION_NAME).lower() + '.py'
2281                app_exe = str(APPLICATION_NAME).lower() + '.exe'
2282                if basename.lower() in [app_py, app_exe]:
2283                    input_file = sys.argv[1]
2284        if input_file is None:
2285            return
2286        if self.frame is not None:
2287            self.frame.set_input_file(input_file=input_file)
2288         
2289           
2290    def set_manager(self, manager):
2291        """
2292        Sets a reference to the application manager
2293        of the GUI manager (Frame)
2294        """
2295        self.frame.set_manager(manager)
2296       
2297    def build_gui(self):
2298        """
2299        Build the GUI
2300        """
2301        #try to load file at the start
2302        try:
2303            self.open_file()
2304        except:
2305            raise
2306        self.frame.build_gui()
2307        #if self.s_screen is not None and self.s_screen.IsShown():
2308        #    self.s_screen.Close()
2309       
2310    def set_welcome_panel(self, panel_class):
2311        """
2312        Set the welcome panel
2313       
2314        :param panel_class: class of the welcome panel to be instantiated
2315       
2316        """
2317        self.frame.set_welcome_panel(panel_class)
2318       
2319    def add_perspective(self, perspective):
2320        """
2321        Manually add a perspective to the application GUI
2322        """
2323        self.frame.add_perspective(perspective)
2324   
2325    def window_placement(self, size):
2326        """
2327        Determines the position and size of the application frame such that it
2328        fits on the user's screen without obstructing (or being obstructed by)
2329        the Windows task bar.  The maximum initial size in pixels is bounded by
2330        WIDTH x HEIGHT.  For most monitors, the application
2331        will be centered on the screen; for very large monitors it will be
2332        placed on the left side of the screen.
2333        """
2334        window_width, window_height = size
2335        screen_size = wx.GetDisplaySize()
2336        window_height = window_height if screen_size[1]>window_height else screen_size[1]-50
2337        window_width  = window_width if screen_size[0]> window_width else screen_size[0]-50
2338        xpos = ypos = 0
2339
2340        # Note that when running Linux and using an Xming (X11) server on a PC
2341        # with a dual  monitor configuration, the reported display size may be
2342        # that of both monitors combined with an incorrect display count of 1.
2343        # To avoid displaying this app across both monitors, we check for
2344        # screen 'too big'.  If so, we assume a smaller width which means the
2345        # application will be placed towards the left hand side of the screen.
2346
2347        _, _, x, y = wx.Display().GetClientArea() # size excludes task bar
2348        if len(sys.argv) > 1 and '--platform' in sys.argv[1:]:
2349            w, h = wx.DisplaySize()  # size includes task bar area
2350        if x > 1920: x = 1280  # display on left side, not centered on screen
2351        if x > window_width:  xpos = (x - window_width)/2
2352        if y > window_height: ypos = (y - window_height)/2
2353
2354        # Return the suggested position and size for the application frame.
2355        return (xpos, ypos), (min(x, window_width), min(y, window_height))
2356   
2357    def display_splash_screen(self, parent, 
2358                              path=SPLASH_SCREEN_PATH):
2359        """Displays the splash screen.  It will exactly cover the main frame."""
2360       
2361        # Prepare the picture.  On a 2GHz intel cpu, this takes about a second.
2362        x, y = parent.GetSizeTuple()
2363        image = wx.Image(path, wx.BITMAP_TYPE_PNG)
2364        image.Rescale(SPLASH_SCREEN_WIDTH, 
2365                      SPLASH_SCREEN_HEIGHT, wx.IMAGE_QUALITY_HIGH)
2366        bm = image.ConvertToBitmap()
2367
2368        # Create and show the splash screen.  It will disappear only when the
2369        # program has entered the event loop AND either the timeout has expired
2370        # or the user has left clicked on the screen.  Thus any processing
2371        # performed in this routine (including sleeping) or processing in the
2372        # calling routine (including doing imports) will prevent the splash
2373        # screen from disappearing.
2374        #
2375        # Note that on Linux, the timeout appears to occur immediately in which
2376        # case the splash screen disappears upon entering the event loop.
2377        s_screen = wx.SplashScreen(bitmap=bm,
2378                         splashStyle=(wx.SPLASH_TIMEOUT|
2379                                              wx.SPLASH_CENTRE_ON_SCREEN),
2380                                 style=(wx.SIMPLE_BORDER|
2381                                        wx.FRAME_NO_TASKBAR|
2382                                        wx.STAY_ON_TOP),
2383                                       
2384                        milliseconds=SS_MAX_DISPLAY_TIME,
2385                        parent=parent,
2386                        id=wx.ID_ANY)
2387        from gui_statusbar import SPageStatusbar
2388        statusBar = SPageStatusbar(s_screen)
2389        s_screen.SetStatusBar(statusBar)
2390        s_screen.Bind(wx.EVT_CLOSE, self.on_close_splash_screen)
2391        s_screen.Show()
2392        return s_screen
2393       
2394       
2395    def on_close_splash_screen(self, event):
2396        """
2397        """
2398        self.frame.Show(True)
2399        event.Skip()
2400     
2401if __name__ == "__main__": 
2402    app = ViewApp(0)
2403    app.MainLoop()
2404
2405             
Note: See TracBrowser for help on using the repository browser.