source: sasview/guiframe/gui_manager.py @ cf9b6950

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

working on data manager

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