source: sasview/guiframe/gui_manager.py @ b113128

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

working on splashpage

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