source: sasview/guiframe/gui_manager.py @ 18a8359

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 18a8359 was 6d727ae, checked in by Jae Cho <jhjcho@…>, 13 years ago

moving a new feature (fast reacting plot panels) from branch

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