source: sasview/guiframe/gui_manager.py @ cc835cd8

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

working on the splash page

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