source: sasview/guiframe/gui_manager.py @ e030625

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

make all derivative of guiframe being able to load from command line

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