source: sasview/guiframe/gui_manager.py @ a03d419

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 a03d419 was a03d419, checked in by Gervaise Alina <gervyh@…>, 13 years ago

add remove button

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