source: sasview/guiframe/gui_manager.py @ 2e3f9e3

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 2e3f9e3 was 2e3f9e3, checked in by Jae Cho <jhjcho@…>, 13 years ago

fixed svs project saving

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