source: sasview/guiframe/gui_manager.py @ 25c1576

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 25c1576 was 0c26793, checked in by Jae Cho <jhjcho@…>, 14 years ago

readjust size of panels

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