source: sasview/guiframe/gui_manager.py @ 20b482f

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

working on delete file

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