source: sasview/guiframe/gui_manager.py @ 0f8f831

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

added save button in toolbar, and repositioned menu items

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