source: sasview/guiframe/gui_manager.py @ fcc5680

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

add new menu item to load project and load application

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