source: sasview/guiframe/gui_manager.py @ c70eb7c

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

working data_panel

  • Property mode set to 100644
File size: 71.1 KB
Line 
1
2################################################################################
3#This software was developed by the University of Tennessee as part of the
4#Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
5#project funded by the US National Science Foundation.
6#
7#See the license text in license.txt
8#
9#copyright 2008, University of Tennessee
10################################################################################
11
12
13import wx
14import wx.aui
15import os
16import sys
17import xml
18
19try:
20    # Try to find a local config
21    import imp
22    path = os.getcwd()
23    if(os.path.isfile("%s/%s.py" % (path, 'local_config'))) or \
24        (os.path.isfile("%s/%s.pyc" % (path, 'local_config'))):
25        fObj, path, descr = imp.find_module('local_config', [path])
26        config = imp.load_module('local_config', fObj, path, descr) 
27    else:
28        # Try simply importing local_config
29        import local_config as config
30except:
31    # Didn't find local config, load the default
32    import config
33   
34import warnings
35warnings.simplefilter("ignore")
36
37import logging
38
39from sans.guiframe.events import EVT_STATUS
40from sans.guiframe.events import EVT_APPEND_BOOKMARK
41from sans.guiframe.events import EVT_PANEL_ON_FOCUS
42from sans.guiframe.events import StatusEvent
43from sans.guiframe.events import NewPlotEvent
44from sans.guiframe.gui_style import GUIFRAME
45from sans.guiframe.gui_style import GUIFRAME_ID
46from sans.guiframe.events import NewLoadedDataEvent
47from sans.guiframe.data_panel import DataPanel
48from sans.guiframe.panel_base import PanelBase
49from sans.guiframe.gui_toolbar import GUIToolBar
50from DataLoader.loader import Loader
51
52
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 append_theory(self, data_id, theory, state=None):
434        """
435        """
436        data_state = self._data_manager.append_theory(data_id=data_id, 
437                                                      theory=theory,
438                                                      state=state)
439        self._data_panel.load_data_list(data_state)
440       
441    def update_data(self, prev_data, new_data):
442        """
443        """
444        prev_id, data_state = self._data_manager.update_data(prev_data=prev_data, 
445                                       new_data=new_data)
446        self._data_panel.remove_by_id(prev_id)
447        self._data_panel.load_data_list(data_state)
448       
449       
450    def freeze(self, data_id, theory_id):
451        """
452        """
453        data_state_list = self._data_manager.freeze_theory(data_id=data_id, 
454                                                theory_id=theory_id)
455       
456        self._data_panel.load_data_list(list=data_state_list)
457        for data_state in data_state_list:
458            theory_list = data_state.get_theory()
459            for new_plot in theory_list:
460                wx.PostEvent(self, NewplotEvent(plot=new_plot,
461                                             title=new_plot.title))
462       
463    def delete_data(self, data):
464        """
465        """
466        self._current_perspective.delete_data(data)
467       
468   
469    def get_context_menu(self, plotpanel=None):
470        """
471        Get the context menu items made available
472        by the different plug-ins.
473        This function is used by the plotting module
474        """
475        if plotpanel is None:
476            return
477        menu_list = []
478        for item in self.plugins:
479            menu_list.extend(item.get_context_menu(plotpanel=plotpanel))
480        return menu_list
481       
482    def popup_panel(self, p):
483        """
484        Add a panel object to the AUI manager
485       
486        :param p: panel object to add to the AUI manager
487       
488        :return: ID of the event associated with the new panel [int]
489       
490        """
491        ID = wx.NewId()
492        self.panels[str(ID)] = p
493        count = 0
494        for item in self.panels:
495            if self.panels[item].window_name.startswith(p.window_name): 
496                count += 1
497        windowname = p.window_name
498        caption = p.window_caption
499        if count > 0:
500            windowname += str(count+1)
501            caption += (' '+str(count))
502        p.window_name = windowname
503        p.window_caption = caption
504           
505        style1 = self.__gui_style & GUIFRAME.FIXED_PANEL
506        style2 = self.__gui_style & GUIFRAME.FLOATING_PANEL
507        if style1 == GUIFRAME.FIXED_PANEL:
508            self._mgr.AddPane(p, wx.aui.AuiPaneInfo().
509                              Name(windowname).Caption(caption).
510                              MinimizeButton().
511                              Resizable(True).
512                              # Use a large best size to make sure the AUI
513                              # manager takes all the available space
514                              BestSize(wx.Size(PLOPANEL_WIDTH, PLOPANEL_HEIGTH)))
515            self._popup_fixed_panel(p)
516   
517        elif style2 == GUIFRAME.FLOATING_PANEL:
518            self._mgr.AddPane(p, wx.aui.AuiPaneInfo().
519                              Name(windowname).Caption(caption).
520                              MinimizeButton().
521                              Resizable(True).
522                              # Use a large best size to make sure the AUI
523                              #  manager takes all the available space
524                              BestSize(wx.Size(PLOPANEL_WIDTH, PLOPANEL_HEIGTH)))
525            self._popup_floating_panel(p)
526           
527        pane = self._mgr.GetPane(windowname)
528        self._mgr.MaximizePane(pane)
529        self._mgr.RestoreMaximizedPane()
530        # Register for showing/hiding the panel
531        wx.EVT_MENU(self, ID, self._on_view)
532       
533        self._mgr.Update()
534        return ID
535       
536    def _setup_menus(self):
537        """
538        Set up the application menus
539        """
540        # Menu
541        self._menubar = wx.MenuBar()
542        self._add_menu_file()
543        self._add_menu_data()
544        self._add_menu_application()
545        self._add_menu_edit()
546        self._add_menu_tool()
547        self._add_current_plugin_menu()
548        self._add_menu_window()
549        self._add_help_menu()
550        self.SetMenuBar(self._menubar)
551       
552    def _setup_tool_bar(self):
553        """
554        add toolbar to the frame
555        """
556        #set toolbar
557        self._toolbar = GUIToolBar(self, -1)
558        self.SetToolBar(self._toolbar)
559        self._update_toolbar_helper()
560        #self._on_hide_toolbar(event=None)
561   
562    def _update_toolbar_helper(self):
563        """
564        """
565        application_name = 'No Selected Application'
566        panel_name = 'No Panel on Focus'
567        self._toolbar.update_toolbar(self.panel_on_focus)
568        if self._current_perspective is not None:
569            application_name = self._current_perspective.sub_menu
570        if self.panel_on_focus is not None:
571            panel_name = self.panel_on_focus.window_caption
572        self._toolbar.update_button(application_name=application_name, 
573                                        panel_name=panel_name)
574        self._toolbar.Realize()
575       
576    def _add_menu_tool(self):
577        """
578        Tools menu
579        Go through plug-ins and find tools to populate the tools menu
580        """
581        style = self.__gui_style & GUIFRAME.TOOL_ON
582        if style == GUIFRAME.TOOL_ON:
583            self._tool_menu = None
584            for item in self.plugins:
585                if hasattr(item, "get_tools"):
586                    for tool in item.get_tools():
587                        # Only create a menu if we have at least one tool
588                        if self._tool_menu is None:
589                            self._tool_menu = wx.Menu()
590                        id = wx.NewId()
591                        self._tool_menu.Append(id, tool[0], tool[1])
592                        wx.EVT_MENU(self, id, tool[2])
593            if self._tool_menu is not None:
594                self._menubar.Append(self._tool_menu, '&Tools')
595               
596    def _add_current_plugin_menu(self):
597        """
598        add current plugin menu
599        Look for plug-in menus
600        Add available plug-in sub-menus.
601        """
602        if (self._menubar is None) or (self._current_perspective is None):
603            return
604        #replace or add a new menu for the current plugin
605       
606        pos = self._menubar.FindMenu(str(self._applications_menu_name))
607        if pos != -1:
608            menu_list = self._current_perspective.populate_menu(self)
609            if menu_list:
610                for (menu, name) in menu_list:
611                    hidden_menu = self._menubar.Replace(pos, menu, name) 
612                    self._applications_menu_name = name
613                #self._applications_menu_pos = pos
614            else:
615                hidden_menu = self._menubar.Remove(pos)
616                self._applications_menu_name = None
617            #get the position of the menu when it first added
618            self._applications_menu_pos = pos
619           
620        else:
621            menu_list = self._current_perspective.populate_menu(self)
622            if menu_list:
623                for (menu,name) in menu_list:
624                    if self._applications_menu_pos == -1:
625                        self._menubar.Append(menu, name)
626                    else:
627                        self._menubar.Insert(self._applications_menu_pos, menu, name)
628                    self._applications_menu_name = name
629                 
630    def _add_help_menu(self):
631        """
632        add help menu
633        """
634        # Help menu
635        self._help_menu = wx.Menu()
636        style = self.__gui_style & GUIFRAME.WELCOME_PANEL_ON
637        if style == GUIFRAME.WELCOME_PANEL_ON:
638            # add the welcome panel menu item
639            if self.defaultPanel is not None:
640                id = wx.NewId()
641                self._help_menu.Append(id, '&Welcome', '')
642                self._help_menu.AppendSeparator()
643                wx.EVT_MENU(self, id, self.show_welcome_panel)
644        # Look for help item in plug-ins
645        for item in self.plugins:
646            if hasattr(item, "help"):
647                id = wx.NewId()
648                self._help_menu.Append(id,'&%s help' % item.sub_menu, '')
649                wx.EVT_MENU(self, id, item.help)
650        if config._do_aboutbox:
651            id = wx.NewId()
652            self._help_menu.Append(id,'&About', 'Software information')
653            wx.EVT_MENU(self, id, self._onAbout)
654       
655        # Checking for updates needs major refactoring to work with py2exe
656        # We need to make sure it doesn't hang the application if the server
657        # is not up. We also need to make sure there's a proper executable to
658        # run if we spawn a new background process.
659        #id = wx.NewId()
660        #self._help_menu.Append(id,'&Check for update',
661        #'Check for the latest version of %s' % config.__appname__)
662        #wx.EVT_MENU(self, id, self._check_update)
663        self._menubar.Append(self._help_menu, '&Help')
664           
665    def _add_menu_window(self):
666        """
667        add a menu window to the menu bar
668        Window menu
669        Attach a menu item for each panel in our
670        panel list that also appears in a plug-in.
671       
672        Only add the panel menu if there is only one perspective and
673        it has more than two panels.
674        Note: the first plug-in is always the plotting plug-in.
675        The first application
676        #plug-in is always the second one in the list.
677        """
678        self._window_menu = wx.Menu()
679        if self._plotting_plugin is not None:
680            for (menu, name) in self._plotting_plugin.populate_menu(self):
681                self._window_menu.AppendSubMenu(menu, name)
682        self._menubar.Append(self._window_menu, '&Window')
683     
684        style = self.__gui_style & GUIFRAME.MANAGER_ON
685        id = wx.NewId()
686        self._data_panel_menu = self._window_menu.Append(id,
687                                                '&Data Explorer ON', '')
688        wx.EVT_MENU(self, id, self.show_data_panel)
689        if style == GUIFRAME.MANAGER_ON:
690            self._data_panel_menu.SetText('Data Explorer OFF')
691        else:
692            self._data_panel_menu.SetText('Data Explorer ON')
693           
694        style = self.__gui_style & GUIFRAME.PLOTTING_ON
695        if style == GUIFRAME.PLOTTING_ON:
696            self._window_menu.AppendSeparator()
697            id = wx.NewId()
698            preferences_menu = wx.Menu()
699            hint = "Plot panels will floating"
700            preferences_menu.Append(id, '&Floating Plot Panel', hint)
701            wx.EVT_MENU(self, id, self.set_plotpanel_floating)
702            id = wx.NewId()
703            hint = "Plot panels will displayed within the frame"
704            preferences_menu.Append(id, '&Fixed Plot Panel', hint)
705            wx.EVT_MENU(self, id, self.set_plotpanel_fixed)
706            id = wx.NewId()
707            style1 = self.__gui_style & GUIFRAME.MULTIPLE_APPLICATIONS
708            if style1 == GUIFRAME.MULTIPLE_APPLICATIONS:
709                id = wx.NewId()
710                self._toolbar_menu = preferences_menu.Append(id,'&Hide Toolbar', '')
711                wx.EVT_MENU(self, id, self._on_hide_toolbar)
712            self._window_menu.AppendSubMenu(preferences_menu,'&Preferences')
713        if self._window_menu.GetMenuItemCount() == 0:
714            pos = self._menubar.FindMenu('Window')
715            self._menubar.Remove(pos)
716        #wx.EVT_MENU(self, id, self.show_preferences_panel)   
717        """
718        if len(self.plugins) == 2:
719            plug = self.plugins[1]
720            pers = plug.get_perspective()
721       
722            if len(pers) > 1:
723                self._window_menu = wx.Menu()
724                for item in self.panels:
725                    if item == 'default':
726                        continue
727                    panel = self.panels[item]
728                    if panel.window_name in pers:
729                        self._window_menu.Append(int(item),
730                                                  panel.window_caption,
731                                        "Show %s window" % panel.window_caption)
732                        wx.EVT_MENU(self, int(item), self._on_view)
733                self._menubar.Append(self._window_menu, '&Window')
734                """
735               
736    def _add_menu_application(self):
737        """
738       
739        # Attach a menu item for each defined perspective or application.
740        # Only add the perspective menu if there are more than one perspectives
741        add menu application
742        """
743        style = self.__gui_style & GUIFRAME.MULTIPLE_APPLICATIONS
744        if style == GUIFRAME.MULTIPLE_APPLICATIONS:
745            plug_data_count = False
746            plug_no_data_count = False
747            self._applications_menu = wx.Menu()
748            separator = self._applications_menu.AppendSeparator()
749            for plug in self.plugins:
750                if len(plug.get_perspective()) > 0:
751                    id = wx.NewId()
752                    if plug.use_data():
753                        self._applications_menu.InsertCheckItem(0, id, plug.sub_menu,
754                                      "Switch to application: %s" % plug.sub_menu)
755                        plug_data_count = True
756                    else:
757                        plug_no_data_count = True
758                        self._applications_menu.AppendCheckItem(id, plug.sub_menu,
759                                      "Switch to application: %s" % plug.sub_menu)
760                    wx.EVT_MENU(self, id, plug.on_perspective)
761            if not (plug_data_count and  plug_no_data_count):
762                self._applications_menu.RemoveItem(separator)
763            self._menubar.Append(self._applications_menu, '&Applications')
764            self._check_applications_menu()
765           
766    def _add_menu_file(self):
767        """
768        add menu file
769        """
770       
771         # File menu
772        self._file_menu = wx.Menu()
773        style = self.__gui_style & GUIFRAME.DATALOADER_ON
774        if style == GUIFRAME.DATALOADER_ON:
775            # some menu of plugin to be seen under file menu
776            hint_load_file = "Read state's files and load"
777            hint_load_file += " them into the application"
778            id = wx.NewId()
779            self._save_appl_menu = self._file_menu.Append(id, 
780                                    '&Open State from File', hint_load_file)
781            wx.EVT_MENU(self, id, self._on_open_state)
782            id = wx.NewId()
783            self._save_appl_menu = self._file_menu.Append(id, 
784                                                          '&Save Application',
785                                 'Save state of the current active application')
786            wx.EVT_MENU(self, id, self._on_save_application)
787            id = wx.NewId()
788            self._file_menu.Append(id, '&Save Project',
789                                 'Save the state of the whole application')
790            wx.EVT_MENU(self, id, self._on_save_project)
791            self._file_menu.AppendSeparator()
792       
793        id = wx.NewId()
794        self._file_menu.Append(id, '&Quit', 'Exit') 
795        wx.EVT_MENU(self, id, self.Close)
796        # Add sub menus
797        self._menubar.Append(self._file_menu, '&File')
798       
799    def _add_menu_edit(self):
800        """
801        add menu edit
802        """
803        # Edit Menu
804        self._edit_menu = wx.Menu()
805        self._edit_menu.Append(GUIFRAME_ID.UNDO_ID, '&Undo', 
806                               'Undo the previous action')
807        wx.EVT_MENU(self, GUIFRAME_ID.UNDO_ID, self.on_undo_panel)
808        self._edit_menu.Append(GUIFRAME_ID.REDO_ID, '&Redo', 
809                               'Redo the previous action')
810        wx.EVT_MENU(self, GUIFRAME_ID.REDO_ID, self.on_redo_panel)
811        #self._edit_menu.AppendSeparator()
812        #self._edit_menu.Append(GUIFRAME_ID.BOOKMARK_ID, '&Bookmark',
813        #                       'bookmark current panel')
814        #wx.EVT_MENU(self, GUIFRAME_ID.BOOKMARK_ID, self.append_bookmark)
815        self._edit_menu.Append(GUIFRAME_ID.SAVE_ID, '&Save As', 
816                               'Save current panel into file')
817        wx.EVT_MENU(self, GUIFRAME_ID.SAVE_ID, self.on_save_panel)
818        self._edit_menu.AppendSeparator()
819        self._edit_menu.Append(GUIFRAME_ID.PREVIEW_ID, '&Print Preview',
820                               'Preview current panel')
821        wx.EVT_MENU(self, GUIFRAME_ID.PREVIEW_ID, self.on_preview_panel)
822        self._edit_menu.Append(GUIFRAME_ID.PRINT_ID, '&Print',
823                               'Print current panel')
824        wx.EVT_MENU(self, GUIFRAME_ID.PRINT_ID, self.on_print_panel)
825        self._edit_menu.AppendSeparator()
826        self._edit_menu.Append(GUIFRAME_ID.ZOOM_ID, '&Zoom',
827                               'Zoom current panel')
828        wx.EVT_MENU(self, GUIFRAME_ID.ZOOM_ID, self.on_zoom_panel)
829        self._edit_menu.Append(GUIFRAME_ID.ZOOM_IN_ID, '&Zoom In',
830                               'Zoom in current panel')
831        wx.EVT_MENU(self, GUIFRAME_ID.ZOOM_IN_ID, self.on_zoom_in_panel)
832        self._edit_menu.Append(GUIFRAME_ID.ZOOM_OUT_ID, '&Zoom Out', 
833                               'Zoom out current panel')
834        wx.EVT_MENU(self, GUIFRAME_ID.ZOOM_OUT_ID, self.on_zoom_out_panel)
835        self._edit_menu.Append(GUIFRAME_ID.DRAG_ID, '&Drag',
836                               'Drag current panel')
837        wx.EVT_MENU(self, GUIFRAME_ID.DRAG_ID, self.on_drag_panel)
838        self._edit_menu.Append(GUIFRAME_ID.RESET_ID, '&Reset', 
839                               'Reset current panel')
840        wx.EVT_MENU(self, GUIFRAME_ID.RESET_ID, self.on_reset_panel)
841        self._menubar.Append(self._edit_menu,  '&Edit')
842        self.enable_edit_menu()
843       
844    def get_style(self):
845        """
846        """
847        return  self.__gui_style
848   
849    def _add_menu_data(self):
850        """
851        Add menu item item data to menu bar
852        """
853        if self._data_plugin is not None:
854            menu_list = self._data_plugin.populate_menu(self)
855            if menu_list:
856                for (menu, name) in menu_list:
857                    self._menubar.Append(menu, name)
858           
859    def _on_hide_toolbar(self, event=None):
860        """
861        hide or show toolbar
862        """
863        if self._toolbar is None:
864            return
865        if self._toolbar.IsShown():
866            if self._toolbar_menu is not None:
867                self._toolbar_menu.SetItemLabel('Show Toolbar')
868            self._toolbar.Hide()
869        else:
870            if self._toolbar_menu is not None:
871                self._toolbar_menu.SetItemLabel('Hide Toolbar')
872            self._toolbar.Show()
873        self._toolbar.Realize()
874       
875    def _on_status_event(self, evt):
876        """
877        Display status message
878        """
879        self.sb.set_status(event=evt)
880       
881    def _on_view(self, evt):
882        """
883        A panel was selected to be shown. If it's not already
884        shown, display it.
885       
886        :param evt: menu event
887       
888        """
889        self.show_panel(evt.GetId())
890       
891    def on_close_welcome_panel(self):
892        """
893        Close the welcome panel
894        """
895        if self.defaultPanel is None:
896            return 
897        self._mgr.GetPane(self.panels["default"].window_name).Hide()
898        self._mgr.Update()
899        # set a default perspective
900        self.set_default_perspective()
901       
902    def show_welcome_panel(self, event):
903        """   
904        Display the welcome panel
905        """
906        if self.defaultPanel is None:
907            return 
908        for id in self.panels.keys():
909            if id  ==  'default':
910                # Show default panel
911                if not self._mgr.GetPane(self.panels["default"].window_name).IsShown():
912                    self._mgr.GetPane(self.panels["default"].window_name).Show(True)
913            elif id == "data_panel":
914                flag = self._mgr.GetPane(self.panels["data_panel"].window_name).IsShown()
915                self._mgr.GetPane(self.panels["data_panel"].window_name).Show(flag)
916            else:
917                self._mgr.GetPane(self.panels[id].window_name).IsShown()
918                self._mgr.GetPane(self.panels[id].window_name).Hide()
919        self._mgr.Update()
920       
921    def show_panel(self, uid):
922        """
923        Shows the panel with the given id
924       
925        :param uid: unique ID number of the panel to show
926       
927        """
928        ID = str(uid)
929        config.printEVT("show_panel: %s" % ID)
930        if ID in self.panels.keys():
931            if not self._mgr.GetPane(self.panels[ID].window_name).IsShown():
932                self._mgr.GetPane(self.panels[ID].window_name).Show()
933                # Hide default panel
934                self._mgr.GetPane(self.panels["default"].window_name).Hide()
935            self._mgr.Update()
936   
937    def clear_panel(self):
938        """
939        """
940        for item in self.panels:
941            try:
942                self.panels[item].clear_panel()
943            except:
944                pass
945           
946    def create_gui_data(self, data, path=None):
947        """
948        """
949        return self._data_manager.create_gui_data(data, path)
950   
951    def get_data(self, path):
952        """
953        """
954        message = ""
955        log_msg = ''
956        output = []
957        error_message = ""
958        basename  = os.path.basename(path)
959        root, extension = os.path.splitext(basename)
960        if extension.lower() not in EXTENSIONS:
961            log_msg = "File Loader cannot "
962            log_msg += "load: %s\n" % str(basename)
963            log_msg += "Try Data opening...."
964            logging.info(log_msg)
965            self.load_complete(output=output, error_message=error_message,
966                   message=log_msg, path=path)   
967            return
968       
969        #reading a state file
970        for plug in self.plugins:
971            reader, ext = plug.get_extensions()
972            if reader is not None:
973                #read the state of the single plugin
974                if extension == ext:
975                    reader.read(path)
976                    return
977                elif extension == '.svs':
978                    reader.read(path)
979       
980        style = self.__gui_style & GUIFRAME.MANAGER_ON
981        if style == GUIFRAME.MANAGER_ON:
982            if self._data_panel is not None:
983                data_state = self._data_manager.get_selected_data()
984                self._data_panel.load_data_list(data_state)
985                self._mgr.GetPane(self._data_panel.window_name).Show(True)
986                       
987    def _on_open_state(self, event):
988        """
989        """
990        path = None
991        if self._default_save_location == None:
992            self._default_save_location = os.getcwd()
993 
994        wlist = ['SansView files (*.svs)|*.svs',
995                  'P(r) files (*.prv)|*.prv',
996                  'Fitting files (*.fitv)|*.fitv',
997                  'Invariant files (*.inv)|*.inv']
998        wlist = '|'.join(wlist)
999        dlg = wx.FileDialog(self, 
1000                            "Choose a file", 
1001                            self._default_save_location, "",
1002                             wlist)
1003        if dlg.ShowModal() == wx.ID_OK:
1004            path = dlg.GetPath()
1005            if path is not None:
1006                self._default_save_location = os.path.dirname(path)
1007        dlg.Destroy()
1008        if path and os.path.isfile(path):
1009            basename  = os.path.basename(path)
1010            if  basename.endswith('.svs'):
1011                #remove panels for new states
1012                for plug in self.plugins:
1013                    plug.clear_panel()
1014                    self.panel_on_focus = None
1015               
1016            self.get_data(path)
1017               
1018        if self.defaultPanel is not None and \
1019            self._mgr.GetPane(self.panels["default"].window_name).IsShown():
1020            self.on_close_welcome_panel()
1021   
1022    def _on_save_application(self, event):
1023        """
1024        save the state of the current active application
1025        """
1026        if self.panel_on_focus is not None:
1027            self.panel_on_focus.on_save(event)
1028           
1029    def _on_save_project(self, event):
1030        """
1031        save the state of the current active application
1032        """
1033        ## Default file location for save
1034        self._default_save_location = os.getcwd()
1035        if self._current_perspective is  None:
1036            return
1037        reader, ext = self._current_perspective.get_extensions()
1038        path = None
1039        dlg = wx.FileDialog(self, "Save Project file",
1040                            self._default_save_location, "", '.svs', wx.SAVE)
1041        if dlg.ShowModal() == wx.ID_OK:
1042            path = dlg.GetPath()
1043            self._default_save_location = os.path.dirname(path)
1044        else:
1045            return None
1046        dlg.Destroy()
1047        if path is None:
1048            return
1049        # default cansas xml doc
1050        doc = None
1051        for panel in self.panels.values():
1052            doc = self.on_save_helper(doc, reader, panel, path)
1053       
1054           
1055    def on_save_helper(self, doc, reader, panel, path):
1056        """
1057        Save state into a file
1058        """
1059        try:
1060            data = panel.get_data()
1061            state = panel.get_state()
1062            if reader is not None:
1063                if data is not None:
1064                    new_doc = reader.write_toXML(data, state)
1065                    if hasattr(doc, "firstChild"):
1066                        child = new_doc.firstChild.firstChild
1067                        doc.firstChild.appendChild(child) 
1068                    else:
1069                        doc = new_doc
1070        except: 
1071            raise
1072            #pass
1073        # Write the XML document
1074        if doc != None:
1075            fd = open(path, 'w')
1076            fd.write(doc.toprettyxml())
1077            fd.close()
1078        else:
1079            raise
1080            #print "Nothing to save..."
1081            #raise RuntimeError, "%s is not a SansView (.svs) file..." % path
1082        return doc
1083
1084    def quit_guiframe(self):
1085        """
1086        Pop up message to make sure the user wants to quit the application
1087        """
1088        message = "Do you really want to quit \n"
1089        message += "this application?"
1090        dial = wx.MessageDialog(self, message, 'Question',
1091                           wx.YES_NO|wx.YES_DEFAULT|wx.ICON_QUESTION)
1092        if dial.ShowModal() == wx.ID_YES:
1093            return True
1094        else:
1095            return False   
1096       
1097    def Close(self, event=None):
1098        """
1099        Quit the application
1100        """
1101        #flag = self.quit_guiframe()
1102        if True:
1103            wx.Exit()
1104            sys.exit()
1105
1106    def _check_update(self, event=None): 
1107        """
1108        Check with the deployment server whether a new version
1109        of the application is available.
1110        A thread is started for the connecting with the server. The thread calls
1111        a call-back method when the current version number has been obtained.
1112        """
1113        if hasattr(config, "__update_URL__"):
1114            import version
1115            checker = version.VersionThread(config.__update_URL__,
1116                                            self._process_version,
1117                                            baggage=event==None)
1118            checker.start() 
1119   
1120    def _process_version(self, version, standalone=True):
1121        """
1122        Call-back method for the process of checking for updates.
1123        This methods is called by a VersionThread object once the current
1124        version number has been obtained. If the check is being done in the
1125        background, the user will not be notified unless there's an update.
1126       
1127        :param version: version string
1128        :param standalone: True of the update is being checked in
1129           the background, False otherwise.
1130           
1131        """
1132        try:
1133            if cmp(version, config.__version__) > 0:
1134                msg = "Version %s is available! See the Help "
1135                msg += "menu to download it." % version
1136                self.SetStatusText(msg)
1137                if not standalone:
1138                    import webbrowser
1139                    webbrowser.open(config.__download_page__)
1140            else:
1141                if not standalone:
1142                    msg = "You have the latest version"
1143                    msg += " of %s" % config.__appname__
1144                    self.SetStatusText(msg)
1145        except:
1146            msg = "guiframe: could not get latest application"
1147            msg += " version number\n  %s" % sys.exc_value
1148            logging.error(msg)
1149            if not standalone:
1150                msg = "Could not connect to the application server."
1151                msg += " Please try again later."
1152                self.SetStatusText(msg)
1153                   
1154    def _onAbout(self, evt):
1155        """
1156        Pop up the about dialog
1157       
1158        :param evt: menu event
1159       
1160        """
1161        if config._do_aboutbox:
1162            import aboutbox 
1163            dialog = aboutbox.DialogAbout(None, -1, "")
1164            dialog.ShowModal()           
1165           
1166    def set_manager(self, manager):
1167        """
1168        Sets the application manager for this frame
1169       
1170        :param manager: frame manager
1171        """
1172        self.app_manager = manager
1173       
1174    def post_init(self):
1175        """
1176        This initialization method is called after the GUI
1177        has been created and all plug-ins loaded. It calls
1178        the post_init() method of each plug-in (if it exists)
1179        so that final initialization can be done.
1180        """
1181        for item in self.plugins:
1182            if hasattr(item, "post_init"):
1183                item.post_init()
1184       
1185    def set_default_perspective(self):
1186        """
1187        Choose among the plugin the first plug-in that has
1188        "set_default_perspective" method and its return value is True will be
1189        as a default perspective when the welcome page is closed
1190        """
1191        for item in self.plugins:
1192            if hasattr(item, "set_default_perspective"):
1193                if item.set_default_perspective():
1194                    item.on_perspective(event=None)
1195                    return 
1196       
1197    def set_perspective(self, panels):
1198        """
1199        Sets the perspective of the GUI.
1200        Opens all the panels in the list, and closes
1201        all the others.
1202       
1203        :param panels: list of panels
1204        """
1205        for item in self.panels:
1206            # Check whether this is a sticky panel
1207            if hasattr(self.panels[item], "ALWAYS_ON"):
1208                if self.panels[item].ALWAYS_ON:
1209                    continue 
1210            if self.panels[item].window_name in panels:
1211                if not self._mgr.GetPane(self.panels[item].window_name).IsShown():
1212                    self._mgr.GetPane(self.panels[item].window_name).Show()
1213            else:
1214                # always show the data panel if enable
1215                style = self.__gui_style & GUIFRAME.MANAGER_ON
1216                if (style == GUIFRAME.MANAGER_ON) and self.panels[item] == self._data_panel:
1217                    if 'data_panel' in self.panels.keys():
1218                        flag = self._mgr.GetPane(self.panels['data_panel'].window_name).IsShown()
1219                        self._mgr.GetPane(self.panels['data_panel'].window_name).Show(flag)
1220                else:
1221                    if self._mgr.GetPane(self.panels[item].window_name).IsShown():
1222                        self._mgr.GetPane(self.panels[item].window_name).Hide()
1223        self._mgr.Update()
1224       
1225    def show_data_panel(self, event=None):
1226        """
1227        show the data panel
1228        """
1229        label = self._data_panel_menu.GetText()
1230        if label == 'Data Explorer ON':
1231            pane = self._mgr.GetPane(self.panels["data_panel"].window_name)
1232            #if not pane.IsShown():
1233            pane.Show(True)
1234            self._mgr.Update()
1235            self.__gui_style = self.__gui_style | GUIFRAME.MANAGER_ON
1236           
1237            self._data_panel_menu.SetText('Data Explorer OFF')
1238        else:
1239            pane = self._mgr.GetPane(self.panels["data_panel"].window_name)
1240            #if not pane.IsShown():
1241            pane.Show(False)
1242            self._mgr.Update()
1243            self.__gui_style = self.__gui_style & (~GUIFRAME.MANAGER_ON)
1244            self._data_panel_menu.SetText('Data Explorer ON')
1245   
1246    def add_data_helper(self, data_list):
1247        """
1248        """
1249        self._data_manager.add_data(data_list)
1250       
1251    def add_data(self, data_list):
1252        """
1253        receive a list of data . store them its data manager if possible
1254        determine if data was be plot of send to data perspectives
1255        """
1256        #send a list of available data to plotting plugin
1257        avalaible_data = []
1258        theory_list = []
1259        if self._data_manager is not None:
1260            self._data_manager.add_data(data_list)
1261            avalaible_data = self._data_manager.get_all_data()
1262        style = self.__gui_style & GUIFRAME.MANAGER_ON
1263        if style == GUIFRAME.MANAGER_ON:
1264            #wait for button press from the data panel to set_data
1265            if self._data_panel is not None:
1266                self._mgr.GetPane(self._data_panel.window_name).Show(True)
1267                self._mgr.Update() 
1268        else:
1269            #automatically send that to the current perspective
1270            self.set_data(data_list)
1271       
1272         # set data in the data panel
1273        if self._data_panel is not None:
1274            data_state = self._data_manager.get_selected_data()
1275            self._data_panel.load_data_list(data_state)
1276           
1277    def get_data_from_panel(self, data_id, plot=False,append=False):
1278        """
1279        receive a list of data key retreive the data from data manager and set
1280        then to the current perspective
1281        """
1282        data_dict = self._data_manager.get_by_id(data_id)
1283        data_list = []
1284        for data_state in data_dict.values():
1285            data_list.append(data_state.data)
1286        if plot:
1287            self.plot_data(data_list, append=append)
1288        else:
1289            #sent data to active application
1290            self.set_data(data_list=data_list)
1291       
1292       
1293    def set_data(self, data_list):
1294        """
1295        set data to current perspective
1296        """
1297        if self._current_perspective is not None:
1298            try:
1299                self._current_perspective.set_data(data_list)
1300            except:
1301                msg = str(sys.exc_value)
1302                wx.PostEvent(self, StatusEvent(status=msg, info="error"))
1303        else:
1304            msg = "Guiframe does not have a current perspective"
1305            logging.info(msg)
1306           
1307    def plot_data(self, data_list, append=False):
1308        """
1309        send a list of data to plot
1310        """
1311        if not data_list:
1312            message = "Please check data to plot or append"
1313            wx.PostEvent(self, StatusEvent(status=message, info='warning'))
1314            return 
1315        for new_plot in data_list:
1316            if append:
1317                if self.panel_on_focus is None or \
1318                    not self.enable_add_data(new_plot):
1319                    message = "cannot append plot. No plot panel on focus!"
1320                    message += "please click on any available plot to set focus"
1321                    wx.PostEvent(self, StatusEvent(status=message, 
1322                                                   info='warning'))
1323                    return 
1324                else:
1325                    if self.enable_add_data(new_plot) and \
1326                    hasattr(self.panel_on_focus, 'group_id'):
1327                        new_plot.group_id.append(self.panel_on_focus.group_id)
1328            else:
1329                #if not append then new plot
1330                new_plot.group_id.append(wx.NewId())
1331            wx.PostEvent(self, NewPlotEvent(plot=new_plot,
1332                                                  title=str(new_plot.title)))
1333           
1334 
1335               
1336    def remove_data(self, data_id, theory_id=None, delete_all=True):
1337        """
1338        Delete data state if data_id is provide
1339        delete theory created with data of id data_id if theory_id is provide
1340        if delete all true: delete the all state
1341        else delete theory
1342        """
1343        self._data_manager.delete_data(data_id=data_id, 
1344                                       theory_id=theory_id, 
1345                                       delete_all=delete_all)
1346        for plug in self.plugins:
1347            plug.delete_data(data_id)
1348           
1349       
1350    def set_current_perspective(self, perspective):
1351        """
1352        set the current active perspective
1353        """
1354        self._current_perspective = perspective
1355        name = "No current Application selected"
1356        if self._current_perspective is not None:
1357            self._add_current_plugin_menu()
1358            for panel in self.panels.values():
1359                if hasattr(panel, 'CENTER_PANE') and panel.CENTER_PANE:
1360                    for name in self._current_perspective.get_perspective():
1361                        if name == panel.window_name:
1362                            panel.on_set_focus(event=None)
1363                            break
1364                           
1365            name = self._current_perspective.sub_menu
1366            if self._data_panel is not None:
1367                self._data_panel.set_active_perspective(name)
1368                self._check_applications_menu()
1369 
1370    def _check_applications_menu(self):
1371        """
1372        check the menu of the current application
1373        """
1374        if self._applications_menu is not None:
1375            for menu in self._applications_menu.GetMenuItems():
1376                if self._current_perspective is not None:
1377                    name = self._current_perspective.sub_menu
1378                    if menu.IsCheckable():
1379                        if menu.GetLabel() == name:
1380                            menu.Check(True)
1381                        else:
1382                             menu.Check(False) 
1383           
1384    def set_plotpanel_floating(self, event=None):
1385        """
1386        make the plot panel floatable
1387        """
1388        self.__gui_style &= (~GUIFRAME.FIXED_PANEL)
1389        self.__gui_style |= GUIFRAME.FLOATING_PANEL
1390        for p in self.panels.values():
1391            plot_panel = self._plotting_plugin.plot_panels
1392            for p in self.panels.values():
1393                if p in plot_panel:
1394                    self._popup_floating_panel(p)
1395       
1396    def set_plotpanel_fixed(self, event=None):
1397        """
1398        make the plot panel fixed
1399        """
1400        self.__gui_style &= (~GUIFRAME.FLOATING_PANEL)
1401        self.__gui_style |= GUIFRAME.FIXED_PANEL
1402        plot_panel = []
1403        if self._plotting_plugin is not None:
1404            plot_panel = self._plotting_plugin.plot_panels
1405            for p in self.panels.values():
1406                if p in plot_panel:
1407                    self._popup_fixed_panel(p)
1408                   
1409    def _popup_fixed_panel(self, p):
1410        """
1411        """
1412        style = self.__gui_style & GUIFRAME.FIXED_PANEL
1413        if style == GUIFRAME.FIXED_PANEL:
1414            self._mgr.GetPane(p.window_name).Floatable()
1415            self._mgr.GetPane(p.window_name).Right()
1416            self._mgr.GetPane(p.window_name).TopDockable(False)
1417            self._mgr.GetPane(p.window_name).BottomDockable(False)
1418            self._mgr.GetPane(p.window_name).LeftDockable(False)
1419            self._mgr.GetPane(p.window_name).RightDockable(True)
1420            flag = self._mgr.GetPane(p.window_name).IsShown()
1421            self._mgr.GetPane(p.window_name).Show(flag)
1422            self._mgr.Update()
1423           
1424    def _popup_floating_panel(self, p):
1425        """
1426        """
1427        style = self.__gui_style &  GUIFRAME.FLOATING_PANEL
1428        if style == GUIFRAME.FLOATING_PANEL: 
1429            self._mgr.GetPane(p.window_name).Floatable(True)
1430            self._mgr.GetPane(p.window_name).Float()
1431            self._mgr.GetPane(p.window_name).Dockable(False)
1432            flag = self._mgr.GetPane(p.window_name).IsShown()
1433            self._mgr.GetPane(p.window_name).Show(flag)
1434            self._mgr.Update()
1435           
1436    def enable_add_data(self, new_plot):
1437        """
1438        Enable append data on a plot panel
1439        """
1440        is_theory = len(self.panel_on_focus.plots) <= 1 and \
1441            self.panel_on_focus.plots.values()[0].__class__.__name__ == "Theory1D"
1442           
1443        is_data2d = hasattr(new_plot, 'data')
1444        is_data1d = self.panel_on_focus.__class__.__name__ == "ModelPanel1D"\
1445            and self.panel_on_focus.group_id is not None
1446        has_meta_data = hasattr(new_plot, 'meta_data')
1447       
1448        #disable_add_data if the data is being recovered from  a saved state file.
1449        is_state_data = False
1450        if has_meta_data:
1451            if 'invstate' in new_plot.meta_data: is_state_data = True
1452            if  'prstate' in new_plot.meta_data: is_state_data = True
1453            if  'fitstate' in new_plot.meta_data: is_state_data = True
1454   
1455        return is_data1d and not is_data2d and not is_theory and not is_state_data
1456   
1457    def enable_edit_menu(self):
1458        """
1459        enable menu item under edit menu depending on the panel on focus
1460        """
1461        if self.panel_on_focus is not None and self._edit_menu is not None:
1462            flag = self.panel_on_focus.get_undo_flag()
1463            self._edit_menu.Enable(GUIFRAME_ID.UNDO_ID, flag)
1464            flag = self.panel_on_focus.get_redo_flag()
1465            self._edit_menu.Enable(GUIFRAME_ID.REDO_ID, flag)
1466            #flag = self.panel_on_focus.get_bookmark_flag()
1467            #self._edit_menu.Enable(GUIFRAME_ID.BOOKMARK_ID, flag)
1468            flag = self.panel_on_focus.get_save_flag()
1469            self._edit_menu.Enable(GUIFRAME_ID.SAVE_ID, flag)
1470            flag = self.panel_on_focus.get_print_flag()
1471            self._edit_menu.Enable(GUIFRAME_ID.PRINT_ID, flag)
1472            flag = self.panel_on_focus.get_preview_flag()
1473            self._edit_menu.Enable(GUIFRAME_ID.PREVIEW_ID, flag)
1474            flag = self.panel_on_focus.get_zoom_flag()
1475            self._edit_menu.Enable(GUIFRAME_ID.ZOOM_ID, flag)
1476            flag = self.panel_on_focus.get_zoom_in_flag()
1477            self._edit_menu.Enable(GUIFRAME_ID.ZOOM_IN_ID, flag)
1478            flag = self.panel_on_focus.get_zoom_out_flag()
1479            self._edit_menu.Enable(GUIFRAME_ID.ZOOM_OUT_ID, flag)
1480            flag = self.panel_on_focus.get_drag_flag()
1481            self._edit_menu.Enable(GUIFRAME_ID.DRAG_ID, flag)
1482            flag = self.panel_on_focus.get_reset_flag()
1483            self._edit_menu.Enable(GUIFRAME_ID.RESET_ID, flag)
1484        else:
1485            flag = False
1486            self._edit_menu.Enable(GUIFRAME_ID.UNDO_ID, flag)
1487            self._edit_menu.Enable(GUIFRAME_ID.REDO_ID, flag)
1488            #self._edit_menu.Enable(GUIFRAME_ID.BOOKMARK_ID, flag)
1489            self._edit_menu.Enable(GUIFRAME_ID.SAVE_ID, flag)
1490            self._edit_menu.Enable(GUIFRAME_ID.PRINT_ID, flag)
1491            self._edit_menu.Enable(GUIFRAME_ID.PREVIEW_ID, flag)
1492            self._edit_menu.Enable(GUIFRAME_ID.ZOOM_ID, flag)
1493            self._edit_menu.Enable(GUIFRAME_ID.ZOOM_IN_ID, flag)
1494            self._edit_menu.Enable(GUIFRAME_ID.ZOOM_OUT_ID, flag)
1495            self._edit_menu.Enable(GUIFRAME_ID.DRAG_ID, flag)
1496            self._edit_menu.Enable(GUIFRAME_ID.RESET_ID, flag)
1497           
1498    def on_undo_panel(self, event=None):
1499        """
1500        undo previous action of the last panel on focus if possible
1501        """
1502        if self.panel_on_focus is not None:
1503            self.panel_on_focus.on_undo(event)
1504           
1505    def on_redo_panel(self, event=None):
1506        """
1507        redo the last cancel action done on the last panel on focus
1508        """
1509        if self.panel_on_focus is not None:
1510            self.panel_on_focus.on_redo(event)
1511           
1512    def on_bookmark_panel(self, event=None):
1513        """
1514        bookmark panel
1515        """
1516        if self.panel_on_focus is not None:
1517            self.panel_on_focus.on_bookmark(event)
1518           
1519    def append_bookmark(self, event=None):
1520        """
1521        Bookmark available information of the panel on focus
1522        """
1523        self._toolbar.append_bookmark(event)
1524           
1525    def on_save_panel(self, event=None):
1526        """
1527        save possible information on the current panel
1528        """
1529        if self.panel_on_focus is not None:
1530            self.panel_on_focus.on_save(event)
1531           
1532    def on_preview_panel(self, event=None):
1533        """
1534        preview information on the panel on focus
1535        """
1536        if self.panel_on_focus is not None:
1537            self.panel_on_focus.on_preview(event)
1538           
1539    def on_print_panel(self, event=None):
1540        """
1541        print available information on the last panel on focus
1542        """
1543        if self.panel_on_focus is not None:
1544            self.panel_on_focus.on_print(event)
1545           
1546    def on_zoom_panel(self, event=None):
1547        """
1548        zoom on the current panel if possible
1549        """
1550        if self.panel_on_focus is not None:
1551            self.panel_on_focus.on_zoom(event)
1552           
1553    def on_zoom_in_panel(self, event=None):
1554        """
1555        zoom in of the panel on focus
1556        """
1557        if self.panel_on_focus is not None:
1558            self.panel_on_focus.on_zoom_in(event)
1559           
1560    def on_zoom_out_panel(self, event=None):
1561        """
1562        zoom out on the panel on focus
1563        """
1564        if self.panel_on_focus is not None:
1565            self.panel_on_focus.on_zoom_out(event)
1566           
1567    def on_drag_panel(self, event=None):
1568        """
1569        drag apply to the panel on focus
1570        """
1571        if self.panel_on_focus is not None:
1572            self.panel_on_focus.on_drag(event)
1573           
1574    def on_reset_panel(self, event=None):
1575        """
1576        reset the current panel
1577        """
1578        if self.panel_on_focus is not None:
1579            self.panel_on_focus.on_reset(event)
1580           
1581    def enable_undo(self):
1582        """
1583        enable undo related control
1584        """
1585        if self.panel_on_focus is not None:
1586            self._toolbar.enable_undo(self.panel_on_focus)
1587           
1588    def enable_redo(self):
1589        """
1590        enable redo
1591        """
1592        if self.panel_on_focus is not None:
1593            self._toolbar.enable_redo(self.panel_on_focus)
1594           
1595    def enable_bookmark(self):
1596        """
1597        Bookmark
1598        """
1599        if self.panel_on_focus is not None:
1600            self._toolbar.enable_bookmark(self.panel_on_focus)
1601           
1602    def enable_save(self):
1603        """
1604        save
1605        """
1606        if self.panel_on_focus is not None:
1607            self._toolbar.enable_save(self.panel_on_focus)
1608           
1609    def enable_preview(self):
1610        """
1611        preview
1612        """
1613        if self.panel_on_focus is not None:
1614            self._toolbar.enable_preview(self.panel_on_focus)
1615           
1616    def enable_print(self):
1617        """
1618        print
1619        """
1620        if self.panel_on_focus is not None:
1621            self._toolbar.enable_print(self.panel_on_focus)
1622           
1623    def enable_zoom(self):
1624        """
1625        zoom
1626        """
1627        if self.panel_on_focus is not None:
1628            self._toolbar.enable_zoom(self.panel_on_focus)
1629           
1630    def enable_zoom_in(self):
1631        """
1632        zoom in
1633        """
1634        if self.panel_on_focus is not None:
1635            self._toolbar.enable_zoom_in(self.panel_on_focus)
1636           
1637    def enable_zoom_out(self):
1638        """
1639        zoom out
1640        """
1641        if self.panel_on_focus is not None:
1642            self._toolbar.enable_zoom_out(self.panel_on_focus)
1643           
1644    def enable_drag(self, event=None):
1645        """
1646        drag
1647        """
1648        if self.panel_on_focus is not None:
1649            self._toolbar.enable_drag(self.panel_on_focus)
1650           
1651    def enable_reset(self):
1652        """
1653        reset the current panel
1654        """
1655        if self.panel_on_focus is not None:
1656            self._toolbar.enable_reset(self.panel_on_focus)
1657       
1658class DefaultPanel(wx.Panel, PanelBase):
1659    """
1660    Defines the API for a panels to work with
1661    the GUI manager
1662    """
1663    ## Internal nickname for the window, used by the AUI manager
1664    window_name = "default"
1665    ## Name to appear on the window title bar
1666    window_caption = "Welcome panel"
1667    ## Flag to tell the AUI manager to put this panel in the center pane
1668    CENTER_PANE = True
1669    def __init__(self, parent, *args, **kwds):
1670        wx.Panel.__init__(self, parent, *args, **kwds)
1671        PanelBase.__init__(self, parent)
1672   
1673
1674
1675# Toy application to test this Frame
1676class ViewApp(wx.App):
1677    """
1678    """
1679    SIZE = (GUIFRAME_WIDTH,GUIFRAME_HEIGHT)
1680    TITLE = config.__appname__
1681    PROG_SPLASH_PATH = PROG_SPLASH_SCREEN
1682    STYLE = GUIFRAME.SINGLE_APPLICATION
1683    def OnInit(self):
1684        """
1685        """
1686        pos, size = self.window_placement(self.SIZE)
1687        self.frame = ViewerFrame(parent=None, 
1688                                 title=self.TITLE, 
1689                                 pos=pos, 
1690                                 gui_style = self.STYLE,
1691                                 size=size) 
1692         # Display a splash screen on top of the frame.
1693        if len(sys.argv) > 1 and '--time' in sys.argv[1:]:
1694            log_time("Starting to display the splash screen")
1695        if self.PROG_SPLASH_PATH is not None and \
1696            os.path.isfile(self.PROG_SPLASH_PATH):
1697            try:
1698                self.display_splash_screen(parent=self.frame, path=self.PROG_SPLASH_PATH)   
1699            except:
1700                msg = "Cannot display splash screen\n"
1701                msg += str (sys.exc_value)
1702                logging.error(msg)
1703        self.frame.Show(True)
1704
1705        if hasattr(self.frame, 'special'):
1706            self.frame.special.SetCurrent()
1707        self.SetTopWindow(self.frame)
1708        return True
1709   
1710    def set_manager(self, manager):
1711        """
1712        Sets a reference to the application manager
1713        of the GUI manager (Frame)
1714        """
1715        self.frame.set_manager(manager)
1716       
1717    def build_gui(self):
1718        """
1719        Build the GUI
1720        """
1721        self.frame.build_gui()
1722        self.frame.post_init()
1723       
1724    def set_welcome_panel(self, panel_class):
1725        """
1726        Set the welcome panel
1727       
1728        :param panel_class: class of the welcome panel to be instantiated
1729       
1730        """
1731        self.frame.set_welcome_panel(panel_class)
1732       
1733    def add_perspective(self, perspective):
1734        """
1735        Manually add a perspective to the application GUI
1736        """
1737        self.frame.add_perspective(perspective)
1738   
1739    def window_placement(self, size):
1740        """
1741        Determines the position and size of the application frame such that it
1742        fits on the user's screen without obstructing (or being obstructed by)
1743        the Windows task bar.  The maximum initial size in pixels is bounded by
1744        WIDTH x HEIGHT.  For most monitors, the application
1745        will be centered on the screen; for very large monitors it will be
1746        placed on the left side of the screen.
1747        """
1748        window_width, window_height = size
1749        screen_size = wx.GetDisplaySize()
1750        window_height = window_height if screen_size[1]>window_height else screen_size[1]-50
1751        window_width  = window_width if screen_size[0]> window_width else screen_size[0]-50
1752        xpos = ypos = 0
1753
1754        # Note that when running Linux and using an Xming (X11) server on a PC
1755        # with a dual  monitor configuration, the reported display size may be
1756        # that of both monitors combined with an incorrect display count of 1.
1757        # To avoid displaying this app across both monitors, we check for
1758        # screen 'too big'.  If so, we assume a smaller width which means the
1759        # application will be placed towards the left hand side of the screen.
1760
1761        _, _, x, y = wx.Display().GetClientArea() # size excludes task bar
1762        if len(sys.argv) > 1 and '--platform' in sys.argv[1:]:
1763            w, h = wx.DisplaySize()  # size includes task bar area
1764        if x > 1920: x = 1280  # display on left side, not centered on screen
1765        if x > window_width:  xpos = (x - window_width)/2
1766        if y > window_height: ypos = (y - window_height)/2
1767
1768        # Return the suggested position and size for the application frame.
1769        return (xpos, ypos), (min(x, window_width), min(y, window_height))
1770   
1771    def display_splash_screen(self, parent, path=PROG_SPLASH_SCREEN):
1772        """Displays the splash screen.  It will exactly cover the main frame."""
1773
1774        # Prepare the picture.  On a 2GHz intel cpu, this takes about a second.
1775        x, y = parent.GetSizeTuple()
1776        image = wx.Image(path, wx.BITMAP_TYPE_PNG)
1777        image.Rescale(x, y, wx.IMAGE_QUALITY_HIGH)
1778        bm = image.ConvertToBitmap()
1779
1780        # Create and show the splash screen.  It will disappear only when the
1781        # program has entered the event loop AND either the timeout has expired
1782        # or the user has left clicked on the screen.  Thus any processing
1783        # performed in this routine (including sleeping) or processing in the
1784        # calling routine (including doing imports) will prevent the splash
1785        # screen from disappearing.
1786        #
1787        # Note that on Linux, the timeout appears to occur immediately in which
1788        # case the splash screen disappears upon entering the event loop.
1789        wx.SplashScreen(bitmap=bm,
1790                        splashStyle=(wx.SPLASH_CENTRE_ON_PARENT|
1791                                     wx.SPLASH_TIMEOUT|
1792                                     wx.STAY_ON_TOP),
1793                        milliseconds=4000,
1794                        parent=parent,
1795                        id=wx.ID_ANY)
1796
1797        # Keep the splash screen up a minimum amount of time for non-Windows
1798        # systems.  This is a workaround for Linux and possibly MacOS that
1799        # appear to ignore the splash screen timeout option.
1800        if '__WXMSW__' not in wx.PlatformInfo:
1801            if len(sys.argv) > 1 and '--time' in sys.argv[1:]:
1802                log_time("Starting sleep of 2 secs")
1803            time.sleep(2)
1804
1805        # A call to wx.Yield does not appear to be required.  If used on
1806        # Windows, the cursor changes from 'busy' to 'ready' before the event
1807        # loop is reached which is not desirable.  On Linux it seems to have
1808        # no effect.
1809        #wx.Yield()
1810
1811       
1812
1813if __name__ == "__main__": 
1814    app = ViewApp(0)
1815    app.MainLoop()
1816
1817             
Note: See TracBrowser for help on using the repository browser.