source: sasview/guiframe/gui_manager.py @ 56fb77f

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

fixing plot panel and control panels focusing problems

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