source: sasview/guiframe/gui_manager.py @ 7194f7b

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 7194f7b was 7ad8faa, checked in by Gervaise Alina <gervyh@…>, 13 years ago

fix loading issues with same id

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