source: sasview/guiframe/gui_manager.py @ ec489f5

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

put original sansview save state

  • Property mode set to 100644
File size: 54.2 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_ADD_MANY_DATA
41from sans.guiframe.events import StatusEvent
42from sans.guiframe.events import NewPlotEvent
43from sans.guiframe.gui_style import *
44from sans.guiframe.events import NewLoadedDataEvent
45from sans.guiframe.data_panel import DataPanel
46
47STATE_FILE_EXT = ['.inv', '.fitv', '.prv']
48DATA_MANAGER = False
49AUTO_PLOT = False
50AUTO_SET_DATA = True
51PLOPANEL_WIDTH = 400
52PLOPANEL_HEIGTH = 400
53GUIFRAME_WIDTH = 1000
54GUIFRAME_HEIGHT = 800
55PROG_SPLASH_SCREEN = "images/danse_logo.png" 
56
57class ViewerFrame(wx.Frame):
58    """
59    Main application frame
60    """
61   
62    def __init__(self, parent, title, 
63                 size=(GUIFRAME_WIDTH, GUIFRAME_HEIGHT),
64                 gui_style=GUIFRAME.DEFAULT_STYLE, 
65                 pos=wx.DefaultPosition):
66        """
67        Initialize the Frame object
68        """
69       
70        wx.Frame.__init__(self, parent=parent, title=title, pos=pos,size=size)
71        # Preferred window size
72        self._window_width, self._window_height = size
73        self.__gui_style = gui_style
74       
75        # Logging info
76        logging.basicConfig(level=logging.DEBUG,
77                    format='%(asctime)s %(levelname)s %(message)s',
78                    filename='sans_app.log',
79                    filemode='w')       
80        path = os.path.dirname(__file__)
81        temp_path = os.path.join(path,'images')
82        ico_file = os.path.join(temp_path,'ball.ico')
83        if os.path.isfile(ico_file):
84            self.SetIcon(wx.Icon(ico_file, wx.BITMAP_TYPE_ICO))
85        else:
86            temp_path = os.path.join(os.getcwd(),'images')
87            ico_file = os.path.join(temp_path,'ball.ico')
88            if os.path.isfile(ico_file):
89                self.SetIcon(wx.Icon(ico_file, wx.BITMAP_TYPE_ICO))
90       
91        ## Application manager
92        self.app_manager = None
93        self._mgr = None
94        #add current perpsective
95        self._current_perspective = None
96        self._plotting_plugin = None
97        self._data_plugin = None
98        #Menu bar and item
99        self._menubar = None
100        self._file_menu = None
101        self._data_menu = None
102        self._window_menu = None
103        self._window_menu = None
104        self._help_menu = None
105        self._tool_menu = None
106        self._plugin_menu_pos = -1
107        ## Find plug-ins
108        # Modify this so that we can specify the directory to look into
109        self.plugins = []
110        #add local plugin
111        self.plugins += self._get_local_plugins()
112        self.plugins += self._find_plugins()
113        ## List of panels
114        self.panels = {}
115
116        # Default locations
117        self._default_save_location = os.getcwd()       
118       
119        # Welcome panel
120        self.defaultPanel = None
121        #panel on focus
122        self.panel_on_focus = None
123         #data manager
124        from data_manager import DataManager
125        self._data_manager = DataManager()
126        self._data_panel = DataPanel(parent=self)
127        if self.panel_on_focus is not None:
128            self._data_panel.set_panel_on_focus(self.panel_on_focus.window_caption)
129        # Check for update
130        #self._check_update(None)
131        # Register the close event so it calls our own method
132        wx.EVT_CLOSE(self, self.Close)
133        # Register to status events
134        self.Bind(EVT_STATUS, self._on_status_event)
135        #Register add extra data on the same panel event on load
136        self.Bind(EVT_ADD_MANY_DATA, self.set_panel_on_focus)
137       
138    def set_panel_on_focus(self, event):
139        """
140        Store reference to the last panel on focus
141        """
142        self.panel_on_focus = event.panel
143        if self.panel_on_focus is not None and self._data_panel is not None:
144            self._data_panel.set_panel_on_focus(self.panel_on_focus.window_name)
145           
146    def build_gui(self):
147        """
148        """
149        # Set up the layout
150        self._setup_layout()
151       
152        # Set up the menu
153        self._setup_menus()
154        #self.Fit()
155        #self._check_update(None)
156             
157    def _setup_layout(self):
158        """
159        Set up the layout
160        """
161        # Status bar
162        from gui_statusbar import StatusBar
163        self.sb = StatusBar(self, wx.ID_ANY)
164        self.SetStatusBar(self.sb)
165        # Add panel
166        default_flag = wx.aui.AUI_MGR_DEFAULT| wx.aui.AUI_MGR_ALLOW_ACTIVE_PANE
167        self._mgr = wx.aui.AuiManager(self, flags=default_flag)
168   
169        # Load panels
170        self._load_panels()
171        self.set_default_perspective()
172        self._mgr.Update()
173       
174    def SetStatusText(self, *args, **kwds):
175        """
176        """
177        number = self.sb.get_msg_position()
178        wx.Frame.SetStatusText(number=number, *args, **kwds)
179       
180    def PopStatusText(self, *args, **kwds):
181        """
182        """
183        field = self.sb.get_msg_position()
184        wx.Frame.PopStatusText(field=field)
185       
186    def PushStatusText(self, *args, **kwds):
187        """
188        """
189        field = self.sb.get_msg_position()
190        wx.Frame.PushStatusText(self, field=field, string=string)
191
192    def add_perspective(self, plugin):
193        """
194        Add a perspective if it doesn't already
195        exist.
196        """
197        is_loaded = False
198        for item in self.plugins:
199            if plugin.__class__ == item.__class__:
200                msg = "Plugin %s already loaded" % plugin.__class__.__name__
201                logging.info(msg)
202                is_loaded = True   
203        if not is_loaded:
204            self.plugins.append(plugin)
205     
206    def _get_local_plugins(self):
207        """
208        get plugins local to guiframe and others
209        """
210        plugins = []
211        #import guiframe local plugins
212        #check if the style contain guiframe.dataloader
213        style1 = self.__gui_style & GUIFRAME.DATALOADER_ON
214        style2 = self.__gui_style & GUIFRAME.PLOTTING_ON
215        if style1 == GUIFRAME.DATALOADER_ON:
216            try:
217                from sans.guiframe.local_perspectives.data_loader import data_loader
218                self._data_plugin = data_loader.Plugin()
219                plugins.append(self._data_plugin)
220            except:
221                msg = "ViewerFrame._get_local_plugins:"
222                msg += "cannot import dataloader plugin.\n %s" % sys.exc_value
223                logging.error(msg)
224        if style2 == GUIFRAME.PLOTTING_ON:
225            try:
226                from sans.guiframe.local_perspectives.plotting import plotting
227                self._plotting_plugin = plotting.Plugin()
228                plugins.append(self._plotting_plugin)
229            except:
230                msg = "ViewerFrame._get_local_plugins:"
231                msg += "cannot import plotting plugin.\n %s" % sys.exc_value
232                logging.error(msg)
233     
234        return plugins
235   
236    def _find_plugins(self, dir="perspectives"):
237        """
238        Find available perspective plug-ins
239       
240        :param dir: directory in which to look for plug-ins
241       
242        :return: list of plug-ins
243       
244        """
245        import imp
246        plugins = []
247        # Go through files in panels directory
248        try:
249            list = os.listdir(dir)
250            ## the default panel is the panel is the last plugin added
251            for item in list:
252                toks = os.path.splitext(os.path.basename(item))
253                name = None
254                if not toks[0] == '__init__':
255                   
256                    if toks[1] == '.py' or toks[1] == '':
257                        name = toks[0]
258               
259                    path = [os.path.abspath(dir)]
260                    file = None
261                    try:
262                        if toks[1] == '':
263                            mod_path = '.'.join([dir, name])
264                            module = __import__(mod_path, globals(),
265                                                locals(), [name])
266                        else:
267                            (file, path, info) = imp.find_module(name, path)
268                            module = imp.load_module( name, file, item, info)
269                        if hasattr(module, "PLUGIN_ID"):
270                            try: 
271                                plug = module.Plugin()
272                                if plug.set_default_perspective():
273                                    self._current_perspective = plug
274                                plugins.append(plug)
275                                msg = "Found plug-in: %s" % module.PLUGIN_ID
276                                logging.info(msg)
277                            except:
278                                msg = "Error accessing PluginPanel"
279                                msg += " in %s\n  %s" % (name, sys.exc_value)
280                                config.printEVT(msg)
281                    except:
282                        print sys.exc_value
283                        msg = "ViewerFrame._find_plugins: %s" % sys.exc_value
284                        logging.error(msg)
285                    finally:
286                        if not file == None:
287                            file.close()
288        except:
289            # Should raise and catch at a higher level and
290            # display error on status bar
291            pass   
292        return plugins
293   
294    def set_welcome_panel(self, panel_class):
295        """
296        Sets the default panel as the given welcome panel
297       
298        :param panel_class: class of the welcome panel to be instantiated
299       
300        """
301        self.defaultPanel = panel_class(self, -1, style=wx.RAISED_BORDER)
302       
303    def _get_panels_size(self, p):
304        """
305        find the proper size of the current panel
306        get the proper panel width and height
307        """
308        panel_height_min = self._window_height
309        panel_width_min = self._window_width
310        style = self.__gui_style & (GUIFRAME.MANAGER_ON)
311        if self._data_panel is not None  and (p == self._data_panel):
312            panel_width_min = self._window_width * 2/25 
313            return panel_width_min, panel_height_min
314        if hasattr(p, "CENTER_PANE") and p.CENTER_PANE:
315            style = self.__gui_style & (GUIFRAME.PLOTTING_ON|GUIFRAME.MANAGER_ON)
316            if style == (GUIFRAME.PLOTTING_ON|GUIFRAME.MANAGER_ON):
317                panel_width_min = self._window_width * 17/25 
318            return panel_width_min, panel_height_min
319        return panel_width_min, panel_height_min
320   
321    def _load_panels(self):
322        """
323        Load all panels in the panels directory
324        """
325       
326        # Look for plug-in panels
327        panels = []   
328        for item in self.plugins:
329            if hasattr(item, "get_panels"):
330                ps = item.get_panels(self)
331                panels.extend(ps)
332       
333        # Show a default panel with some help information
334        # It also sets the size of the application windows
335        #TODO: Use this for slpash screen
336        if self.defaultPanel is None:
337            self.defaultPanel = DefaultPanel(self, -1, style=wx.RAISED_BORDER)
338        # add a blank default panel always present
339        self.panels["default"] = self.defaultPanel
340        self._mgr.AddPane(self.defaultPanel, wx.aui.AuiPaneInfo().
341                              Name("default").
342                              Center().
343                              CloseButton(True).
344                              # This is where we set the size of
345                              # the application window
346                              BestSize(wx.Size(self._window_width, 
347                                               self._window_height)).
348                              Show())
349        #add data panel
350        self.panels["data_panel"] = self._data_panel
351        w, h = self._get_panels_size(self._data_panel)
352        self._mgr.AddPane(self._data_panel, wx.aui.AuiPaneInfo().
353                              Name(self._data_panel.window_name).
354                              Left().
355                              MinimizeButton().
356                              MinSize(wx.Size(w, h)).
357                              Show())
358        style = self.__gui_style & GUIFRAME.MANAGER_ON
359        if style != GUIFRAME.MANAGER_ON:
360            self._mgr.GetPane(self.panels["data_panel"].window_name).Hide()
361           
362        # Add the panels to the AUI manager
363        for panel_class in panels:
364            p = panel_class
365            id = wx.NewId()
366            w, h = self._get_panels_size(p)
367            # Check whether we need to put this panel
368            # in the center pane
369            if hasattr(p, "CENTER_PANE") and p.CENTER_PANE:
370                if p.CENTER_PANE:
371                    self.panels[str(id)] = p
372                    self._mgr.AddPane(p, wx.aui.AuiPaneInfo().
373                                          Name(p.window_name).Caption(p.window_caption).
374                                           CenterPane().
375                                           MinSize(wx.Size(w, h)).
376                                           Hide())
377            else:
378                self.panels[str(id)] = p
379                self._mgr.AddPane(p, wx.aui.AuiPaneInfo().
380                                  Name(p.window_name).Caption(p.window_caption).
381                                  Right().
382                                  Dock().
383                                  TopDockable().
384                                  BottomDockable().
385                                  LeftDockable().
386                                  RightDockable().
387                                  MinimizeButton().
388                                  Hide())       
389     
390    def get_context_menu(self, graph=None):
391        """
392        Get the context menu items made available
393        by the different plug-ins.
394        This function is used by the plotting module
395        """
396        menu_list = []
397        for item in self.plugins:
398            if hasattr(item, "get_context_menu"):
399                menu_list.extend(item.get_context_menu(graph))
400        return menu_list
401       
402    def popup_panel(self, p):
403        """
404        Add a panel object to the AUI manager
405       
406        :param p: panel object to add to the AUI manager
407       
408        :return: ID of the event associated with the new panel [int]
409       
410        """
411        ID = wx.NewId()
412        self.panels[str(ID)] = p
413        count = 0
414        for item in self.panels:
415            if self.panels[item].window_name.startswith(p.window_name): 
416                count += 1
417        windowname = p.window_name
418        caption = p.window_caption
419        if count > 0:
420            windowname += str(count+1)
421            caption += (' '+str(count))
422        p.window_name = windowname
423        p.window_caption = caption
424           
425        style1 = self.__gui_style & GUIFRAME.FIXED_PANEL
426        style2 = self.__gui_style & GUIFRAME.FLOATING_PANEL
427        if style1 == GUIFRAME.FIXED_PANEL:
428            self._mgr.AddPane(p, wx.aui.AuiPaneInfo().
429                              Name(windowname).Caption(caption).
430                              MinimizeButton().
431                              Resizable(True).
432                              # Use a large best size to make sure the AUI
433                              # manager takes all the available space
434                              BestSize(wx.Size(PLOPANEL_WIDTH, PLOPANEL_HEIGTH)))
435            self._popup_fixed_panel(p)
436   
437        elif style2 == GUIFRAME.FLOATING_PANEL:
438            self._mgr.AddPane(p, wx.aui.AuiPaneInfo().
439                              Name(windowname).Caption(caption).
440                              MinimizeButton().
441                              Resizable(True).
442                              # Use a large best size to make sure the AUI
443                              #  manager takes all the available space
444                              BestSize(wx.Size(PLOPANEL_WIDTH, PLOPANEL_HEIGTH)))
445            self._popup_floating_panel(p)
446           
447        pane = self._mgr.GetPane(windowname)
448        self._mgr.MaximizePane(pane)
449        self._mgr.RestoreMaximizedPane()
450        # Register for showing/hiding the panel
451        wx.EVT_MENU(self, ID, self._on_view)
452       
453        self._mgr.Update()
454        return ID
455       
456    def _populate_file_menu(self):
457        """
458        Insert menu item under file menu
459        """
460        for plugin in self.plugins:
461            if len(plugin.populate_file_menu()) > 0:
462                for item in plugin.populate_file_menu():
463                    id = wx.NewId()
464                    m_name, m_hint, m_handler = item
465                    self._file_menu.Append(id, m_name, m_hint)
466                    wx.EVT_MENU(self, id, m_handler)
467                self._file_menu.AppendSeparator()
468               
469    def _setup_menus(self):
470        """
471        Set up the application menus
472        """
473        # Menu
474        self._menubar = wx.MenuBar()
475        self._add_menu_file()
476        self._add_menu_data()
477        self._add_menu_application()
478        self._add_menu_tool()
479        self._add_current_plugin_menu()
480        self._add_menu_window()
481        self._add_help_menu()
482        self.SetMenuBar(self._menubar)
483       
484    def _add_menu_tool(self):
485        """
486        Tools menu
487        Go through plug-ins and find tools to populate the tools menu
488        """
489        style = self.__gui_style & GUIFRAME.TOOL_ON
490        if style == GUIFRAME.TOOL_ON:
491            self._tool_menu = None
492            for item in self.plugins:
493                if hasattr(item, "get_tools"):
494                    for tool in item.get_tools():
495                        # Only create a menu if we have at least one tool
496                        if self._tool_menu is None:
497                            self._tool_menu = wx.Menu()
498                        id = wx.NewId()
499                        self._tool_menu.Append(id, tool[0], tool[1])
500                        wx.EVT_MENU(self, id, tool[2])
501            if self._tool_menu is not None:
502                self._menubar.Append(self._tool_menu, '&Tools')
503               
504    def _add_current_plugin_menu(self):
505        """
506        add current plugin menu
507        Look for plug-in menus
508        Add available plug-in sub-menus.
509        """
510        if (self._menubar is None) or (self._current_perspective is None):
511            return
512        #replace or add a new menu for the current plugin
513        name = 'Others'
514        pos = self._menubar.FindMenu(name)
515        if pos != -1:
516            menu_list = self._current_perspective.populate_menu(self)
517            if menu_list:
518                for (menu, _) in menu_list:
519                    hidden_menu = self._menubar.Replace(pos, menu, name) 
520            else:
521                hidden_menu = self._menubar.Remove(pos)
522            #get the position of the menu when it first added
523            self._plugin_menu_pos = pos
524        else:
525            menu_list = self._current_perspective.populate_menu(self)
526            if menu_list:
527                for (menu, _) in menu_list:
528                    if self._plugin_menu_pos == -1:
529                        self._menubar.Append(menu, name)
530                    else:
531                        self._menubar.Insert(self._plugin_menu_pos, menu, name)
532                 
533    def _add_help_menu(self):
534        """
535        add help menu
536        """
537        # Help menu
538        self._help_menu = wx.Menu()
539        # add the welcome panel menu item
540        if self.defaultPanel is not None:
541            id = wx.NewId()
542            self._help_menu.Append(id, '&Welcome', '')
543            self._help_menu.AppendSeparator()
544            wx.EVT_MENU(self, id, self.show_welcome_panel)
545        # Look for help item in plug-ins
546        for item in self.plugins:
547            if hasattr(item, "help"):
548                id = wx.NewId()
549                self._help_menu.Append(id,'&%s help' % item.sub_menu, '')
550                wx.EVT_MENU(self, id, item.help)
551        if config._do_aboutbox:
552            id = wx.NewId()
553            self._help_menu.Append(id,'&About', 'Software information')
554            wx.EVT_MENU(self, id, self._onAbout)
555       
556        # Checking for updates needs major refactoring to work with py2exe
557        # We need to make sure it doesn't hang the application if the server
558        # is not up. We also need to make sure there's a proper executable to
559        # run if we spawn a new background process.
560        #id = wx.NewId()
561        #self._help_menu.Append(id,'&Check for update',
562        #'Check for the latest version of %s' % config.__appname__)
563        #wx.EVT_MENU(self, id, self._check_update)
564        self._menubar.Append(self._help_menu, '&Help')
565           
566    def _add_menu_window(self):
567        """
568        add a menu window to the menu bar
569        Window menu
570        Attach a menu item for each panel in our
571        panel list that also appears in a plug-in.
572       
573        Only add the panel menu if there is only one perspective and
574        it has more than two panels.
575        Note: the first plug-in is always the plotting plug-in.
576        The first application
577        #plug-in is always the second one in the list.
578        """
579        self._window_menu = wx.Menu()
580        if self._plotting_plugin is not None:
581            for (menu, name) in self._plotting_plugin.populate_menu(self):
582                self._window_menu.AppendSubMenu(menu, name)
583        self._menubar.Append(self._window_menu, '&Window')
584     
585        style = self.__gui_style & GUIFRAME.MANAGER_ON
586        if style == GUIFRAME.MANAGER_ON:
587            id = wx.NewId()
588            self._window_menu.Append(id,'&Data Manager', '')
589            wx.EVT_MENU(self, id, self.show_data_panel)
590           
591        style = self.__gui_style & GUIFRAME.PLOTTING_ON
592        if style == GUIFRAME.PLOTTING_ON:
593            self._window_menu.AppendSeparator()
594            id = wx.NewId()
595            preferences_menu = wx.Menu()
596            hint = "Plot panels will floating"
597            preferences_menu.Append(id, '&Floating Plot Panel', hint)
598            wx.EVT_MENU(self, id, self.set_plotpanel_floating)
599            id = wx.NewId()
600            hint = "Plot panels will displayed within the frame"
601            preferences_menu.Append(id, '&Fixed Plot Panel', hint)
602            wx.EVT_MENU(self, id, self.set_plotpanel_fixed)
603            id = wx.NewId()
604            self._window_menu.AppendSubMenu(preferences_menu,'&Preferences')
605        #wx.EVT_MENU(self, id, self.show_preferences_panel)   
606        """
607        if len(self.plugins) == 2:
608            plug = self.plugins[1]
609            pers = plug.get_perspective()
610       
611            if len(pers) > 1:
612                self._window_menu = wx.Menu()
613                for item in self.panels:
614                    if item == 'default':
615                        continue
616                    panel = self.panels[item]
617                    if panel.window_name in pers:
618                        self._window_menu.Append(int(item),
619                                                  panel.window_caption,
620                                        "Show %s window" % panel.window_caption)
621                        wx.EVT_MENU(self, int(item), self._on_view)
622                self._menubar.Append(self._window_menu, '&Window')
623                """
624               
625    def _add_menu_application(self):
626        """
627       
628        # Attach a menu item for each defined perspective or application.
629        # Only add the perspective menu if there are more than one perspectives
630        add menu application
631        """
632        style = self.__gui_style & GUIFRAME.MULTIPLE_APPLICATIONS
633        if style == GUIFRAME.MULTIPLE_APPLICATIONS:
634            p_menu = wx.Menu()
635            for plug in self.plugins:
636                if len(plug.get_perspective()) > 0:
637                    id = wx.NewId()
638                    p_menu.Append(id, plug.sub_menu,
639                                  "Switch to application: %s" % plug.sub_menu)
640                    wx.EVT_MENU(self, id, plug.on_perspective)
641            self._menubar.Append(p_menu, '&Applications')
642           
643    def _add_menu_file(self):
644        """
645        add menu file
646        """
647         # File menu
648        self._file_menu = wx.Menu()
649        # some menu of plugin to be seen under file menu
650        self._populate_file_menu()
651        id = wx.NewId()
652        self._file_menu.Append(id, '&Save Application',
653                             'Save state of the current active application')
654        wx.EVT_MENU(self, id, self._on_save_application)
655        id = wx.NewId()
656        self._file_menu.Append(id, '&Save Project',
657                             'Save the state of the whole application')
658        wx.EVT_MENU(self, id, self._on_save_project)
659        self._file_menu.AppendSeparator()
660       
661        id = wx.NewId()
662        self._file_menu.Append(id, '&Quit', 'Exit') 
663        wx.EVT_MENU(self, id, self.Close)
664        # Add sub menus
665        self._menubar.Append(self._file_menu, '&File')
666       
667    def _add_menu_data(self):
668        """
669        Add menu item item data to menu bar
670        """
671        # Add menu data
672        self._data_menu = wx.Menu()
673        #menu for data files
674        data_file_id = wx.NewId()
675        data_file_hint = "load one or more data in the application"
676        self._data_menu.Append(data_file_id, 
677                         '&Load Data File(s)', data_file_hint)
678        wx.EVT_MENU(self, data_file_id, self._load_data)
679        style = self.__gui_style & GUIFRAME.MULTIPLE_APPLICATIONS
680        style1 = self.__gui_style & GUIFRAME.DATALOADER_ON
681        if style == GUIFRAME.MULTIPLE_APPLICATIONS:
682            #menu for data from folder
683            data_folder_id = wx.NewId()
684            data_folder_hint = "load multiple data in the application"
685            self._data_menu.Append(data_folder_id, 
686                             '&Load Data Folder', data_folder_hint)
687            wx.EVT_MENU(self, data_folder_id, self._load_folder)
688            self._menubar.Append(self._data_menu, '&Data')
689        elif style1 == GUIFRAME.DATALOADER_ON:
690            self._menubar.Append(self._data_menu, '&Data')
691       
692    def _load_data(self, event):
693        """
694        connect menu item load data with the first plugin that can load data
695        """
696        for plug in self.plugins:
697            if plug.can_load_data():
698                plug.load_data(event)
699        style = self.__gui_style & GUIFRAME.MANAGER_ON
700        if style == GUIFRAME.MANAGER_ON:
701            self.show_data_panel(event=None)
702       
703    def _load_folder(self, event):
704        """
705        connect menu item load data with the first plugin that can load data and
706        folder
707        """
708        for plug in self.plugins:
709            if plug.can_load_data():
710                plug.load_folder(event)
711        style = self.__gui_style & GUIFRAME.MANAGER_ON
712        if style == GUIFRAME.MANAGER_ON:
713            self.show_data_panel(event=None)
714               
715    def _on_status_event(self, evt):
716        """
717        Display status message
718        """
719        self.sb.set_status(event=evt)
720       
721    def _on_view(self, evt):
722        """
723        A panel was selected to be shown. If it's not already
724        shown, display it.
725       
726        :param evt: menu event
727       
728        """
729        self.show_panel(evt.GetId())
730       
731    def on_close_welcome_panel(self):
732        """
733        Close the welcome panel
734        """
735        if self.defaultPanel is None:
736            return 
737        self._mgr.GetPane(self.panels["default"].window_name).Hide()
738        self._mgr.Update()
739        # set a default perspective
740        self.set_default_perspective()
741       
742    def show_welcome_panel(self, event):
743        """   
744        Display the welcome panel
745        """
746        if self.defaultPanel is None:
747            return 
748        for id in self.panels.keys():
749            if id  ==  'default':
750                # Show default panel
751                if not self._mgr.GetPane(self.panels["default"].window_name).IsShown():
752                    self._mgr.GetPane(self.panels["default"].window_name).Show(True)
753            elif id == "data_panel":
754                flag = self._mgr.GetPane(self.panels["data_panel"].window_name).IsShown()
755                self._mgr.GetPane(self.panels["data_panel"].window_name).Show(flag)
756            else:
757                self._mgr.GetPane(self.panels[id].window_name).IsShown()
758                self._mgr.GetPane(self.panels[id].window_name).Hide()
759        self._mgr.Update()
760       
761    def show_panel(self, uid):
762        """
763        Shows the panel with the given id
764       
765        :param uid: unique ID number of the panel to show
766       
767        """
768        ID = str(uid)
769        config.printEVT("show_panel: %s" % ID)
770        if ID in self.panels.keys():
771            if not self._mgr.GetPane(self.panels[ID].window_name).IsShown():
772                self._mgr.GetPane(self.panels[ID].window_name).Show()
773                # Hide default panel
774                self._mgr.GetPane(self.panels["default"].window_name).Hide()
775            self._mgr.Update()
776   
777    def _on_open(self, event):
778        """
779        """
780        path = self.choose_file()
781        if path is None:
782            return
783
784        if path and os.path.isfile(path):
785            basename  = os.path.basename(path)
786            if  basename.endswith('.svs'):
787                #remove panels for new states
788                for item in self.panels:
789                    try:
790                        self.panels[item].clear_panel()
791                    except:
792                        pass
793                #reset states and plot data
794                for item in STATE_FILE_EXT:
795                    exec "plot_data(self, path,'%s')" % str(item)
796            else:
797                plot_data(self, path)
798        if self.defaultPanel is not None and \
799            self._mgr.GetPane(self.panels["default"].window_name).IsShown():
800            self.on_close_welcome_panel()
801           
802    def _on_save_application(self, event):
803        """
804        save the state of the current active application
805        """
806        ## Default file location for save
807        self._default_save_location = os.getcwd()
808        if self._current_perspective is  None:
809            return
810        reader, ext = self._current_perspective.get_extensions()
811        path = None
812        dlg = wx.FileDialog(self, "Choose a file",
813                            self._default_save_location, "", ext, wx.SAVE)
814        if dlg.ShowModal() == wx.ID_OK:
815            path = dlg.GetPath()
816            self._default_save_location = os.path.dirname(path)
817        else:
818            return None
819        dlg.Destroy()
820        if path is None:
821            return
822        # default cansas xml doc
823        doc = None
824        for panel in self._current_perspective.get_perspective():
825            doc = on_save_helper(doc, reader, panel, path)
826           
827    def _on_save_project(self, event):
828        """
829        save the state of the current active application
830        """
831        ## Default file location for save
832        self._default_save_location = os.getcwd()
833        if self._current_perspective is  None:
834            return
835        reader, ext = self._current_perspective.get_extensions()
836        path = None
837        dlg = wx.FileDialog(self, "Choose a file",
838                            self._default_save_location, "", '.svs', wx.SAVE)
839        if dlg.ShowModal() == wx.ID_OK:
840            path = dlg.GetPath()
841            self._default_save_location = os.path.dirname(path)
842        else:
843            return None
844        dlg.Destroy()
845        if path is None:
846            return
847        # default cansas xml doc
848        doc = None
849        for panel in self.panels.values():
850            doc = self.on_save_helper(doc, reader, panel, path)
851       
852           
853    def on_save_helper(self, doc, reader, panel, path):
854        """
855        Save state into a file
856        """
857        try:
858            data = panel.get_data()
859            state = panel.get_state()
860            if reader is not None:
861                if data is not None:
862                    new_doc = reader.write_toXML(data, state)
863                    if hasattr(doc, "firstChild"):
864                        child = new_doc.firstChild.firstChild
865                        doc.firstChild.appendChild(child) 
866                    else:
867                        doc = new_doc
868        except: 
869            raise
870            #pass
871        # Write the XML document
872        if doc != None:
873            fd = open(path, 'w')
874            fd.write(doc.toprettyxml())
875            fd.close()
876        else:
877            raise
878            #print "Nothing to save..."
879            #raise RuntimeError, "%s is not a SansView (.svs) file..." % path
880        return doc
881
882    def quit_guiframe(self):
883        """
884        Pop up message to make sure the user wants to quit the application
885        """
886        message = "Do you really want to quit \n"
887        message += "this application?"
888        dial = wx.MessageDialog(self, message, 'Question',
889                           wx.YES_NO|wx.YES_DEFAULT|wx.ICON_QUESTION)
890        if dial.ShowModal() == wx.ID_YES:
891            return True
892        else:
893            return False   
894       
895    def Close(self, event=None):
896        """
897        Quit the application
898        """
899        #flag = self.quit_guiframe()
900        if True:
901            wx.Exit()
902            sys.exit()
903
904    def _check_update(self, event=None): 
905        """
906        Check with the deployment server whether a new version
907        of the application is available.
908        A thread is started for the connecting with the server. The thread calls
909        a call-back method when the current version number has been obtained.
910        """
911        if hasattr(config, "__update_URL__"):
912            import version
913            checker = version.VersionThread(config.__update_URL__,
914                                            self._process_version,
915                                            baggage=event==None)
916            checker.start() 
917   
918    def _process_version(self, version, standalone=True):
919        """
920        Call-back method for the process of checking for updates.
921        This methods is called by a VersionThread object once the current
922        version number has been obtained. If the check is being done in the
923        background, the user will not be notified unless there's an update.
924       
925        :param version: version string
926        :param standalone: True of the update is being checked in
927           the background, False otherwise.
928           
929        """
930        try:
931            if cmp(version, config.__version__) > 0:
932                msg = "Version %s is available! See the Help "
933                msg += "menu to download it." % version
934                self.SetStatusText(msg)
935                if not standalone:
936                    import webbrowser
937                    webbrowser.open(config.__download_page__)
938            else:
939                if not standalone:
940                    msg = "You have the latest version"
941                    msg += " of %s" % config.__appname__
942                    self.SetStatusText(msg)
943        except:
944            msg = "guiframe: could not get latest application"
945            msg += " version number\n  %s" % sys.exc_value
946            logging.error(msg)
947            if not standalone:
948                msg = "Could not connect to the application server."
949                msg += " Please try again later."
950                self.SetStatusText(msg)
951                   
952    def _onAbout(self, evt):
953        """
954        Pop up the about dialog
955       
956        :param evt: menu event
957       
958        """
959        if config._do_aboutbox:
960            import aboutbox 
961            dialog = aboutbox.DialogAbout(None, -1, "")
962            dialog.ShowModal()           
963           
964    def set_manager(self, manager):
965        """
966        Sets the application manager for this frame
967       
968        :param manager: frame manager
969        """
970        self.app_manager = manager
971       
972    def post_init(self):
973        """
974        This initialization method is called after the GUI
975        has been created and all plug-ins loaded. It calls
976        the post_init() method of each plug-in (if it exists)
977        so that final initialization can be done.
978        """
979        for item in self.plugins:
980            if hasattr(item, "post_init"):
981                item.post_init()
982       
983    def set_default_perspective(self):
984        """
985        Choose among the plugin the first plug-in that has
986        "set_default_perspective" method and its return value is True will be
987        as a default perspective when the welcome page is closed
988        """
989        for item in self.plugins:
990            if hasattr(item, "set_default_perspective"):
991                if item.set_default_perspective():
992                    item.on_perspective(event=None)
993                    return 
994       
995    def set_perspective(self, panels):
996        """
997        Sets the perspective of the GUI.
998        Opens all the panels in the list, and closes
999        all the others.
1000       
1001        :param panels: list of panels
1002        """
1003        for item in self.panels:
1004            # Check whether this is a sticky panel
1005            if hasattr(self.panels[item], "ALWAYS_ON"):
1006                if self.panels[item].ALWAYS_ON:
1007                    continue 
1008            if self.panels[item].window_name in panels:
1009                if not self._mgr.GetPane(self.panels[item].window_name).IsShown():
1010                    self._mgr.GetPane(self.panels[item].window_name).Show()
1011            else:
1012                # always show the data panel if enable
1013                style = self.__gui_style & GUIFRAME.MANAGER_ON
1014                if (style == GUIFRAME.MANAGER_ON) and self.panels[item] == self._data_panel:
1015                    if 'data_panel' in self.panels.keys():
1016                        flag = self._mgr.GetPane(self.panels['data_panel'].window_name).IsShown()
1017                        self._mgr.GetPane(self.panels['data_panel'].window_name).Show(flag)
1018                else:
1019                    if self._mgr.GetPane(self.panels[item].window_name).IsShown():
1020                        self._mgr.GetPane(self.panels[item].window_name).Hide()
1021        self._mgr.Update()
1022       
1023    def show_data_panel(self, event=None):
1024        """
1025        show the data panel
1026        """
1027        pane = self._mgr.GetPane(self.panels["data_panel"].window_name)
1028        #if not pane.IsShown():
1029        pane.Show(True)
1030        self._mgr.Update()
1031 
1032    def add_data(self, data_list, flag=False):
1033        """
1034        receive a list of data . store them its data manager if possible
1035        determine if data was be plot of send to data perspectives
1036        """
1037        #send a list of available data to plotting plugin
1038        avalaible_data = []
1039        if self._data_manager is not None:
1040            self._data_manager.add_data(data_list)
1041            avalaible_data = self._data_manager.get_all_data()
1042           
1043        if True:
1044            #reading a state file
1045            for plug in self.plugins:
1046                plug.on_set_state_helper(event=None)
1047        style = self.__gui_style & GUIFRAME.MANAGER_ON
1048        if style == GUIFRAME.MANAGER_ON:
1049            if self._data_panel is not None:
1050                data_state = self._data_manager.get_selected_data()
1051                self._data_panel.load_data_list(data_state)
1052                self._mgr.GetPane(self._data_panel.window_name).Show(True)
1053                #wait for button press from the data panel to send data
1054        else:
1055            #automatically send that to the current perspective
1056            style = self.__gui_style & GUIFRAME.SINGLE_APPLICATION
1057            if style == GUIFRAME.SINGLE_APPLICATION:
1058                self.set_data(data_list)
1059               
1060    def get_data_from_panel(self, data_id, plot=False,append=False):
1061        """
1062        receive a list of data key retreive the data from data manager and set
1063        then to the current perspective
1064        """
1065        data_dict = self._data_manager.get_by_id(data_id)
1066        data_list = []
1067        for data_state in data_dict.values():
1068            data_list.append(data_state.data)
1069        if plot:
1070            self.plot_data(data_list, append=append)
1071        else:
1072            #sent data to active application
1073            self.set_data(data_list=data_list)
1074       
1075       
1076    def set_data(self, data_list):
1077        """
1078        set data to current perspective
1079        """
1080        if self._current_perspective is not None:
1081            try:
1082                self._current_perspective.set_data(data_list)
1083            except:
1084                msg = str(sys.exc_value)
1085                wx.PostEvent(self, StatusEvent(status=msg, info="error"))
1086        else:
1087            msg = "Guiframe does not have a current perspective"
1088            logging.info(msg)
1089           
1090    def plot_data(self, data_list, append=False):
1091        """
1092        send a list of data to plot
1093        """
1094        if not data_list:
1095            message = "Please check data to plot or append"
1096            wx.PostEvent(self, StatusEvent(status=message, info='warning'))
1097            return 
1098        for new_plot in data_list:
1099            if append:
1100                if self.panel_on_focus is None or \
1101                    not self.enable_add_data(new_plot):
1102                    message = "cannot append plot. No plot panel on focus!"
1103                    message += "please click on any available plot to set focus"
1104                    wx.PostEvent(self, StatusEvent(status=message, 
1105                                                   info='warning'))
1106                    return 
1107                else:
1108                    if self.enable_add_data(new_plot):
1109                        new_plot.group_id = self.panel_on_focus.group_id
1110            wx.PostEvent(self, NewPlotEvent(plot=new_plot,
1111                                                  title=str(new_plot.title)))
1112           
1113    def add_theory(self, data_id, theory):
1114        """
1115        """
1116        self._data_manager.append_theory(data_id, theory)
1117        style = self.__gui_style & GUIFRAME.MANAGER_ON
1118        if style == GUIFRAME.MANAGER_ON:
1119            if self._data_panel is not None:
1120                data_state = self._data_manager.get_by_id([data_id])
1121                self._data_panel.load_data_list(data_state)
1122               
1123    def delete_data(self, data_id, theory_id=None, delete_all=True):
1124        """
1125        Delete data state if data_id is provide
1126        delete theory created with data of id data_id if theory_id is provide
1127        if delete all true: delete the all state
1128        else delete theory
1129        """
1130        self._data_manager.delete_data(data_id=data_id, 
1131                                       theory_id=theory_id, 
1132                                       delete_all=delete_all)
1133        for plug in self.plugins:
1134            plug.delete_data(data_id)
1135           
1136       
1137    def set_current_perspective(self, perspective):
1138        """
1139        set the current active perspective
1140        """
1141        self._current_perspective = perspective
1142        name = "No current Application selected"
1143        if self._current_perspective is not None:
1144            self._add_current_plugin_menu()
1145            if self._data_panel is not None:
1146                name = self._current_perspective.sub_menu
1147                self._data_panel.set_active_perspective(name)
1148           
1149    def set_plotpanel_floating(self, event=None):
1150        """
1151        make the plot panel floatable
1152        """
1153        self.__gui_style &= (~GUIFRAME.FIXED_PANEL)
1154        self.__gui_style |= GUIFRAME.FLOATING_PANEL
1155        for p in self.panels.values():
1156            plot_panel = self._plotting_plugin.plot_panels
1157            for p in self.panels.values():
1158                if p in plot_panel:
1159                    self._popup_floating_panel(p)
1160       
1161    def set_plotpanel_fixed(self, event=None):
1162        """
1163        make the plot panel fixed
1164        """
1165        self.__gui_style &= (~GUIFRAME.FLOATING_PANEL)
1166        self.__gui_style |= GUIFRAME.FIXED_PANEL
1167        plot_panel = []
1168        if self._plotting_plugin is not None:
1169            plot_panel = self._plotting_plugin.plot_panels
1170            for p in self.panels.values():
1171                if p in plot_panel:
1172                    self._popup_fixed_panel(p)
1173                   
1174    def _popup_fixed_panel(self, p):
1175        """
1176        """
1177        style = self.__gui_style & GUIFRAME.FIXED_PANEL
1178        if style == GUIFRAME.FIXED_PANEL:
1179            self._mgr.GetPane(p.window_name).Floatable()
1180            self._mgr.GetPane(p.window_name).Right()
1181            self._mgr.GetPane(p.window_name).TopDockable(False)
1182            self._mgr.GetPane(p.window_name).BottomDockable(False)
1183            self._mgr.GetPane(p.window_name).LeftDockable(False)
1184            self._mgr.GetPane(p.window_name).RightDockable(True)
1185            flag = self._mgr.GetPane(p.window_name).IsShown()
1186            self._mgr.GetPane(p.window_name).Show(flag)
1187            self._mgr.Update()
1188           
1189    def _popup_floating_panel(self, p):
1190        """
1191        """
1192        style = self.__gui_style &  GUIFRAME.FLOATING_PANEL
1193        if style == GUIFRAME.FLOATING_PANEL: 
1194            self._mgr.GetPane(p.window_name).Floatable(True)
1195            self._mgr.GetPane(p.window_name).Float()
1196            self._mgr.GetPane(p.window_name).Dockable(False)
1197            flag = self._mgr.GetPane(p.window_name).IsShown()
1198            self._mgr.GetPane(p.window_name).Show(flag)
1199            self._mgr.Update()
1200           
1201    def enable_add_data(self, new_plot):
1202        """
1203        Enable append data on a plot panel
1204        """
1205        is_theory = len(self.panel_on_focus.plots) <= 1 and \
1206            self.panel_on_focus.plots.values()[0].__class__.__name__ == "Theory1D"
1207           
1208        is_data2d = hasattr(new_plot, 'data')
1209        is_data1d = self.panel_on_focus.__class__.__name__ == "ModelPanel1D"\
1210            and self.panel_on_focus.group_id is not None
1211        has_meta_data = hasattr(new_plot, 'meta_data')
1212       
1213        #disable_add_data if the data is being recovered from  a saved state file.
1214        is_state_data = False
1215        if has_meta_data:
1216            if 'invstate' in new_plot.meta_data: is_state_data = True
1217            if  'prstate' in new_plot.meta_data: is_state_data = True
1218            if  'fitstate' in new_plot.meta_data: is_state_data = True
1219   
1220        return is_data1d and not is_data2d and not is_theory and not is_state_data
1221       
1222class DefaultPanel(wx.Panel):
1223    """
1224    Defines the API for a panels to work with
1225    the GUI manager
1226    """
1227    ## Internal nickname for the window, used by the AUI manager
1228    window_name = "default"
1229    ## Name to appear on the window title bar
1230    window_caption = "Welcome panel"
1231    ## Flag to tell the AUI manager to put this panel in the center pane
1232    CENTER_PANE = True
1233
1234
1235# Toy application to test this Frame
1236class ViewApp(wx.App):
1237    """
1238    """
1239    SIZE = (GUIFRAME_WIDTH,GUIFRAME_HEIGHT)
1240    TITLE = config.__appname__
1241    PROG_SPLASH_PATH = PROG_SPLASH_SCREEN
1242    STYLE = GUIFRAME.DEFAULT_STYLE
1243    def OnInit(self):
1244        """
1245        """
1246        pos, size = self.window_placement(self.SIZE)
1247        self.frame = ViewerFrame(parent=None, 
1248                                 title=self.TITLE, 
1249                                 pos=pos, 
1250                                 gui_style = self.STYLE,
1251                                 size=size) 
1252         # Display a splash screen on top of the frame.
1253        if len(sys.argv) > 1 and '--time' in sys.argv[1:]:
1254            log_time("Starting to display the splash screen")
1255        if self.PROG_SPLASH_PATH is not None and \
1256            os.path.isfile(self.PROG_SPLASH_PATH):
1257            try:
1258                self.display_splash_screen(parent=self.frame, path=self.PROG_SPLASH_PATH)   
1259            except:
1260                msg = "Cannot display splash screen\n"
1261                msg += str (sys.exc_value)
1262                logging.error(msg)
1263        self.frame.Show(True)
1264
1265        if hasattr(self.frame, 'special'):
1266            self.frame.special.SetCurrent()
1267        self.SetTopWindow(self.frame)
1268        return True
1269   
1270    def set_manager(self, manager):
1271        """
1272        Sets a reference to the application manager
1273        of the GUI manager (Frame)
1274        """
1275        self.frame.set_manager(manager)
1276       
1277    def build_gui(self):
1278        """
1279        Build the GUI
1280        """
1281        self.frame.build_gui()
1282        self.frame.post_init()
1283       
1284    def set_welcome_panel(self, panel_class):
1285        """
1286        Set the welcome panel
1287       
1288        :param panel_class: class of the welcome panel to be instantiated
1289       
1290        """
1291        self.frame.set_welcome_panel(panel_class)
1292       
1293    def add_perspective(self, perspective):
1294        """
1295        Manually add a perspective to the application GUI
1296        """
1297        self.frame.add_perspective(perspective)
1298   
1299    def window_placement(self, size):
1300        """
1301        Determines the position and size of the application frame such that it
1302        fits on the user's screen without obstructing (or being obstructed by)
1303        the Windows task bar.  The maximum initial size in pixels is bounded by
1304        WIDTH x HEIGHT.  For most monitors, the application
1305        will be centered on the screen; for very large monitors it will be
1306        placed on the left side of the screen.
1307        """
1308        window_width, window_height = size
1309        screen_size = wx.GetDisplaySize()
1310        window_height = window_height if screen_size[1]>window_height else screen_size[1]-50
1311        window_width  = window_width if screen_size[0]> window_width else screen_size[0]-50
1312        xpos = ypos = 0
1313
1314        # Note that when running Linux and using an Xming (X11) server on a PC
1315        # with a dual  monitor configuration, the reported display size may be
1316        # that of both monitors combined with an incorrect display count of 1.
1317        # To avoid displaying this app across both monitors, we check for
1318        # screen 'too big'.  If so, we assume a smaller width which means the
1319        # application will be placed towards the left hand side of the screen.
1320
1321        _, _, x, y = wx.Display().GetClientArea() # size excludes task bar
1322        if len(sys.argv) > 1 and '--platform' in sys.argv[1:]:
1323            w, h = wx.DisplaySize()  # size includes task bar area
1324            print "*** Reported screen size including taskbar is %d x %d"%(w, h)
1325            print "*** Reported screen size excluding taskbar is %d x %d"%(x, y)
1326
1327        if x > 1920: x = 1280  # display on left side, not centered on screen
1328        if x > window_width:  xpos = (x - window_width)/2
1329        if y > window_height: ypos = (y - window_height)/2
1330
1331        # Return the suggested position and size for the application frame.
1332        return (xpos, ypos), (min(x, window_width), min(y, window_height))
1333   
1334    def display_splash_screen(self, parent, path=PROG_SPLASH_SCREEN):
1335        """Displays the splash screen.  It will exactly cover the main frame."""
1336
1337        # Prepare the picture.  On a 2GHz intel cpu, this takes about a second.
1338        x, y = parent.GetSizeTuple()
1339        image = wx.Image(path, wx.BITMAP_TYPE_PNG)
1340        image.Rescale(x, y, wx.IMAGE_QUALITY_HIGH)
1341        bm = image.ConvertToBitmap()
1342
1343        # Create and show the splash screen.  It will disappear only when the
1344        # program has entered the event loop AND either the timeout has expired
1345        # or the user has left clicked on the screen.  Thus any processing
1346        # performed in this routine (including sleeping) or processing in the
1347        # calling routine (including doing imports) will prevent the splash
1348        # screen from disappearing.
1349        #
1350        # Note that on Linux, the timeout appears to occur immediately in which
1351        # case the splash screen disappears upon entering the event loop.
1352        wx.SplashScreen(bitmap=bm,
1353                        splashStyle=(wx.SPLASH_CENTRE_ON_PARENT|
1354                                     wx.SPLASH_TIMEOUT|
1355                                     wx.STAY_ON_TOP),
1356                        milliseconds=4000,
1357                        parent=parent,
1358                        id=wx.ID_ANY)
1359
1360        # Keep the splash screen up a minimum amount of time for non-Windows
1361        # systems.  This is a workaround for Linux and possibly MacOS that
1362        # appear to ignore the splash screen timeout option.
1363        if '__WXMSW__' not in wx.PlatformInfo:
1364            if len(sys.argv) > 1 and '--time' in sys.argv[1:]:
1365                log_time("Starting sleep of 2 secs")
1366            time.sleep(2)
1367
1368        # A call to wx.Yield does not appear to be required.  If used on
1369        # Windows, the cursor changes from 'busy' to 'ready' before the event
1370        # loop is reached which is not desirable.  On Linux it seems to have
1371        # no effect.
1372        #wx.Yield()
1373
1374       
1375
1376if __name__ == "__main__": 
1377    app = ViewApp(0)
1378    app.MainLoop()
1379
1380             
Note: See TracBrowser for help on using the repository browser.