source: sasview/guiframe/gui_manager.py @ 84e5533

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

working on load data from command line

  • Property mode set to 100644
File size: 76.2 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_from_cmd(self,  path):   
1032        """
1033        """ 
1034        print "load_from_cmd", path
1035        if path is  None:
1036            return
1037        else:
1038            path = os.path.abspath(path)
1039            if not os.path.isfile(path):
1040               print "return abs path", path
1041               return
1042             
1043            print "find a path -->", path
1044
1045        basename  = os.path.basename(path)
1046        root, extension = os.path.splitext(basename)
1047        if extension.lower() not in EXTENSIONS:
1048            self.load_data(path)
1049            print "load data"
1050        else:
1051            self.load_state(path)
1052            "load state"
1053       
1054    def load_state(self, path):   
1055        """
1056        """
1057        if path and (path is not None) and os.path.isfile(path):
1058            basename  = os.path.basename(path)
1059            if APPLICATION_STATE_EXTENSION is not None \
1060                and basename.endswith(APPLICATION_STATE_EXTENSION):
1061                #remove panels for new states
1062                for plug in self.plugins:
1063                    reader, ext = plug.get_extensions()
1064                    if ext is not None and ext.strip() != ''\
1065                        and ext.lower() not in EXTENSIONS:
1066                        plug.clear_panel() 
1067            self.panel_on_focus = None   
1068            self.get_data(path)
1069        if self.defaultPanel is not None and \
1070            self._mgr.GetPane(self.panels["default"].window_name).IsShown():
1071            self.on_close_welcome_panel()
1072           
1073    def load_data(self, path):
1074        """
1075        """
1076        if not os.path.isfile(path):
1077            return
1078        basename  = os.path.basename(path)
1079        root, extension = os.path.splitext(basename)
1080        if extension.lower() in EXTENSIONS:
1081            log_msg = "Data Loader cannot "
1082            log_msg += "load: %s\n" % str(path)
1083            log_msg += "Try File opening ...."
1084            print log_msg
1085            return
1086   
1087        try:
1088            print "Loading Data..." + str(path) + "\n"
1089            temp =  self.loader.load(path)
1090            if temp.__class__.__name__ == "list":
1091                for item in temp:
1092                    data = self.parent.create_gui_data(item, path)
1093                    output[data.id] = data
1094            else:
1095                data = self.parent.create_gui_data(temp, path)
1096                output[data.id] = data
1097           
1098            self.add_data(data_list=output)
1099        except:
1100            error_message = "Error while loading Data: %s\n" % str(path)
1101            error_message += str(sys.exc_value) + "\n"
1102            print error_message
1103           
1104     
1105    def _on_open_state_application(self, event):
1106        """
1107        """
1108        path = None
1109        if self._default_save_location == None:
1110            self._default_save_location = os.getcwd()
1111 
1112        dlg = wx.FileDialog(self, 
1113                            "Choose a file", 
1114                            self._default_save_location, "",
1115                             PLUGINS_WLIST)
1116        if dlg.ShowModal() == wx.ID_OK:
1117            path = dlg.GetPath()
1118            if path is not None:
1119                self._default_save_location = os.path.dirname(path)
1120        dlg.Destroy()
1121        self.load_state(path=path) 
1122           
1123    def _on_open_state_project(self, event):
1124        """
1125        """
1126        path = None
1127        if self._default_save_location == None:
1128            self._default_save_location = os.getcwd()
1129 
1130        dlg = wx.FileDialog(self, 
1131                            "Choose a file", 
1132                            self._default_save_location, "",
1133                             APPLICATION_WLIST)
1134        if dlg.ShowModal() == wx.ID_OK:
1135            path = dlg.GetPath()
1136            if path is not None:
1137                self._default_save_location = os.path.dirname(path)
1138        dlg.Destroy()
1139        self.load_state(path=path)
1140   
1141    def _on_save_application(self, event):
1142        """
1143        save the state of the current active application
1144        """
1145        if self.panel_on_focus is not None:
1146            self.panel_on_focus.on_save(event)
1147           
1148    def _on_save_project(self, event):
1149        """
1150        save the state of the current active application
1151        """
1152        ## Default file location for save
1153        self._default_save_location = os.getcwd()
1154        if self._current_perspective is  None:
1155            return
1156        reader, ext = self._current_perspective.get_extensions()
1157        path = None
1158        dlg = wx.FileDialog(self, "Save Project file",
1159                            self._default_save_location, "",
1160                             APPLICATION_STATE_EXTENSION, 
1161                             wx.SAVE)
1162        if dlg.ShowModal() == wx.ID_OK:
1163            path = dlg.GetPath()
1164            self._default_save_location = os.path.dirname(path)
1165        else:
1166            return None
1167        dlg.Destroy()
1168        if path is None:
1169            return
1170        # default cansas xml doc
1171        doc = None
1172        for panel in self.panels.values():
1173            doc = self.on_save_helper(doc, reader, panel, path)
1174       
1175           
1176    def on_save_helper(self, doc, reader, panel, path):
1177        """
1178        Save state into a file
1179        """
1180        try:
1181            data = panel.get_data()
1182            state = panel.get_state()
1183            if reader is not None:
1184                if data is not None:
1185                    new_doc = reader.write_toXML(data, state)
1186                    if hasattr(doc, "firstChild"):
1187                        child = new_doc.firstChild.firstChild
1188                        doc.firstChild.appendChild(child) 
1189                    else:
1190                        doc = new_doc
1191        except: 
1192            raise
1193            #pass
1194        # Write the XML document
1195        if doc != None:
1196            fd = open(path, 'w')
1197            fd.write(doc.toprettyxml())
1198            fd.close()
1199        else:
1200            msg = "%s cannot read %s\n" % (str(APPLICATION_NAME), str(path))
1201            raise RuntimeError, msg
1202        return doc
1203
1204    def quit_guiframe(self):
1205        """
1206        Pop up message to make sure the user wants to quit the application
1207        """
1208        message = "Do you really want to quit \n"
1209        message += "this application?"
1210        dial = wx.MessageDialog(self, message, 'Question',
1211                           wx.YES_NO|wx.YES_DEFAULT|wx.ICON_QUESTION)
1212        if dial.ShowModal() == wx.ID_YES:
1213            return True
1214        else:
1215            return False   
1216       
1217    def Close(self, event=None):
1218        """
1219        Quit the application
1220        """
1221        #flag = self.quit_guiframe()
1222        if True:
1223            wx.Exit()
1224            sys.exit()
1225
1226    def _check_update(self, event=None): 
1227        """
1228        Check with the deployment server whether a new version
1229        of the application is available.
1230        A thread is started for the connecting with the server. The thread calls
1231        a call-back method when the current version number has been obtained.
1232        """
1233        if hasattr(config, "__update_URL__"):
1234            import version
1235            checker = version.VersionThread(config.__update_URL__,
1236                                            self._process_version,
1237                                            baggage=event==None)
1238            checker.start() 
1239   
1240    def _process_version(self, version, standalone=True):
1241        """
1242        Call-back method for the process of checking for updates.
1243        This methods is called by a VersionThread object once the current
1244        version number has been obtained. If the check is being done in the
1245        background, the user will not be notified unless there's an update.
1246       
1247        :param version: version string
1248        :param standalone: True of the update is being checked in
1249           the background, False otherwise.
1250           
1251        """
1252        try:
1253            if cmp(version, config.__version__) > 0:
1254                msg = "Version %s is available! See the Help "
1255                msg += "menu to download it." % version
1256                self.SetStatusText(msg)
1257                if not standalone:
1258                    import webbrowser
1259                    webbrowser.open(config.__download_page__)
1260            else:
1261                if not standalone:
1262                    msg = "You have the latest version"
1263                    msg += " of %s" % config.__appname__
1264                    self.SetStatusText(msg)
1265        except:
1266            msg = "guiframe: could not get latest application"
1267            msg += " version number\n  %s" % sys.exc_value
1268            logging.error(msg)
1269            if not standalone:
1270                msg = "Could not connect to the application server."
1271                msg += " Please try again later."
1272                self.SetStatusText(msg)
1273                   
1274    def _onAbout(self, evt):
1275        """
1276        Pop up the about dialog
1277       
1278        :param evt: menu event
1279       
1280        """
1281        if config._do_aboutbox:
1282            import aboutbox 
1283            dialog = aboutbox.DialogAbout(None, -1, "")
1284            dialog.ShowModal()           
1285           
1286    def set_manager(self, manager):
1287        """
1288        Sets the application manager for this frame
1289       
1290        :param manager: frame manager
1291        """
1292        self.app_manager = manager
1293       
1294    def post_init(self):
1295        """
1296        This initialization method is called after the GUI
1297        has been created and all plug-ins loaded. It calls
1298        the post_init() method of each plug-in (if it exists)
1299        so that final initialization can be done.
1300        """
1301        for item in self.plugins:
1302            if hasattr(item, "post_init"):
1303                item.post_init()
1304       
1305    def set_default_perspective(self):
1306        """
1307        Choose among the plugin the first plug-in that has
1308        "set_default_perspective" method and its return value is True will be
1309        as a default perspective when the welcome page is closed
1310        """
1311        for item in self.plugins:
1312            if hasattr(item, "set_default_perspective"):
1313                if item.set_default_perspective():
1314                    item.on_perspective(event=None)
1315                    return 
1316       
1317    def set_perspective(self, panels):
1318        """
1319        Sets the perspective of the GUI.
1320        Opens all the panels in the list, and closes
1321        all the others.
1322       
1323        :param panels: list of panels
1324        """
1325        for item in self.panels:
1326            # Check whether this is a sticky panel
1327            if hasattr(self.panels[item], "ALWAYS_ON"):
1328                if self.panels[item].ALWAYS_ON:
1329                    continue 
1330            if self.panels[item].window_name in panels:
1331                if not self._mgr.GetPane(self.panels[item].window_name).IsShown():
1332                    self._mgr.GetPane(self.panels[item].window_name).Show()
1333            else:
1334                # always show the data panel if enable
1335                style = self.__gui_style & GUIFRAME.MANAGER_ON
1336                if (style == GUIFRAME.MANAGER_ON) and self.panels[item] == self._data_panel:
1337                    if 'data_panel' in self.panels.keys():
1338                        flag = self._mgr.GetPane(self.panels['data_panel'].window_name).IsShown()
1339                        self._mgr.GetPane(self.panels['data_panel'].window_name).Show(flag)
1340                else:
1341                    if self._mgr.GetPane(self.panels[item].window_name).IsShown():
1342                        self._mgr.GetPane(self.panels[item].window_name).Hide()
1343        self._mgr.Update()
1344       
1345    def show_data_panel(self, event=None):
1346        """
1347        show the data panel
1348        """
1349        label = self._data_panel_menu.GetText()
1350        if label == 'Data Explorer ON':
1351            pane = self._mgr.GetPane(self.panels["data_panel"].window_name)
1352            #if not pane.IsShown():
1353            pane.Show(True)
1354            self._mgr.Update()
1355            self.__gui_style = self.__gui_style | GUIFRAME.MANAGER_ON
1356           
1357            self._data_panel_menu.SetText('Data Explorer OFF')
1358        else:
1359            pane = self._mgr.GetPane(self.panels["data_panel"].window_name)
1360            #if not pane.IsShown():
1361            pane.Show(False)
1362            self._mgr.Update()
1363            self.__gui_style = self.__gui_style & (~GUIFRAME.MANAGER_ON)
1364            self._data_panel_menu.SetText('Data Explorer ON')
1365   
1366    def add_data_helper(self, data_list):
1367        """
1368        """
1369        if self._data_manager is not None:
1370            self._data_manager.add_data(data_list)
1371       
1372    def add_data(self, data_list):
1373        """
1374        receive a dictionary of data from loader
1375        store them its data manager if possible
1376        send to data the current active perspective if the data panel
1377        is not active.
1378        :param data_list: dictionary of data's ID and value Data
1379        """
1380        #Store data into manager
1381        self.add_data_helper(data_list)
1382        # set data in the data panel
1383        if self._data_panel is not None:
1384            data_state = self._data_manager.get_data_state(data_list.keys())
1385            self._data_panel.load_data_list(data_state)
1386        #if the data panel is shown wait for the user to press a button
1387        #to send data to the current perspective. if the panel is not
1388        #show  automatically send the data to the current perspective
1389        style = self.__gui_style & GUIFRAME.MANAGER_ON
1390        if style == GUIFRAME.MANAGER_ON:
1391            #wait for button press from the data panel to set_data
1392            if self._data_panel is not None:
1393                self._mgr.GetPane(self._data_panel.window_name).Show(True)
1394                self._mgr.Update() 
1395        else:
1396            #automatically send that to the current perspective
1397            self.set_data(data_id=data_list.keys())
1398       
1399    def set_data(self, data_id): 
1400        """
1401        set data to current perspective
1402        """
1403        list_data, _ = self._data_manager.get_by_id(data_id)
1404        if self._current_perspective is not None:
1405            self._current_perspective.set_data(list_data.values())
1406        else:
1407            msg = "Guiframe does not have a current perspective"
1408            logging.info(msg)
1409           
1410    def set_theory(self, state_id, theory_id=None):
1411        """
1412        """
1413        _, list_theory = self._data_manager.get_by_id(theory_id)
1414        if self._current_perspective is not None:
1415            try:
1416                self._current_perspective.set_theory(list_theory.values())
1417            except:
1418                msg = "Guiframe set_theory: \n" + str(sys.exc_value)
1419                logging.info(msg)
1420                wx.PostEvent(self, StatusEvent(status=msg, info="error"))
1421        else:
1422            msg = "Guiframe does not have a current perspective"
1423            logging.info(msg)
1424           
1425    def plot_data(self,  state_id, data_id=None,
1426                  theory_id=None, append=False):
1427        """
1428        send a list of data to plot
1429        """
1430        total_plot_list = []
1431        data_list, _ = self._data_manager.get_by_id(data_id)
1432        _, temp_list_theory = self._data_manager.get_by_id(theory_id)
1433        total_plot_list = data_list.values()
1434        for item in temp_list_theory.values():
1435            theory_data, theory_state = item
1436            total_plot_list.append(theory_data)
1437        GROUP_ID = wx.NewId()
1438        for new_plot in total_plot_list:
1439            if append:
1440                if self.panel_on_focus is None:
1441                    message = "cannot append plot. No plot panel on focus!"
1442                    message += "please click on any available plot to set focus"
1443                    wx.PostEvent(self, StatusEvent(status=message, 
1444                                                   info='warning'))
1445                    return 
1446                else:
1447                    if self.enable_add_data(new_plot):
1448                        new_plot.group_id = self.panel_on_focus.group_id
1449                    else:
1450                        message = "Only 1D Data can be append to plot panel\n"
1451                        message += "%s will be plot separetly\n" %str(new_plot.name)
1452                        wx.PostEvent(self, StatusEvent(status=message, 
1453                                                   info='warning'))
1454            else:
1455                #if not append then new plot
1456                new_plot.group_id = GROUP_ID
1457            title = "PLOT " + str(new_plot.title)
1458            wx.PostEvent(self, NewPlotEvent(plot=new_plot,
1459                                                  title=title))
1460           
1461    def remove_data(self, data_id, theory_id=None):
1462        """
1463        Delete data state if data_id is provide
1464        delete theory created with data of id data_id if theory_id is provide
1465        if delete all true: delete the all state
1466        else delete theory
1467        """
1468        for plug in self.plugins:
1469            plug.delete_data(data_id)
1470        total_plot_list = []
1471        data_list, _ = self._data_manager.get_by_id(data_id)
1472        _, temp_list_theory = self._data_manager.get_by_id(theory_id)
1473        total_plot_list = data_list.values()
1474        for item in temp_list_theory.values():
1475            theory_data, theory_state = item
1476            total_plot_list.append(theory_data)
1477        for new_plot in total_plot_list:
1478            id = new_plot.id
1479            for group_id in new_plot.list_group_id:
1480                wx.PostEvent(self, NewPlotEvent(id=id,
1481                                                   group_id=group_id,
1482                                                   action='remove'))
1483        self._data_manager.delete_data(data_id=data_id, 
1484                                       theory_id=theory_id)
1485           
1486       
1487    def set_current_perspective(self, perspective):
1488        """
1489        set the current active perspective
1490        """
1491        self._current_perspective = perspective
1492        name = "No current Application selected"
1493        if self._current_perspective is not None:
1494            self._add_current_plugin_menu()
1495            for panel in self.panels.values():
1496                if hasattr(panel, 'CENTER_PANE') and panel.CENTER_PANE:
1497                    for name in self._current_perspective.get_perspective():
1498                        if name == panel.window_name:
1499                            panel.on_set_focus(event=None)
1500                            break
1501                           
1502            name = self._current_perspective.sub_menu
1503            if self._data_panel is not None:
1504                self._data_panel.set_active_perspective(name)
1505                self._check_applications_menu()
1506 
1507    def _check_applications_menu(self):
1508        """
1509        check the menu of the current application
1510        """
1511        if self._applications_menu is not None:
1512            for menu in self._applications_menu.GetMenuItems():
1513                if self._current_perspective is not None:
1514                    name = self._current_perspective.sub_menu
1515                    if menu.IsCheckable():
1516                        if menu.GetLabel() == name:
1517                            menu.Check(True)
1518                        else:
1519                             menu.Check(False) 
1520           
1521    def set_plotpanel_floating(self, event=None):
1522        """
1523        make the plot panel floatable
1524        """
1525        self.__gui_style &= (~GUIFRAME.FIXED_PANEL)
1526        self.__gui_style |= GUIFRAME.FLOATING_PANEL
1527        for p in self.panels.values():
1528            plot_panel = self._plotting_plugin.plot_panels.values()
1529            for p in self.panels.values():
1530                if p in plot_panel:
1531                    self._popup_floating_panel(p)
1532       
1533    def set_plotpanel_fixed(self, event=None):
1534        """
1535        make the plot panel fixed
1536        """
1537        self.__gui_style &= (~GUIFRAME.FLOATING_PANEL)
1538        self.__gui_style |= GUIFRAME.FIXED_PANEL
1539        plot_panel = []
1540        if self._plotting_plugin is not None:
1541            plot_panel = self._plotting_plugin.plot_panels.values()
1542            for p in self.panels.values():
1543                if p in plot_panel:
1544                    self._popup_fixed_panel(p)
1545                   
1546    def _popup_fixed_panel(self, p):
1547        """
1548        """
1549        style = self.__gui_style & GUIFRAME.FIXED_PANEL
1550        if style == GUIFRAME.FIXED_PANEL:
1551            self._mgr.GetPane(p.window_name).Floatable()
1552            self._mgr.GetPane(p.window_name).Right()
1553            self._mgr.GetPane(p.window_name).TopDockable(False)
1554            self._mgr.GetPane(p.window_name).BottomDockable(False)
1555            self._mgr.GetPane(p.window_name).LeftDockable(False)
1556            self._mgr.GetPane(p.window_name).RightDockable(True)
1557            flag = self._mgr.GetPane(p.window_name).IsShown()
1558            self._mgr.GetPane(p.window_name).Show(flag)
1559            self._mgr.Update()
1560           
1561    def _popup_floating_panel(self, p):
1562        """
1563        """
1564        style = self.__gui_style &  GUIFRAME.FLOATING_PANEL
1565        if style == GUIFRAME.FLOATING_PANEL: 
1566            self._mgr.GetPane(p.window_name).Floatable(True)
1567            self._mgr.GetPane(p.window_name).Float()
1568            self._mgr.GetPane(p.window_name).Dockable(False)
1569            flag = self._mgr.GetPane(p.window_name).IsShown()
1570            self._mgr.GetPane(p.window_name).Show(flag)
1571            self._mgr.Update()
1572           
1573    def enable_add_data(self, new_plot):
1574        """
1575        Enable append data on a plot panel
1576        """
1577        if self.panel_on_focus not in self._plotting_plugin.plot_panels.values():
1578            return
1579        is_theory = len(self.panel_on_focus.plots) <= 1 and \
1580            self.panel_on_focus.plots.values()[0].__class__.__name__ == "Theory1D"
1581           
1582        is_data2d = hasattr(new_plot, 'data')
1583        is_data1d = self.panel_on_focus.__class__.__name__ == "ModelPanel1D"\
1584            and self.panel_on_focus.group_id is not None
1585        has_meta_data = hasattr(new_plot, 'meta_data')
1586       
1587        #disable_add_data if the data is being recovered from  a saved state file.
1588        is_state_data = False
1589        if has_meta_data:
1590            if 'invstate' in new_plot.meta_data: is_state_data = True
1591            if  'prstate' in new_plot.meta_data: is_state_data = True
1592            if  'fitstate' in new_plot.meta_data: is_state_data = True
1593   
1594        return is_data1d and not is_data2d and not is_theory and not is_state_data
1595   
1596    def enable_edit_menu(self):
1597        """
1598        enable menu item under edit menu depending on the panel on focus
1599        """
1600        if self.panel_on_focus is not None and self._edit_menu is not None:
1601            flag = self.panel_on_focus.get_undo_flag()
1602            self._edit_menu.Enable(GUIFRAME_ID.UNDO_ID, flag)
1603            flag = self.panel_on_focus.get_redo_flag()
1604            self._edit_menu.Enable(GUIFRAME_ID.REDO_ID, flag)
1605            flag = self.panel_on_focus.get_print_flag()
1606            self._edit_menu.Enable(GUIFRAME_ID.PRINT_ID, flag)
1607            flag = self.panel_on_focus.get_preview_flag()
1608            self._edit_menu.Enable(GUIFRAME_ID.PREVIEW_ID, flag)
1609            flag = self.panel_on_focus.get_reset_flag()
1610            self._edit_menu.Enable(GUIFRAME_ID.RESET_ID, flag)
1611        else:
1612            flag = False
1613            self._edit_menu.Enable(GUIFRAME_ID.UNDO_ID, flag)
1614            self._edit_menu.Enable(GUIFRAME_ID.REDO_ID, flag)
1615            self._edit_menu.Enable(GUIFRAME_ID.PRINT_ID, flag)
1616            self._edit_menu.Enable(GUIFRAME_ID.PREVIEW_ID, flag)
1617            self._edit_menu.Enable(GUIFRAME_ID.RESET_ID, flag)
1618           
1619    def on_undo_panel(self, event=None):
1620        """
1621        undo previous action of the last panel on focus if possible
1622        """
1623        if self.panel_on_focus is not None:
1624            self.panel_on_focus.on_undo(event)
1625           
1626    def on_redo_panel(self, event=None):
1627        """
1628        redo the last cancel action done on the last panel on focus
1629        """
1630        if self.panel_on_focus is not None:
1631            self.panel_on_focus.on_redo(event)
1632           
1633    def on_bookmark_panel(self, event=None):
1634        """
1635        bookmark panel
1636        """
1637        if self.panel_on_focus is not None:
1638            self.panel_on_focus.on_bookmark(event)
1639           
1640    def append_bookmark(self, event=None):
1641        """
1642        Bookmark available information of the panel on focus
1643        """
1644        self._toolbar.append_bookmark(event)
1645           
1646    def on_save_panel(self, event=None):
1647        """
1648        save possible information on the current panel
1649        """
1650        if self.panel_on_focus is not None:
1651            self.panel_on_focus.on_save(event)
1652           
1653    def on_preview_panel(self, event=None):
1654        """
1655        preview information on the panel on focus
1656        """
1657        if self.panel_on_focus is not None:
1658            self.panel_on_focus.on_preview(event)
1659           
1660    def on_print_panel(self, event=None):
1661        """
1662        print available information on the last panel on focus
1663        """
1664        if self.panel_on_focus is not None:
1665            self.panel_on_focus.on_print(event)
1666           
1667    def on_zoom_panel(self, event=None):
1668        """
1669        zoom on the current panel if possible
1670        """
1671        if self.panel_on_focus is not None:
1672            self.panel_on_focus.on_zoom(event)
1673           
1674    def on_zoom_in_panel(self, event=None):
1675        """
1676        zoom in of the panel on focus
1677        """
1678        if self.panel_on_focus is not None:
1679            self.panel_on_focus.on_zoom_in(event)
1680           
1681    def on_zoom_out_panel(self, event=None):
1682        """
1683        zoom out on the panel on focus
1684        """
1685        if self.panel_on_focus is not None:
1686            self.panel_on_focus.on_zoom_out(event)
1687           
1688    def on_drag_panel(self, event=None):
1689        """
1690        drag apply to the panel on focus
1691        """
1692        if self.panel_on_focus is not None:
1693            self.panel_on_focus.on_drag(event)
1694           
1695    def on_reset_panel(self, event=None):
1696        """
1697        reset the current panel
1698        """
1699        if self.panel_on_focus is not None:
1700            self.panel_on_focus.on_reset(event)
1701           
1702    def enable_undo(self):
1703        """
1704        enable undo related control
1705        """
1706        if self.panel_on_focus is not None:
1707            self._toolbar.enable_undo(self.panel_on_focus)
1708           
1709    def enable_redo(self):
1710        """
1711        enable redo
1712        """
1713        if self.panel_on_focus is not None:
1714            self._toolbar.enable_redo(self.panel_on_focus)
1715           
1716    def enable_bookmark(self):
1717        """
1718        Bookmark
1719        """
1720        if self.panel_on_focus is not None:
1721            self._toolbar.enable_bookmark(self.panel_on_focus)
1722           
1723    def enable_save(self):
1724        """
1725        save
1726        """
1727        if self.panel_on_focus is not None:
1728            self._toolbar.enable_save(self.panel_on_focus)
1729           
1730    def enable_preview(self):
1731        """
1732        preview
1733        """
1734        if self.panel_on_focus is not None:
1735            self._toolbar.enable_preview(self.panel_on_focus)
1736           
1737    def enable_print(self):
1738        """
1739        print
1740        """
1741        if self.panel_on_focus is not None:
1742            self._toolbar.enable_print(self.panel_on_focus)
1743           
1744    def enable_zoom(self):
1745        """
1746        zoom
1747        """
1748        if self.panel_on_focus is not None:
1749            self._toolbar.enable_zoom(self.panel_on_focus)
1750           
1751    def enable_zoom_in(self):
1752        """
1753        zoom in
1754        """
1755        if self.panel_on_focus is not None:
1756            self._toolbar.enable_zoom_in(self.panel_on_focus)
1757           
1758    def enable_zoom_out(self):
1759        """
1760        zoom out
1761        """
1762        if self.panel_on_focus is not None:
1763            self._toolbar.enable_zoom_out(self.panel_on_focus)
1764           
1765    def enable_drag(self, event=None):
1766        """
1767        drag
1768        """
1769        if self.panel_on_focus is not None:
1770            self._toolbar.enable_drag(self.panel_on_focus)
1771           
1772    def enable_reset(self):
1773        """
1774        reset the current panel
1775        """
1776        if self.panel_on_focus is not None:
1777            self._toolbar.enable_reset(self.panel_on_focus)
1778       
1779class DefaultPanel(wx.Panel, PanelBase):
1780    """
1781    Defines the API for a panels to work with
1782    the GUI manager
1783    """
1784    ## Internal nickname for the window, used by the AUI manager
1785    window_name = "default"
1786    ## Name to appear on the window title bar
1787    window_caption = "Welcome panel"
1788    ## Flag to tell the AUI manager to put this panel in the center pane
1789    CENTER_PANE = True
1790    def __init__(self, parent, *args, **kwds):
1791        wx.Panel.__init__(self, parent, *args, **kwds)
1792        PanelBase.__init__(self, parent)
1793   
1794
1795
1796# Toy application to test this Frame
1797class ViewApp(wx.App):
1798    """
1799    """
1800    def OnInit(self):
1801        """
1802        """
1803        pos, size = self.window_placement((GUIFRAME_WIDTH, GUIFRAME_HEIGHT))
1804        self.frame = ViewerFrame(parent=None, 
1805                                 title=APPLICATION_NAME, 
1806                                 pos=pos, 
1807                                 gui_style = DEFAULT_STYLE,
1808                                 size=size) 
1809        self.s_screen = None
1810        # Display a splash screen on top of the frame.
1811        if len(sys.argv) > 1 and '--time' in sys.argv[1:]:
1812            log_time("Starting to display the splash screen")
1813       
1814        try:
1815            if os.path.isfile(SPLASH_SCREEN_PATH):
1816                self.s_screen = self.display_splash_screen(parent=self.frame, 
1817                                        path=SPLASH_SCREEN_PATH)
1818            else:
1819                self.frame.Show()   
1820        except:
1821           msg = "Cannot display splash screen\n"
1822           msg += str (sys.exc_value)
1823           logging.error(msg)
1824           self.frame.Show()
1825           
1826        if hasattr(self.frame, 'special'):
1827            self.frame.special.SetCurrent()
1828        self.SetTopWindow(self.frame)
1829        self.input_file = None
1830        self.dir = None
1831        print "sys.argv", sys.argv
1832        if len(sys.argv) >= 2:
1833            print "sys.argv 0", sys.argv[0]
1834            cmd = sys.argv[0].lower()
1835            if os.path.isfile(cmd):
1836                basename  = os.path.basename(cmd)
1837                self.dir = os.path.dirname(cmd)
1838                print "basename", basename
1839                if basename in ['sansview.py', 'sansview.exe']:
1840                    print "sys.argv 1", sys.argv[1]
1841                    self.input_file = sys.argv[1]
1842        return True
1843
1844    def open_file(self):
1845        """
1846        open a state file at the start of the application
1847        """
1848       
1849        if self.frame is not None:
1850            self.frame.load_from_cmd(path=self.input_file)
1851         
1852           
1853    def set_manager(self, manager):
1854        """
1855        Sets a reference to the application manager
1856        of the GUI manager (Frame)
1857        """
1858        self.frame.set_manager(manager)
1859       
1860    def build_gui(self):
1861        """
1862        Build the GUI
1863        """
1864        self.frame.build_gui()
1865        self.frame.post_init()
1866        #try to load file at the start
1867        try:
1868            self.open_file()
1869        except:
1870            raise
1871        if self.s_screen is not None and self.s_screen.IsShown():
1872            self.s_screen.Close()
1873       
1874    def set_welcome_panel(self, panel_class):
1875        """
1876        Set the welcome panel
1877       
1878        :param panel_class: class of the welcome panel to be instantiated
1879       
1880        """
1881        self.frame.set_welcome_panel(panel_class)
1882       
1883    def add_perspective(self, perspective):
1884        """
1885        Manually add a perspective to the application GUI
1886        """
1887        self.frame.add_perspective(perspective)
1888   
1889    def window_placement(self, size):
1890        """
1891        Determines the position and size of the application frame such that it
1892        fits on the user's screen without obstructing (or being obstructed by)
1893        the Windows task bar.  The maximum initial size in pixels is bounded by
1894        WIDTH x HEIGHT.  For most monitors, the application
1895        will be centered on the screen; for very large monitors it will be
1896        placed on the left side of the screen.
1897        """
1898        window_width, window_height = size
1899        screen_size = wx.GetDisplaySize()
1900        window_height = window_height if screen_size[1]>window_height else screen_size[1]-50
1901        window_width  = window_width if screen_size[0]> window_width else screen_size[0]-50
1902        xpos = ypos = 0
1903
1904        # Note that when running Linux and using an Xming (X11) server on a PC
1905        # with a dual  monitor configuration, the reported display size may be
1906        # that of both monitors combined with an incorrect display count of 1.
1907        # To avoid displaying this app across both monitors, we check for
1908        # screen 'too big'.  If so, we assume a smaller width which means the
1909        # application will be placed towards the left hand side of the screen.
1910
1911        _, _, x, y = wx.Display().GetClientArea() # size excludes task bar
1912        if len(sys.argv) > 1 and '--platform' in sys.argv[1:]:
1913            w, h = wx.DisplaySize()  # size includes task bar area
1914        if x > 1920: x = 1280  # display on left side, not centered on screen
1915        if x > window_width:  xpos = (x - window_width)/2
1916        if y > window_height: ypos = (y - window_height)/2
1917
1918        # Return the suggested position and size for the application frame.
1919        return (xpos, ypos), (min(x, window_width), min(y, window_height))
1920   
1921    def display_splash_screen(self, parent, 
1922                              path=SPLASH_SCREEN_PATH):
1923        """Displays the splash screen.  It will exactly cover the main frame."""
1924       
1925        # Prepare the picture.  On a 2GHz intel cpu, this takes about a second.
1926        x, y = parent.GetSizeTuple()
1927        image = wx.Image(path, wx.BITMAP_TYPE_PNG)
1928        image.Rescale(SPLASH_SCREEN_WIDTH, 
1929                      SPLASH_SCREEN_HEIGHT, wx.IMAGE_QUALITY_HIGH)
1930        bm = image.ConvertToBitmap()
1931
1932        # Create and show the splash screen.  It will disappear only when the
1933        # program has entered the event loop AND either the timeout has expired
1934        # or the user has left clicked on the screen.  Thus any processing
1935        # performed in this routine (including sleeping) or processing in the
1936        # calling routine (including doing imports) will prevent the splash
1937        # screen from disappearing.
1938        #
1939        # Note that on Linux, the timeout appears to occur immediately in which
1940        # case the splash screen disappears upon entering the event loop.
1941        s_screen = wx.SplashScreen(bitmap=bm,
1942                         splashStyle=(wx.SPLASH_TIMEOUT|
1943                                              wx.SPLASH_CENTRE_ON_SCREEN),
1944                                 style=(wx.SIMPLE_BORDER|
1945                                        wx.FRAME_NO_TASKBAR|
1946                                        wx.STAY_ON_TOP),
1947                                       
1948                        milliseconds=SS_MAX_DISPLAY_TIME,
1949                        parent=parent,
1950                        id=wx.ID_ANY)
1951
1952        s_screen.Bind(wx.EVT_CLOSE, self.on_close_splash_screen)
1953        s_screen.Show()
1954        return s_screen
1955       
1956       
1957    def on_close_splash_screen(self, event):
1958        """
1959        """
1960        self.frame.Show(True)
1961        event.Skip()
1962     
1963     
1964
1965       
1966
1967if __name__ == "__main__": 
1968    app = ViewApp(0)
1969    app.MainLoop()
1970
1971             
Note: See TracBrowser for help on using the repository browser.