source: sasview/guiframe/gui_manager.py @ b92cbf61

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

trying to fix MAC active Show/Hide/On/Off? menu

  • Property mode set to 100644
File size: 92.6 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 plot panel\n"
1729                        message += "%s will be plot separetly\n" %str(new_plot.name)
1730                        wx.PostEvent(self, StatusEvent(status=message, 
1731                                                   info='warning'))
1732            else:
1733                #if not append then new plot
1734                from sans.guiframe.dataFitting import Data2D
1735                if (Data2D, new_plot.__class__):
1736                    #for 2 D always plot in a separated new plot
1737                    new_plot.group_id = wx.NewId()
1738                else:
1739                    # plot all 1D in a new plot
1740                    new_plot.group_id = GROUP_ID
1741            title = "PLOT " + str(new_plot.title)
1742            wx.PostEvent(self, NewPlotEvent(plot=new_plot,
1743                                                  title=title,
1744                                                  group_id = new_plot.group_id))
1745           
1746    def remove_data(self, data_id, theory_id=None):
1747        """
1748        Delete data state if data_id is provide
1749        delete theory created with data of id data_id if theory_id is provide
1750        if delete all true: delete the all state
1751        else delete theory
1752        """
1753        for plug in self.plugins:
1754            plug.delete_data(data_id)
1755        total_plot_list = []
1756        data_list, _ = self._data_manager.get_by_id(data_id)
1757        _, temp_list_theory = self._data_manager.get_by_id(theory_id)
1758        total_plot_list = data_list.values()
1759        for item in temp_list_theory.values():
1760            theory_data, theory_state = item
1761            total_plot_list.append(theory_data)
1762        for new_plot in total_plot_list:
1763            id = new_plot.id
1764            for group_id in new_plot.list_group_id:
1765                wx.PostEvent(self, NewPlotEvent(id=id,
1766                                                   group_id=group_id,
1767                                                   action='remove'))
1768        self._data_manager.delete_data(data_id=data_id, 
1769                                       theory_id=theory_id)
1770           
1771       
1772    def set_current_perspective(self, perspective):
1773        """
1774        set the current active perspective
1775        """
1776        self._current_perspective = perspective
1777        name = "No current analysis selected"
1778        if self._current_perspective is not None:
1779            self._add_current_plugin_menu()
1780            for panel in self.panels.values():
1781                if hasattr(panel, 'CENTER_PANE') and panel.CENTER_PANE:
1782                    for name in self._current_perspective.get_perspective():
1783                        if name == panel.window_name:
1784                            panel.on_set_focus(event=None)
1785                            break               
1786            name = self._current_perspective.sub_menu
1787            if self._data_panel is not None:
1788                self._data_panel.set_active_perspective(name)
1789                self._check_applications_menu()
1790            #Set the SansView title
1791            self._set_title_name(name)
1792         
1793           
1794    def _set_title_name(self, name):
1795        """
1796        Set the SansView title w/ the current application name
1797       
1798        : param name: application name [string]
1799        """
1800        # Set SanView Window title w/ application anme
1801        title = self.title + "  - " + name + " -"
1802        self.SetTitle(title)
1803           
1804    def _check_applications_menu(self):
1805        """
1806        check the menu of the current application
1807        """
1808        if self._applications_menu is not None:
1809            for menu in self._applications_menu.GetMenuItems():
1810                if self._current_perspective is not None:
1811                    name = self._current_perspective.sub_menu
1812                    if menu.IsCheckable():
1813                        if menu.GetLabel() == name:
1814                            menu.Check(True)
1815                        else:
1816                             menu.Check(False) 
1817           
1818    def set_plotpanel_floating(self, event=None):
1819        """
1820        make the plot panel floatable
1821        """
1822        self.__gui_style &= (~GUIFRAME.FIXED_PANEL)
1823        self.__gui_style |= GUIFRAME.FLOATING_PANEL
1824        for p in self.panels.values():
1825            plot_panel = self._plotting_plugin.plot_panels.values()
1826            for p in self.panels.values():
1827                if p in plot_panel:
1828                    self._popup_floating_panel(p)
1829       
1830    def set_plotpanel_fixed(self, event=None):
1831        """
1832        make the plot panel fixed
1833        """
1834        self.__gui_style &= (~GUIFRAME.FLOATING_PANEL)
1835        self.__gui_style |= GUIFRAME.FIXED_PANEL
1836        plot_panel = []
1837        if self._plotting_plugin is not None:
1838            plot_panel = self._plotting_plugin.plot_panels.values()
1839            for p in self.panels.values():
1840                if p in plot_panel:
1841                    self._popup_fixed_panel(p)
1842                   
1843    def _popup_fixed_panel(self, p):
1844        """
1845        """
1846        style = self.__gui_style & GUIFRAME.FIXED_PANEL
1847        if style == GUIFRAME.FIXED_PANEL:
1848            self._mgr.GetPane(p.window_name).Dock()
1849            self._mgr.GetPane(p.window_name).Floatable()
1850            self._mgr.GetPane(p.window_name).Right()
1851            self._mgr.GetPane(p.window_name).TopDockable(False)
1852            self._mgr.GetPane(p.window_name).BottomDockable(False)
1853            self._mgr.GetPane(p.window_name).LeftDockable(False)
1854            self._mgr.GetPane(p.window_name).RightDockable(True)
1855            flag = self._mgr.GetPane(p.window_name).IsShown()
1856            self._mgr.GetPane(p.window_name).Show(flag)
1857            self._mgr.Update()
1858           
1859    def _popup_floating_panel(self, p):
1860        """
1861        """
1862        style = self.__gui_style &  GUIFRAME.FLOATING_PANEL
1863        if style == GUIFRAME.FLOATING_PANEL: 
1864            self._mgr.GetPane(p.window_name).Floatable(True)
1865            self._mgr.GetPane(p.window_name).Float()
1866            self._mgr.GetPane(p.window_name).Dockable(False)
1867            flag = self._mgr.GetPane(p.window_name).IsShown()
1868            self._mgr.GetPane(p.window_name).Show(flag)
1869            self._mgr.Update()
1870           
1871    def enable_add_data(self, new_plot):
1872        """
1873        Enable append data on a plot panel
1874        """
1875
1876        if self.panel_on_focus not in self._plotting_plugin.plot_panels.values():
1877            return
1878        is_theory = len(self.panel_on_focus.plots) <= 1 and \
1879            self.panel_on_focus.plots.values()[0].__class__.__name__ == "Theory1D"
1880           
1881        is_data2d = hasattr(new_plot, 'data')
1882       
1883        is_data1d = self.panel_on_focus.__class__.__name__ == "ModelPanel1D"\
1884            and self.panel_on_focus.group_id is not None
1885        has_meta_data = hasattr(new_plot, 'meta_data')
1886       
1887        #disable_add_data if the data is being recovered from  a saved state file.
1888        is_state_data = False
1889        if has_meta_data:
1890            if 'invstate' in new_plot.meta_data: is_state_data = True
1891            if  'prstate' in new_plot.meta_data: is_state_data = True
1892            if  'fitstate' in new_plot.meta_data: is_state_data = True
1893   
1894        return is_data1d and not is_data2d and not is_theory and not is_state_data
1895   
1896    def enable_edit_menu(self):
1897        """
1898        enable menu item under edit menu depending on the panel on focus
1899        """
1900        if self.cpanel_on_focus is not None and self._edit_menu is not None:
1901            flag = self.cpanel_on_focus.get_undo_flag()
1902            self._edit_menu.Enable(GUIFRAME_ID.UNDO_ID, flag)
1903            flag = self.cpanel_on_focus.get_redo_flag()
1904            self._edit_menu.Enable(GUIFRAME_ID.REDO_ID, flag)
1905            flag = self.cpanel_on_focus.get_print_flag()
1906            self._edit_menu.Enable(GUIFRAME_ID.PRINT_ID, flag)
1907            flag = self.cpanel_on_focus.get_preview_flag()
1908            self._edit_menu.Enable(GUIFRAME_ID.PREVIEW_ID, flag)
1909            flag = self.cpanel_on_focus.get_reset_flag()
1910            self._edit_menu.Enable(GUIFRAME_ID.RESET_ID, flag)
1911        else:
1912            flag = False
1913            self._edit_menu.Enable(GUIFRAME_ID.UNDO_ID, flag)
1914            self._edit_menu.Enable(GUIFRAME_ID.REDO_ID, flag)
1915            self._edit_menu.Enable(GUIFRAME_ID.PRINT_ID, flag)
1916            self._edit_menu.Enable(GUIFRAME_ID.PREVIEW_ID, flag)
1917            self._edit_menu.Enable(GUIFRAME_ID.RESET_ID, flag)
1918           
1919    def on_undo_panel(self, event=None):
1920        """
1921        undo previous action of the last panel on focus if possible
1922        """
1923        if self.cpanel_on_focus is not None:
1924            self.cpanel_on_focus.on_undo(event)
1925           
1926    def on_redo_panel(self, event=None):
1927        """
1928        redo the last cancel action done on the last panel on focus
1929        """
1930        if self.cpanel_on_focus is not None:
1931            self.cpanel_on_focus.on_redo(event)
1932           
1933    def on_bookmark_panel(self, event=None):
1934        """
1935        bookmark panel
1936        """
1937        if self.cpanel_on_focus is not None:
1938            self.cpanel_on_focus.on_bookmark(event)
1939           
1940    def append_bookmark(self, event=None):
1941        """
1942        Bookmark available information of the panel on focus
1943        """
1944        self._toolbar.append_bookmark(event)
1945           
1946    def on_save_panel(self, event=None):
1947        """
1948        save possible information on the current panel
1949        """
1950        if self.cpanel_on_focus is not None:
1951            self.cpanel_on_focus.on_save(event)
1952           
1953    def on_preview_panel(self, event=None):
1954        """
1955        preview information on the panel on focus
1956        """
1957        if self.cpanel_on_focus is not None:
1958            self.cpanel_on_focus.on_preview(event)
1959           
1960    def on_print_panel(self, event=None):
1961        """
1962        print available information on the last panel on focus
1963        """
1964        if self.cpanel_on_focus is not None:
1965            self.cpanel_on_focus.on_print(event)
1966           
1967    def on_zoom_panel(self, event=None):
1968        """
1969        zoom on the current panel if possible
1970        """
1971        if self.cpanel_on_focus is not None:
1972            self.cpanel_on_focus.on_zoom(event)
1973           
1974    def on_zoom_in_panel(self, event=None):
1975        """
1976        zoom in of the panel on focus
1977        """
1978        if self.cpanel_on_focus is not None:
1979            self.cpanel_on_focus.on_zoom_in(event)
1980           
1981    def on_zoom_out_panel(self, event=None):
1982        """
1983        zoom out on the panel on focus
1984        """
1985        if self.cpanel_on_focus is not None:
1986            self.cpanel_on_focus.on_zoom_out(event)
1987           
1988    def on_drag_panel(self, event=None):
1989        """
1990        drag apply to the panel on focus
1991        """
1992        if self.cpanel_on_focus is not None:
1993            self.cpanel_on_focus.on_drag(event)
1994           
1995    def on_reset_panel(self, event=None):
1996        """
1997        reset the current panel
1998        """
1999        if self.cpanel_on_focus is not None:
2000            self.cpanel_on_focus.on_reset(event)
2001           
2002    def enable_undo(self):
2003        """
2004        enable undo related control
2005        """
2006        if self.cpanel_on_focus is not None:
2007            self._toolbar.enable_undo(self.cpanel_on_focus)
2008           
2009    def enable_redo(self):
2010        """
2011        enable redo
2012        """
2013        if self.cpanel_on_focus is not None:
2014            self._toolbar.enable_redo(self.cpanel_on_focus)
2015           
2016    def enable_bookmark(self):
2017        """
2018        Bookmark
2019        """
2020        if self.cpanel_on_focus is not None:
2021            self._toolbar.enable_bookmark(self.cpanel_on_focus)
2022           
2023    def enable_save(self):
2024        """
2025        save
2026        """
2027        if self.cpanel_on_focus is not None:
2028            self._toolbar.enable_save(self.cpanel_on_focus)
2029           
2030    def enable_preview(self):
2031        """
2032        preview
2033        """
2034        if self.cpanel_on_focus is not None:
2035            self._toolbar.enable_preview(self.cpanel_on_focus)
2036           
2037    def enable_print(self):
2038        """
2039        print
2040        """
2041        if self.cpanel_on_focus is not None:
2042            self._toolbar.enable_print(self.cpanel_on_focus)
2043           
2044    def enable_zoom(self):
2045        """
2046        zoom
2047        """
2048        if self.cpanel_on_focus is not None:
2049            self._toolbar.enable_zoom(self.panel_on_focus)
2050           
2051    def enable_zoom_in(self):
2052        """
2053        zoom in
2054        """
2055        if self.cpanel_on_focus is not None:
2056            self._toolbar.enable_zoom_in(self.panel_on_focus)
2057           
2058    def enable_zoom_out(self):
2059        """
2060        zoom out
2061        """
2062        if self.cpanel_on_focus is not None:
2063            self._toolbar.enable_zoom_out(self.panel_on_focus)
2064           
2065    def enable_drag(self, event=None):
2066        """
2067        drag
2068        """
2069        if self.cpanel_on_focus is not None:
2070            self._toolbar.enable_drag(self.panel_on_focus)
2071           
2072    def enable_reset(self):
2073        """
2074        reset the current panel
2075        """
2076        if self.cpanel_on_focus is not None:
2077            self._toolbar.enable_reset(self.panel_on_focus)
2078
2079    def set_schedule_full_draw(self, panel=None, func='del'):
2080        """
2081        Add/subtract the schedule full draw list with the panel given
2082       
2083        :param panel: plot panel
2084        :param func: append or del [string]
2085        """
2086
2087        # append this panel in the schedule list if not in yet
2088        if func == 'append':
2089            if not panel in self.schedule_full_draw_list:
2090                self.schedule_full_draw_list.append(panel) 
2091        # remove this panel from schedule list
2092        elif func == 'del':
2093            if len(self.schedule_full_draw_list) > 0:
2094                if panel in self.schedule_full_draw_list:
2095                    self.schedule_full_draw_list.remove(panel)
2096
2097        # reset the schdule
2098        if len(self.schedule_full_draw_list) == 0:
2099            self.schedule = False
2100        else:
2101            self.schedule = True   
2102       
2103    def full_draw(self):
2104        """
2105        Draw the panels with axes in the schedule to full dwar list
2106        """
2107        count = len(self.schedule_full_draw_list)
2108        #if not self.schedule:
2109        if count < 1:
2110            self.set_schedule(False)
2111            return
2112        else:
2113            ind = 0
2114            # if any of the panel is shown do full_draw
2115            for panel in self.schedule_full_draw_list:
2116                ind += 1
2117                if self._mgr.GetPane(panel.window_name).IsShown():
2118                    break
2119                # otherwise, return
2120                if ind == count:
2121                    return
2122
2123        #Simple redraw only for a panel shown
2124        def f_draw(panel):
2125            """
2126            Draw A panel in the full dwar list
2127            """
2128            try:
2129                # This checking of GetCapture is to stop redrawing
2130                # while any panel is capture.
2131                if self.GetCapture() == None:
2132                    # draw if possible
2133                    panel.set_resizing(False)
2134                    panel.draw_plot()
2135                    # Check if the panel is not shown
2136                    if not self._mgr.GetPane(panel.window_name).IsShown():
2137                        self._mgr.GetPane(panel.window_name).Hide()
2138            except:
2139                pass
2140        #print self.callback,self.schedule,self.schedule_full_draw_list
2141       
2142        # Draw all panels       
2143        map(f_draw, self.schedule_full_draw_list)
2144       
2145        # Reset the attr 
2146        if len(self.schedule_full_draw_list) == 0:
2147            self.set_schedule(False)
2148        else:
2149            self.set_schedule(True)
2150        # do not update mgr
2151        #self._mgr.Update()
2152       
2153    def set_schedule(self, schedule=False): 
2154        """
2155        Set schedule
2156        """
2157        self.schedule = schedule
2158               
2159    def get_schedule(self): 
2160        """
2161        Get schedule
2162        """
2163        return self.schedule
2164   
2165    def on_set_plot_focus(self, panel):
2166        """
2167        Set focus on a plot panel
2168        """
2169        self.set_plot_unfocus()
2170        panel.on_set_focus(None) 
2171        # set focusing panel
2172        self.panel_on_focus = panel 
2173        self.set_panel_on_focus(None)
2174   
2175    def set_plot_unfocus(self): 
2176        """
2177        Un focus all plot panels
2178        """
2179        for plot in self.plot_panels.values():
2180            plot.on_kill_focus(None)
2181
2182    def _onDrawIdle(self, *args, **kwargs):
2183        """
2184        ReDraw with axes
2185        """
2186        # check if it is time to redraw
2187        if self.GetCapture() == None:
2188            # Draw plot, changes resizing too
2189            self.full_draw()
2190           
2191        # restart idle       
2192        self._redraw_idle(*args, **kwargs)
2193
2194           
2195    def _redraw_idle(self, *args, **kwargs):
2196        """
2197        Restart Idle
2198        """
2199        # restart idle   
2200        self.idletimer.Restart(55, *args, **kwargs)
2201
2202       
2203class DefaultPanel(wx.Panel, PanelBase):
2204    """
2205    Defines the API for a panels to work with
2206    the GUI manager
2207    """
2208    ## Internal nickname for the window, used by the AUI manager
2209    window_name = "default"
2210    ## Name to appear on the window title bar
2211    window_caption = "Welcome panel"
2212    ## Flag to tell the AUI manager to put this panel in the center pane
2213    CENTER_PANE = True
2214    def __init__(self, parent, *args, **kwds):
2215        wx.Panel.__init__(self, parent, *args, **kwds)
2216        PanelBase.__init__(self, parent)
2217   
2218
2219
2220# Toy application to test this Frame
2221class ViewApp(wx.App):
2222    """
2223    """
2224    def OnInit(self):
2225        """
2226        """
2227        pos, size = self.window_placement((GUIFRAME_WIDTH, GUIFRAME_HEIGHT))
2228        self.frame = ViewerFrame(parent=None, 
2229                                 title=APPLICATION_NAME, 
2230                                 pos=pos, 
2231                                 gui_style = DEFAULT_STYLE,
2232                                 size=size) 
2233        self.frame.Hide()
2234        self.s_screen = None
2235        try:
2236            # make sure the current dir is App dir when it starts
2237            temp_path = os.path.dirname(os.path.sys.path[0]) 
2238            os.chdir(temp_path)
2239        except:
2240            pass
2241        # Display a splash screen on top of the frame.
2242        if len(sys.argv) > 1 and '--time' in sys.argv[1:]:
2243            log_time("Starting to display the splash screen")
2244       
2245        try:
2246            if os.path.isfile(SPLASH_SCREEN_PATH):
2247                self.s_screen = self.display_splash_screen(parent=self.frame, 
2248                                        path=SPLASH_SCREEN_PATH)
2249            else:
2250                self.frame.Show()   
2251        except:
2252            if self.s_screen is not None:
2253                self.s_screen.Close()
2254            msg = "Cannot display splash screen\n"
2255            msg += str (sys.exc_value)
2256            logging.error(msg)
2257            self.frame.Show()
2258           
2259        if hasattr(self.frame, 'special'):
2260            self.frame.special.SetCurrent()
2261        self.SetTopWindow(self.frame)
2262        try:
2263            self.open_file()
2264        except:
2265            msg = "%s Could not load " % str(APPLICATION_NAME)
2266            msg += "input file from command line.\n"
2267            logging.error(msg)
2268        return True
2269
2270    def open_file(self):
2271        """
2272        open a state file at the start of the application
2273        """
2274        input_file = None
2275        if len(sys.argv) >= 2:
2276            cmd = sys.argv[0].lower()
2277            if os.path.isfile(cmd):
2278                basename  = os.path.basename(cmd)
2279                app_py = str(APPLICATION_NAME).lower() + '.py'
2280                app_exe = str(APPLICATION_NAME).lower() + '.exe'
2281                if basename.lower() in [app_py, app_exe]:
2282                    input_file = sys.argv[1]
2283        if input_file is None:
2284            return
2285        if self.frame is not None:
2286            self.frame.set_input_file(input_file=input_file)
2287         
2288           
2289    def set_manager(self, manager):
2290        """
2291        Sets a reference to the application manager
2292        of the GUI manager (Frame)
2293        """
2294        self.frame.set_manager(manager)
2295       
2296    def build_gui(self):
2297        """
2298        Build the GUI
2299        """
2300        #try to load file at the start
2301        try:
2302            self.open_file()
2303        except:
2304            raise
2305        self.frame.build_gui()
2306        #if self.s_screen is not None and self.s_screen.IsShown():
2307        #    self.s_screen.Close()
2308       
2309    def set_welcome_panel(self, panel_class):
2310        """
2311        Set the welcome panel
2312       
2313        :param panel_class: class of the welcome panel to be instantiated
2314       
2315        """
2316        self.frame.set_welcome_panel(panel_class)
2317       
2318    def add_perspective(self, perspective):
2319        """
2320        Manually add a perspective to the application GUI
2321        """
2322        self.frame.add_perspective(perspective)
2323   
2324    def window_placement(self, size):
2325        """
2326        Determines the position and size of the application frame such that it
2327        fits on the user's screen without obstructing (or being obstructed by)
2328        the Windows task bar.  The maximum initial size in pixels is bounded by
2329        WIDTH x HEIGHT.  For most monitors, the application
2330        will be centered on the screen; for very large monitors it will be
2331        placed on the left side of the screen.
2332        """
2333        window_width, window_height = size
2334        screen_size = wx.GetDisplaySize()
2335        window_height = window_height if screen_size[1]>window_height else screen_size[1]-50
2336        window_width  = window_width if screen_size[0]> window_width else screen_size[0]-50
2337        xpos = ypos = 0
2338
2339        # Note that when running Linux and using an Xming (X11) server on a PC
2340        # with a dual  monitor configuration, the reported display size may be
2341        # that of both monitors combined with an incorrect display count of 1.
2342        # To avoid displaying this app across both monitors, we check for
2343        # screen 'too big'.  If so, we assume a smaller width which means the
2344        # application will be placed towards the left hand side of the screen.
2345
2346        _, _, x, y = wx.Display().GetClientArea() # size excludes task bar
2347        if len(sys.argv) > 1 and '--platform' in sys.argv[1:]:
2348            w, h = wx.DisplaySize()  # size includes task bar area
2349        if x > 1920: x = 1280  # display on left side, not centered on screen
2350        if x > window_width:  xpos = (x - window_width)/2
2351        if y > window_height: ypos = (y - window_height)/2
2352
2353        # Return the suggested position and size for the application frame.
2354        return (xpos, ypos), (min(x, window_width), min(y, window_height))
2355   
2356    def display_splash_screen(self, parent, 
2357                              path=SPLASH_SCREEN_PATH):
2358        """Displays the splash screen.  It will exactly cover the main frame."""
2359       
2360        # Prepare the picture.  On a 2GHz intel cpu, this takes about a second.
2361        x, y = parent.GetSizeTuple()
2362        image = wx.Image(path, wx.BITMAP_TYPE_PNG)
2363        image.Rescale(SPLASH_SCREEN_WIDTH, 
2364                      SPLASH_SCREEN_HEIGHT, wx.IMAGE_QUALITY_HIGH)
2365        bm = image.ConvertToBitmap()
2366
2367        # Create and show the splash screen.  It will disappear only when the
2368        # program has entered the event loop AND either the timeout has expired
2369        # or the user has left clicked on the screen.  Thus any processing
2370        # performed in this routine (including sleeping) or processing in the
2371        # calling routine (including doing imports) will prevent the splash
2372        # screen from disappearing.
2373        #
2374        # Note that on Linux, the timeout appears to occur immediately in which
2375        # case the splash screen disappears upon entering the event loop.
2376        s_screen = wx.SplashScreen(bitmap=bm,
2377                         splashStyle=(wx.SPLASH_TIMEOUT|
2378                                              wx.SPLASH_CENTRE_ON_SCREEN),
2379                                 style=(wx.SIMPLE_BORDER|
2380                                        wx.FRAME_NO_TASKBAR|
2381                                        wx.STAY_ON_TOP),
2382                                       
2383                        milliseconds=SS_MAX_DISPLAY_TIME,
2384                        parent=parent,
2385                        id=wx.ID_ANY)
2386        from gui_statusbar import SPageStatusbar
2387        statusBar = SPageStatusbar(s_screen)
2388        s_screen.SetStatusBar(statusBar)
2389        s_screen.Bind(wx.EVT_CLOSE, self.on_close_splash_screen)
2390        s_screen.Show()
2391        return s_screen
2392       
2393       
2394    def on_close_splash_screen(self, event):
2395        """
2396        """
2397        self.frame.Show(True)
2398        event.Skip()
2399     
2400if __name__ == "__main__": 
2401    app = ViewApp(0)
2402    app.MainLoop()
2403
2404             
Note: See TracBrowser for help on using the repository browser.