source: sasview/sansguiframe/src/sans/guiframe/gui_manager.py @ 33fdb34

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

fixed for mac check menuitems

  • Property mode set to 100644
File size: 118.1 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
18import time
19import py_compile
20# Try to find a local config
21import imp
22import warnings
23warnings.simplefilter("ignore")
24import logging
25
26
27from sans.guiframe.events import EVT_STATUS
28from sans.guiframe.events import EVT_APPEND_BOOKMARK
29from sans.guiframe.events import EVT_PANEL_ON_FOCUS
30from sans.guiframe.events import EVT_NEW_LOAD_DATA
31from sans.guiframe.events import EVT_NEW_COLOR
32from sans.guiframe.events import StatusEvent
33from sans.guiframe.events import NewPlotEvent
34from sans.guiframe.gui_style import GUIFRAME
35from sans.guiframe.gui_style import GUIFRAME_ID
36from sans.guiframe.data_panel import DataPanel
37from sans.guiframe.panel_base import PanelBase
38from sans.guiframe.gui_toolbar import GUIToolBar
39from sans.guiframe.data_processor import GridFrame
40from sans.guiframe.data_processor import BatchOutputFrame
41from sans.guiframe.events import EVT_NEW_BATCH
42from sans.dataloader.loader import Loader
43
44DATAPATH = os.getcwd()
45def _change_current_dir():
46    """
47    Get the path of the current ran file and change the application current
48    directory to the directory of that file
49    """
50    tem_path = sys.path[0]
51    if os.path.isfile(tem_path):
52        tem_path = os.path.dirname(tem_path)
53   
54    os.chdir(os.path.abspath(tem_path))
55   
56   
57_change_current_dir()   
58PATH_APP = os.getcwd()
59
60def _find_local_config(file, path):
61    """
62    Find configuration file for the current application
63    """
64   
65    file_path = os.path.abspath(os.path.join(path, "%s.py" % file))
66    if(os.path.isfile(file_path)):
67        py_compile.compile(file=file_path)
68        fObj, path_config, descr = imp.find_module(file, [path])
69        try:
70            return imp.load_module(file, fObj, path_config, descr) 
71        except:
72            raise
73        finally:
74            if fObj:
75                fObj.close()
76       
77             
78try:
79    path = PATH_APP
80    config = _find_local_config('local_config', path)
81    if config is None:
82        path, _ = os.path.split(PATH_APP)
83        config = _find_local_config('local_config', path)
84except:
85    # Didn't find local config, load the default
86    import sans.guiframe.config as config
87custom_config = None
88try:
89    path = PATH_APP
90    custom_config = _find_local_config('custom_config', path)
91    if custom_config is None:
92        path, _ = os.path.split(PATH_APP)
93        custom_config = _find_local_config('custom_config', path)
94except:
95    msg = "Custom_config file was not imported"
96    logging.info(msg)
97   
98
99#read some constants from config
100APPLICATION_STATE_EXTENSION = config.APPLICATION_STATE_EXTENSION
101APPLICATION_NAME = config.__appname__
102SPLASH_SCREEN_PATH = config.SPLASH_SCREEN_PATH
103WELCOME_PANEL_ON = config.WELCOME_PANEL_ON
104SPLASH_SCREEN_WIDTH = config.SPLASH_SCREEN_WIDTH
105SPLASH_SCREEN_HEIGHT = config.SPLASH_SCREEN_HEIGHT
106SS_MAX_DISPLAY_TIME = config.SS_MAX_DISPLAY_TIME
107if not WELCOME_PANEL_ON:
108        WELCOME_PANEL_SHOW = False
109else:
110    WELCOME_PANEL_SHOW = True
111try:
112    DATALOADER_SHOW = custom_config.DATALOADER_SHOW
113    TOOLBAR_SHOW = custom_config.TOOLBAR_SHOW
114    FIXED_PANEL = custom_config.FIXED_PANEL
115    if WELCOME_PANEL_ON:
116        WELCOME_PANEL_SHOW = custom_config.WELCOME_PANEL_SHOW
117    PLOPANEL_WIDTH = custom_config.PLOPANEL_WIDTH
118    DATAPANEL_WIDTH = custom_config.DATAPANEL_WIDTH
119    GUIFRAME_WIDTH = custom_config.GUIFRAME_WIDTH
120    GUIFRAME_HEIGHT = custom_config.GUIFRAME_HEIGHT
121    DEFAULT_PERSPECTIVE = custom_config.DEFAULT_PERSPECTIVE
122    CLEANUP_PLOT = custom_config.CLEANUP_PLOT
123    # custom open_path
124    open_folder = custom_config.DEFAULT_OPEN_FOLDER
125    if open_folder != None and os.path.isdir(open_folder):
126        DEFAULT_OPEN_FOLDER = os.path.abspath(open_folder)
127    else:
128        DEFAULT_OPEN_FOLDER = PATH_APP
129except:
130    DATALOADER_SHOW = True
131    TOOLBAR_SHOW = True
132    FIXED_PANEL = True
133    WELCOME_PANEL_SHOW = False
134    PLOPANEL_WIDTH = config.PLOPANEL_WIDTH
135    DATAPANEL_WIDTH = config.DATAPANEL_WIDTH
136    GUIFRAME_WIDTH = config.GUIFRAME_WIDTH
137    GUIFRAME_HEIGHT = config.GUIFRAME_HEIGHT
138    DEFAULT_PERSPECTIVE = None
139    CLEANUP_PLOT = False
140    DEFAULT_OPEN_FOLDER = PATH_APP
141
142DEFAULT_STYLE = config.DEFAULT_STYLE
143
144
145PLOPANEL_HEIGTH = config.PLOPANEL_HEIGTH
146DATAPANEL_HEIGHT = config.DATAPANEL_HEIGHT
147PLUGIN_STATE_EXTENSIONS =  config.PLUGIN_STATE_EXTENSIONS
148OPEN_SAVE_MENU = config.OPEN_SAVE_PROJECT_MENU
149VIEW_MENU = config.VIEW_MENU
150EDIT_MENU = config.EDIT_MENU
151extension_list = []
152if APPLICATION_STATE_EXTENSION is not None:
153    extension_list.append(APPLICATION_STATE_EXTENSION)
154EXTENSIONS = PLUGIN_STATE_EXTENSIONS + extension_list
155try:
156    PLUGINS_WLIST = '|'.join(config.PLUGINS_WLIST)
157except:
158    PLUGINS_WLIST = ''
159APPLICATION_WLIST = config.APPLICATION_WLIST
160IS_WIN = True
161if sys.platform.count("win32")==0:
162    IS_WIN = False
163
164   
165class ViewerFrame(wx.Frame):
166    """
167    Main application frame
168    """
169   
170    def __init__(self, parent, title, 
171                 size=(GUIFRAME_WIDTH, GUIFRAME_HEIGHT),
172                 gui_style=DEFAULT_STYLE, 
173                 style=wx.DEFAULT_FRAME_STYLE,
174                 pos=wx.DefaultPosition):
175        """
176        Initialize the Frame object
177        """
178       
179        wx.Frame.__init__(self, parent=parent, title=title, pos=pos,size=size)
180        # title
181        self.title = title
182        # Preferred window size
183        self._window_width, self._window_height = size
184        self.__gui_style = gui_style
185        # Logging info
186        logging.basicConfig(level=logging.DEBUG,
187                    format='%(asctime)s %(levelname)s %(message)s',
188                    filename='sans_app.log',
189                    filemode='w')       
190        path = os.path.dirname(__file__)
191        temp_path = os.path.join(path,'images')
192        ico_file = os.path.join(temp_path,'ball.ico')
193        if os.path.isfile(ico_file):
194            self.SetIcon(wx.Icon(ico_file, wx.BITMAP_TYPE_ICO))
195        else:
196            temp_path = os.path.join(os.getcwd(),'images')
197            ico_file = os.path.join(temp_path,'ball.ico')
198            if os.path.isfile(ico_file):
199                self.SetIcon(wx.Icon(ico_file, wx.BITMAP_TYPE_ICO))
200            else:
201                ico_file = os.path.join(os.path.dirname(os.path.sys.path[0]),
202                             'images', 'ball.ico')
203                if os.path.isfile(ico_file):
204                    self.SetIcon(wx.Icon(ico_file, wx.BITMAP_TYPE_ICO))
205        self.path = PATH_APP
206        self.application_name = APPLICATION_NAME
207        ## Application manager
208        self._input_file = None
209        self.app_manager = None
210        self._mgr = None
211        #add current perpsective
212        self._current_perspective = None
213        self._plotting_plugin = None
214        self._data_plugin = None
215        #Menu bar and item
216        self._menubar = None
217        self._file_menu = None
218        self._data_menu = None
219        self._view_menu = None
220        self._window_menu = None
221        self._data_panel_menu = None
222        self._help_menu = None
223        self._tool_menu = None
224        self._applications_menu_pos = -1
225        self._applications_menu_name = None
226        self._applications_menu = None
227        self._edit_menu = None
228        self._toolbar_menu = None
229        self._save_appl_menu = None
230        #tool bar
231        self._toolbar = None
232        # number of plugins
233        self._num_perspectives = 0
234        # plot duck cleanup option
235        self.cleanup_plots = CLEANUP_PLOT
236        # (un)-focus color
237        #self.color = '#b3b3b3'
238        ## Find plug-ins
239        # Modify this so that we can specify the directory to look into
240        self.plugins = []
241        #add local plugin
242        self.plugins += self._get_local_plugins()
243        self.plugins += self._find_plugins()
244        ## List of panels
245        self.panels = {}
246        # List of plot panels
247        self.plot_panels = {}
248        # default Graph number fot the plotpanel caption
249        self.graph_num = 0
250
251        # Default locations
252        self._default_save_location = DEFAULT_OPEN_FOLDER       
253        # Welcome panel
254        self.defaultPanel = None
255        #panel on focus
256        self.panel_on_focus = None
257        #control_panel on focus
258        self.cpanel_on_focus = None
259        self.loader = Loader()   
260        #data manager
261        from data_manager import DataManager
262        self._data_manager = DataManager()
263        self._data_panel = DataPanel(parent=self)
264        if self.panel_on_focus is not None:
265            self._data_panel.set_panel_on_focus(self.panel_on_focus.window_caption)
266        # list of plot panels in schedule to full redraw
267        self.schedule = False
268        #self.callback = True
269        self._idle_count = 0
270        self.schedule_full_draw_list = []
271        self.idletimer = wx.CallLater(1, self._onDrawIdle)
272       
273        self.batch_frame = GridFrame(parent=self)
274        self.batch_frame.Hide()
275        # Check for update
276        #self._check_update(None)
277        # Register the close event so it calls our own method
278        wx.EVT_CLOSE(self, self.Close)
279        # Register to status events
280        self.Bind(EVT_STATUS, self._on_status_event)
281        #Register add extra data on the same panel event on load
282        self.Bind(EVT_PANEL_ON_FOCUS, self.set_panel_on_focus)
283        self.Bind(EVT_APPEND_BOOKMARK, self.append_bookmark)
284        self.Bind(EVT_NEW_LOAD_DATA, self.on_load_data)
285        self.Bind(EVT_NEW_BATCH, self.on_batch_selection)
286        self.Bind(EVT_NEW_COLOR, self.on_color_selection)
287        self.setup_custom_conf()
288   
289    def on_set_batch_result(self, data_outputs, data_inputs=None,
290                             plugin_name=""):
291        """
292        Display data into a grid in batch mode and show the grid
293        """
294        t = time.localtime(time.time())
295        time_str = time.strftime("%b %d %H;%M of %Y", t)
296        name = "Batch"  +  time_str
297        details = "File Generated by %s : %s" % (APPLICATION_NAME,
298                                                     str(plugin_name))
299        details += "on %s.\n" % time_str
300        ext = ".csv"
301        file_name = "Batch_" + str(plugin_name)+ "_" + time_str + ext
302        file_name = self._default_save_location + str(file_name)
303        #Need to save configuration for later
304        frame = BatchOutputFrame(parent=self, data_outputs=data_outputs, 
305                                 data_inputs=data_inputs,
306                                file_name=file_name,
307                                details=details)
308        frame.Show(True)
309   
310    def open_with_localapp(self, data_inputs, data_outputs):
311        """
312        Display value of data into the application grid
313        :param data: dictionary of string and list of items
314        """
315        self.batch_frame.set_data(data_inputs, data_outputs)
316        self.batch_frame.Show(True)
317       
318    def on_read_batch_tofile(self, event):
319        """
320        Open a file dialog , extract the file to read and display values
321        into a grid
322        """
323        path = None
324        if self._default_save_location == None:
325            self._default_save_location = os.getcwd()
326       
327        dlg = wx.FileDialog(self, 
328                            "Choose a file", 
329                            self._default_save_location, "",
330                             "(*.csv)|*.csv| Text Files (*.txt)|*.txt")
331        if dlg.ShowModal() == wx.ID_OK:
332            path = dlg.GetPath()
333            if path is not None:
334                self._default_save_location = os.path.dirname(path)
335        dlg.Destroy()
336       
337        self.read_batch_tofile(file_name=path)
338       
339    def read_batch_tofile(self, file_name):
340        """
341        Extract value from file name and Display them into a grid
342        """
343        if file_name is None or file_name.strip() == "":
344            return
345        data = {}
346        fd = open(file_name, 'r')
347        _, ext = os.path.splitext(file_name)
348        separator = "\t"
349        if ext.lower() == ".csv":
350            separator = ","
351        buffer = fd.read()
352        lines = buffer.split('\n')
353        fd.close()
354        column_names_line  = ""
355        index = None
356        for index in range(len(lines)):
357            line = lines[index]
358            if line.find(separator) != -1:
359                #found the first line containing the label
360                column_names_line = line
361                first_data_index = index
362                break 
363        if column_names_line.strip() == "" or index is None:
364            return 
365        col_name_toks = column_names_line.split(separator)
366        c_index = 0
367        for col_index in range(len(col_name_toks)):
368            c_name = col_name_toks[col_index]
369            if c_name.strip() != "":
370                data[c_name] = [ lines[row].split(separator)[c_index]
371                                for row in range(index + 1, len(lines)-1)]
372                c_index += 1
373        self.open_with_localapp(data=data)
374       
375    def write_batch_tofile(self, data, file_name, details=""):
376        """
377        Helper to write result from batch into cvs file
378        """
379        self._default_save_location = os.path.dirname(file_name)
380        file_name = os.path.basename(file_name)
381        if data is None or file_name is None or file_name.strip() == "":
382            return
383        _, ext = os.path.splitext(file_name)
384       
385        fd = open(file_name, 'w')
386        separator = "\t"
387        if ext.lower() == ".csv":
388            separator = ","
389        fd.write(str(details))
390        for col_name  in data.keys():
391             fd.write(str(col_name))
392             fd.write(separator)
393        fd.write('\n')
394        max_list = [len(value) for value in data.values()]
395        if len(max_list) == 0:
396            return
397        max_index = max(max_list)
398        index = 0
399        while(index < max_index):
400            for value_list in data.values():
401                if index < len(value_list):
402                    fd.write(str(value_list[index]))
403                    fd.write(separator)
404                else:
405                    fd.write('')
406                    fd.write(separator)
407            fd.write('\n')
408            index += 1
409        fd.close()
410           
411    def open_with_externalapp(self, data, file_name, details=""):
412        """
413        Display data in the another application , by default Excel
414        """
415        if not os.path.exists(file_name):
416            self.write_batch_tofile(data=data, file_name=file_name,
417                                               details=details)
418        try:
419            from win32com.client import Dispatch
420            excel_app = Dispatch('Excel.Application')     
421            wb = excel_app.Workbooks.Open(file_name) 
422            excel_app.Visible = 1
423        except:
424            msg = "Error occured when calling Excel\n"
425            msg += "Check that Excel in installed in this machine or \n"
426            msg += "Check that %s really exists.\n" % str(file_name)
427            wx.PostEvent(self, StatusEvent(status=msg,
428                                             info="error"))
429           
430         
431    def on_batch_selection(self, event):
432        """
433        :param event: contains parameter enable . when enable is set to True
434        the application is in Batch mode
435        else the application is default mode(single mode)
436        """
437        self.batch_on = event.enable
438        for plug in self.plugins:
439            plug.set_batch_selection(self.batch_on)
440           
441    def on_color_selection(self, event):
442        """
443        :param event: contains parameters for id and color
444        """ 
445        color, id = event.color, event.id
446        for plug in self.plugins:
447            plug.add_color(color, id)
448       
449       
450    def setup_custom_conf(self):
451        """
452        Set up custom configuration if exists
453        """
454        if custom_config == None:
455            return
456       
457        if not FIXED_PANEL:
458            self.__gui_style &= (~GUIFRAME.FIXED_PANEL)
459            self.__gui_style |= GUIFRAME.FLOATING_PANEL
460
461        if not DATALOADER_SHOW:
462            self.__gui_style &= (~GUIFRAME.MANAGER_ON)
463
464        if not TOOLBAR_SHOW:
465            self.__gui_style &= (~GUIFRAME.TOOLBAR_ON)
466
467        if WELCOME_PANEL_SHOW:
468            self.__gui_style |= GUIFRAME.WELCOME_PANEL_ON   
469             
470    def set_custom_default_perspective(self):
471        """
472        Set default starting perspective
473        """
474        if custom_config == None:
475            return
476        for plugin in self.plugins:
477            try:
478                if plugin.sub_menu == DEFAULT_PERSPECTIVE:
479                   
480                    plugin.on_perspective(event=None)
481                    #self._check_applications_menu()
482                    break
483            except:
484                pass 
485        return         
486               
487    def on_load_data(self, event):
488        """
489        received an event to trigger load from data plugin
490        """
491        if self._data_plugin is not None:
492            self._data_plugin.load_data(event)
493           
494    def get_current_perspective(self):
495        """
496        return the current perspective
497        """
498        return self._current_perspective
499   
500    def set_input_file(self, input_file):
501        """
502        :param input_file: file to read
503        """
504        self._input_file = input_file
505       
506    def get_data_manager(self):
507        """
508        """
509        return self._data_manager
510   
511    def get_toolbar(self):
512        """
513        """
514        return self._toolbar
515   
516    def set_panel_on_focus(self, event):
517        """
518        Store reference to the last panel on focus
519        update the toolbar if available
520        update edit menu if available
521        """
522        if event != None:
523            self.panel_on_focus = event.panel
524        panel_name = 'No panel on focus'
525        application_name = 'No Selected Analysis'
526        if self.panel_on_focus is not None:
527            if self.panel_on_focus not in self.plot_panels.values():
528                for ID in self.panels.keys():
529                    if self.panel_on_focus != self.panels[ID]:
530                        self.panels[ID].on_kill_focus(None)
531
532            if self._data_panel is not None and \
533                            self.panel_on_focus is not None:
534                self.set_panel_on_focus_helper()
535                #update toolbar
536                self._update_toolbar_helper()
537                #update edit menu
538                self.enable_edit_menu()
539   
540    def set_panel_on_focus_helper(self):
541        """
542        Helper for panel on focus with data_panel
543        """
544        panel_name = self.panel_on_focus.window_caption
545        ID = self.panel_on_focus.uid
546        self._data_panel.set_panel_on_focus(ID)
547        #update combo
548        if self.panel_on_focus in self.plot_panels.values():
549            combo = self._data_panel.cb_plotpanel
550            combo_title = str(self.panel_on_focus.window_caption)
551            combo.SetStringSelection(combo_title)
552            combo.SetToolTip( wx.ToolTip(combo_title )) 
553        elif self.panel_on_focus != self._data_panel:
554            cpanel = self.panel_on_focus
555            if self.cpanel_on_focus != cpanel:
556                self.cpanel_on_focus = self.panel_on_focus
557               
558    def reset_bookmark_menu(self, panel):
559        """
560        Reset Bookmark menu list
561       
562        : param panel: a control panel or tap where the bookmark is
563        """
564        cpanel = panel
565        if self._toolbar != None and cpanel._bookmark_flag:
566            for item in  self._toolbar.get_bookmark_items():
567                self._toolbar.remove_bookmark_item(item)
568            self._toolbar.add_bookmark_default()
569            pos = 0
570            for bitem in cpanel.popUpMenu.GetMenuItems():
571                pos += 1
572                if pos < 3:
573                    continue
574                id =  bitem.GetId()
575                label = bitem.GetLabel()
576                self._toolbar.append_bookmark_item(id, label)
577                wx.EVT_MENU(self, id, cpanel._back_to_bookmark)
578            self._toolbar.Realize()
579             
580
581    def build_gui(self):
582        """
583        """
584        # set tool bar
585        self._setup_tool_bar()
586        # Set up the layout
587        self._setup_layout()
588       
589        # Set up the menu
590        self._setup_menus()
591       
592        try:
593            self.load_from_cmd(self._input_file)
594        except:
595            msg = "%s Cannot load file %s\n" %(str(APPLICATION_NAME), 
596                                             str(self._input_file))
597            msg += str(sys.exc_value) + '\n'
598            print msg
599        if self._data_panel is not None and len(self.plugins) > 0:
600            self._data_panel.fill_cbox_analysis(self.plugins)
601        self.post_init()
602        # Set Custom default
603        self.set_custom_default_perspective()
604        # Set up extra custom tool menu
605        self._setup_extra_custom()
606        #self.Show(True)
607        #self._check_update(None)
608   
609    def _setup_extra_custom(self): 
610        """
611        Set up toolbar and welcome view if needed
612        """
613        style = self.__gui_style & GUIFRAME.TOOLBAR_ON
614        if (style == GUIFRAME.TOOLBAR_ON) & (not self._toolbar.IsShown()):
615            self._on_toggle_toolbar() 
616       
617        # Set Custom deafult start page
618        welcome_style = self.__gui_style & GUIFRAME.WELCOME_PANEL_ON
619        if welcome_style == GUIFRAME.WELCOME_PANEL_ON:
620            self.show_welcome_panel(None)
621     
622    def _setup_layout(self):
623        """
624        Set up the layout
625        """
626        # Status bar
627        from gui_statusbar import StatusBar
628        self.sb = StatusBar(self, wx.ID_ANY)
629        self.SetStatusBar(self.sb)
630        # Add panel
631        default_flag = wx.aui.AUI_MGR_DEFAULT#| wx.aui.AUI_MGR_ALLOW_ACTIVE_PANE
632        self._mgr = wx.aui.AuiManager(self, flags=default_flag)
633        self._mgr.SetDockSizeConstraint(0.5, 0.5)
634        # border color
635        #self.b_color = wx.aui.AUI_DOCKART_BORDER_COLOUR 
636        #self._mgr.GetArtProvider().SetColor(self.b_color, self.color)
637        #self._mgr.SetArtProvider(wx.aui.AuiDockArt(wx.AuiDefaultDockArt))
638        #print "set", self._dockart.GetColour(13)
639        # Load panels
640        self._load_panels()
641        self.set_default_perspective()
642        self._mgr.Update()
643       
644    def SetStatusText(self, *args, **kwds):
645        """
646        """
647        number = self.sb.get_msg_position()
648        wx.Frame.SetStatusText(number=number, *args, **kwds)
649       
650    def PopStatusText(self, *args, **kwds):
651        """
652        """
653        field = self.sb.get_msg_position()
654        wx.Frame.PopStatusText(field=field)
655       
656    def PushStatusText(self, *args, **kwds):
657        """
658        """
659        field = self.sb.get_msg_position()
660        wx.Frame.PushStatusText(self, field=field, string=string)
661
662    def add_perspective(self, plugin):
663        """
664        Add a perspective if it doesn't already
665        exist.
666        """
667        self._num_perspectives += 1
668        is_loaded = False
669        for item in self.plugins:
670            if plugin.__class__ == item.__class__:
671                msg = "Plugin %s already loaded" % plugin.sub_menu
672                logging.info(msg)
673                is_loaded = True 
674        if not is_loaded:
675           
676            self.plugins.append(plugin)
677             
678     
679    def _get_local_plugins(self):
680        """
681        get plugins local to guiframe and others
682        """
683        plugins = []
684        #import guiframe local plugins
685        #check if the style contain guiframe.dataloader
686        style1 = self.__gui_style & GUIFRAME.DATALOADER_ON
687        style2 = self.__gui_style & GUIFRAME.PLOTTING_ON
688        if style1 == GUIFRAME.DATALOADER_ON:
689            try:
690                from sans.guiframe.local_perspectives.data_loader import data_loader
691                self._data_plugin = data_loader.Plugin()
692                plugins.append(self._data_plugin)
693            except:
694                msg = "ViewerFrame._get_local_plugins:"
695                msg += "cannot import dataloader plugin.\n %s" % sys.exc_value
696                logging.error(msg)
697        if style2 == GUIFRAME.PLOTTING_ON:
698            try:
699                from sans.guiframe.local_perspectives.plotting import plotting
700                self._plotting_plugin = plotting.Plugin()
701                plugins.append(self._plotting_plugin)
702            except:
703                msg = "ViewerFrame._get_local_plugins:"
704                msg += "cannot import plotting plugin.\n %s" % sys.exc_value
705                logging.error(msg)
706     
707        return plugins
708   
709    def _find_plugins(self, dir="perspectives"):
710        """
711        Find available perspective plug-ins
712       
713        :param dir: directory in which to look for plug-ins
714       
715        :return: list of plug-ins
716       
717        """
718        import imp
719        plugins = []
720        # Go through files in panels directory
721        try:
722            list = os.listdir(dir)
723            ## the default panel is the panel is the last plugin added
724            for item in list:
725                toks = os.path.splitext(os.path.basename(item))
726                name = ''
727                if not toks[0] == '__init__':
728                    if toks[1] == '.py' or toks[1] == '':
729                        name = toks[0]
730                    #check the validity of the module name parsed
731                    #before trying to import it
732                    if name is None or name.strip() == '':
733                        continue
734                    path = [os.path.abspath(dir)]
735                    file = ''
736                    try:
737                        if toks[1] == '':
738                            mod_path = '.'.join([dir, name])
739                            module = __import__(mod_path, globals(),
740                                                locals(), [name])
741                        else:
742                            (file, path, info) = imp.find_module(name, path)
743                            module = imp.load_module( name, file, item, info)
744                        if hasattr(module, "PLUGIN_ID"):
745                            try: 
746                                plug = module.Plugin()
747                                if plug.set_default_perspective():
748                                    self._current_perspective = plug
749                                plugins.append(plug)
750                               
751                                msg = "Found plug-in: %s" % module.PLUGIN_ID
752                                logging.info(msg)
753                            except:
754                                msg = "Error accessing PluginPanel"
755                                msg += " in %s\n  %s" % (name, sys.exc_value)
756                                config.printEVT(msg)
757                    except:
758                        msg = "ViewerFrame._find_plugins: %s" % sys.exc_value
759                        #print msg
760                        logging.error(msg)
761                    finally:
762                        if not file == None:
763                            file.close()
764        except:
765            # Should raise and catch at a higher level and
766            # display error on status bar
767            pass 
768
769        return plugins
770   
771    def set_welcome_panel(self, panel_class):
772        """
773        Sets the default panel as the given welcome panel
774       
775        :param panel_class: class of the welcome panel to be instantiated
776       
777        """
778        self.defaultPanel = panel_class(self, -1, style=wx.RAISED_BORDER)
779       
780    def _get_panels_size(self, p):
781        """
782        find the proper size of the current panel
783        get the proper panel width and height
784        """
785        panel_height_min = self._window_height
786        panel_width_min = self._window_width
787        style = self.__gui_style & (GUIFRAME.MANAGER_ON)
788        if self._data_panel is not None  and (p == self._data_panel):
789            panel_width_min = DATAPANEL_WIDTH
790            panel_height_min = self._window_height * 0.8
791            return panel_width_min, panel_height_min
792        if hasattr(p, "CENTER_PANE") and p.CENTER_PANE:
793            style = self.__gui_style & (GUIFRAME.PLOTTING_ON|GUIFRAME.MANAGER_ON)
794            if style == (GUIFRAME.PLOTTING_ON|GUIFRAME.MANAGER_ON):
795                panel_width_min = self._window_width -\
796                            (DATAPANEL_WIDTH +config.PLOPANEL_WIDTH)
797            return panel_width_min, panel_height_min
798        return panel_width_min, panel_height_min
799   
800    def _load_panels(self):
801        """
802        Load all panels in the panels directory
803        """
804       
805        # Look for plug-in panels
806        panels = []   
807        for item in self.plugins:
808            if hasattr(item, "get_panels"):
809                ps = item.get_panels(self)
810                panels.extend(ps)
811       
812        # Show a default panel with some help information
813        # It also sets the size of the application windows
814        #TODO: Use this for slpash screen
815        if self.defaultPanel is None:
816            self.defaultPanel = DefaultPanel(self, -1, style=wx.RAISED_BORDER)
817        # add a blank default panel always present
818        self.panels["default"] = self.defaultPanel
819        self._mgr.AddPane(self.defaultPanel, wx.aui.AuiPaneInfo().
820                              Name("default").
821                              CenterPane().
822                              #CloseButton(False).
823                              #MinimizeButton(False).
824                              # This is where we set the size of
825                              # the application window
826                              BestSize(wx.Size(self._window_width, 
827                                               self._window_height)).
828                              Show())
829
830        #add data panel
831        self.panels["data_panel"] = self._data_panel
832        w, h = self._get_panels_size(self._data_panel)
833        self._mgr.AddPane(self._data_panel, wx.aui.AuiPaneInfo().
834                              Name(self._data_panel.window_name).
835                              Caption(self._data_panel.window_caption).
836                              Left().
837                              MinimizeButton().
838                              CloseButton(True).
839                              TopDockable(False).
840                              BottomDockable(False).
841                              LeftDockable(True).
842                              RightDockable(False).
843                              BestSize(wx.Size(w, h)).
844                              Hide())
845
846        style = self.__gui_style & GUIFRAME.MANAGER_ON
847        data_pane = self._mgr.GetPane(self.panels["data_panel"].window_name)
848        if style != GUIFRAME.MANAGER_ON:
849            self._mgr.GetPane(self.panels["data_panel"].window_name).Hide()
850        else:
851            self._mgr.GetPane(self.panels["data_panel"].window_name).Show()
852           
853        # Add the panels to the AUI manager
854        for panel_class in panels:
855            p = panel_class
856            id = wx.NewId()
857            #w, h = self._get_panels_size(p)
858            # Check whether we need to put this panel
859            # in the center pane
860            if hasattr(p, "CENTER_PANE") and p.CENTER_PANE:
861                w, h = self._get_panels_size(p)
862                if p.CENTER_PANE:
863                    self.panels[str(id)] = p
864                    self._mgr.AddPane(p, wx.aui.AuiPaneInfo().
865                                          Name(p.window_name).
866                                          CenterPane().
867                                          Center().
868                                          CloseButton(False).
869                                          Hide())
870            else:
871                self.panels[str(id)] = p
872                self._mgr.AddPane(p, wx.aui.AuiPaneInfo().
873                                  Name(p.window_name).Caption(p.window_caption).
874                                  Right().
875                                  Dock().
876                                  TopDockable().
877                                  BottomDockable().
878                                  LeftDockable().
879                                  RightDockable().
880                                  MinimizeButton().
881                                  Hide())       
882     
883    def update_data(self, prev_data, new_data):
884        """
885        """
886        prev_id, data_state = self._data_manager.update_data(prev_data=prev_data, 
887                                       new_data=new_data)
888       
889        self._data_panel.remove_by_id(prev_id)
890        self._data_panel.load_data_list(data_state)
891       
892    def update_theory(self, data_id, theory, state=None):
893        """
894        """ 
895        data_state = self._data_manager.update_theory(data_id=data_id, 
896                                         theory=theory,
897                                         state=state) 
898        self._data_panel.load_data_list(data_state)
899       
900    def onfreeze(self, theory_id):
901        """
902        """
903        data_state_list = self._data_manager.freeze(theory_id)
904        self._data_panel.load_data_list(list=data_state_list)
905        for data_state in data_state_list.values():
906            new_plot = data_state.get_data()
907           
908            wx.PostEvent(self, NewPlotEvent(plot=new_plot,
909                                             title=new_plot.title))
910       
911    def freeze(self, data_id, theory_id):
912        """
913        """
914        data_state_list = self._data_manager.freeze_theory(data_id=data_id, 
915                                                theory_id=theory_id)
916        self._data_panel.load_data_list(list=data_state_list)
917        for data_state in data_state_list.values():
918            new_plot = data_state.get_data()
919            wx.PostEvent(self, NewPlotEvent(plot=new_plot,
920                                             title=new_plot.title))
921       
922    def delete_data(self, data):
923        """
924        """
925        self._current_perspective.delete_data(data)
926       
927   
928    def get_context_menu(self, plotpanel=None):
929        """
930        Get the context menu items made available
931        by the different plug-ins.
932        This function is used by the plotting module
933        """
934        if plotpanel is None:
935            return
936        menu_list = []
937        for item in self.plugins:
938            menu_list.extend(item.get_context_menu(plotpanel=plotpanel))
939        return menu_list
940       
941    def popup_panel(self, p):
942        """
943        Add a panel object to the AUI manager
944       
945        :param p: panel object to add to the AUI manager
946       
947        :return: ID of the event associated with the new panel [int]
948       
949        """
950        ID = wx.NewId()
951        self.panels[str(ID)] = p
952        count = 0
953        for item in self.panels:
954            if self.panels[item].window_name.startswith(p.window_name): 
955                count += 1
956        windowname = p.window_name
957        windowcaption = 'Graph'#p.window_caption
958        if count > 0:
959            windowname += str(count+1)
960            #caption += (' '+str(count))
961        p.window_name = windowname
962
963        # Append nummber
964        captions = self._get_plotpanel_captions()
965        while (1):
966            self.graph_num += 1
967            caption = windowcaption + '%s'% str(self.graph_num)
968            if caption not in captions:
969                break
970
971        p.window_caption = caption
972           
973        style1 = self.__gui_style & GUIFRAME.FIXED_PANEL
974        style2 = self.__gui_style & GUIFRAME.FLOATING_PANEL
975        if style1 == GUIFRAME.FIXED_PANEL:
976            self._mgr.AddPane(p, wx.aui.AuiPaneInfo().
977                              Name(windowname).
978                              Caption(caption).
979                              Position(10).
980                              Floatable().
981                              Right().
982                              Dock().
983                              MinimizeButton().
984                              Resizable(True).
985                              # Use a large best size to make sure the AUI
986                              # manager takes all the available space
987                              BestSize(wx.Size(PLOPANEL_WIDTH, 
988                                               PLOPANEL_HEIGTH)))
989       
990            self._popup_fixed_panel(p)
991   
992        elif style2 == GUIFRAME.FLOATING_PANEL:
993            self._mgr.AddPane(p, wx.aui.AuiPaneInfo().
994                              Name(windowname).Caption(caption).
995                              MinimizeButton().
996                              Resizable(True).
997                              # Use a large best size to make sure the AUI
998                              #  manager takes all the available space
999                              BestSize(wx.Size(PLOPANEL_WIDTH, 
1000                                               PLOPANEL_HEIGTH)))
1001
1002            self._popup_floating_panel(p)
1003 
1004        # Register for showing/hiding the panel
1005        wx.EVT_MENU(self, ID, self.on_view)
1006        if p not in self.plot_panels.values() and p.group_id != None:
1007            self.plot_panels[ID] = p
1008            if len(self.plot_panels) == 1:
1009                self.panel_on_focus = p
1010                self.set_panel_on_focus(None)
1011            if self._data_panel is not None and \
1012                self._plotting_plugin is not None:
1013                ind = self._data_panel.cb_plotpanel.FindString('None')
1014                if ind != wx.NOT_FOUND:
1015                    self._data_panel.cb_plotpanel.Delete(ind)
1016                if caption not in self._data_panel.cb_plotpanel.GetItems():
1017                    self._data_panel.cb_plotpanel.Append(str(caption), p)
1018        return ID
1019   
1020    def _get_plotpanel_captions(self):
1021        """
1022        Get all the plotpanel cations
1023       
1024        : return: list of captions
1025        """
1026        captions = []
1027        for Id in self.plot_panels.keys():
1028            captions.append(self.plot_panels[Id].window_caption)
1029       
1030        return captions
1031         
1032    def _setup_menus(self):
1033        """
1034        Set up the application menus
1035        """
1036        # Menu
1037        self._menubar = wx.MenuBar()
1038        self._add_menu_file()
1039        self._add_menu_edit()
1040        self._add_menu_view()
1041        #self._add_menu_data()
1042        self._add_menu_application()
1043        self._add_menu_tool()
1044        self._add_current_plugin_menu()
1045        self._add_menu_window()
1046        self._add_help_menu()
1047        self.SetMenuBar(self._menubar)
1048       
1049    def _setup_tool_bar(self):
1050        """
1051        add toolbar to the frame
1052        """
1053        #set toolbar
1054        self._toolbar = GUIToolBar(self, -1)
1055        self.SetToolBar(self._toolbar)
1056        self._update_toolbar_helper()
1057        self._on_toggle_toolbar(event=None)
1058   
1059    def _update_toolbar_helper(self):
1060        """
1061        """
1062        application_name = 'No Selected Analysis'
1063        panel_name = 'No Panel on Focus'
1064        if self._toolbar is  None:
1065            return
1066        if self.cpanel_on_focus is not None:
1067            self.reset_bookmark_menu(self.cpanel_on_focus)
1068        self._toolbar.update_toolbar(self.cpanel_on_focus)
1069        if self._current_perspective is not None:
1070            application_name = self._current_perspective.sub_menu
1071        if self.cpanel_on_focus is not None:
1072            panel_name = self.cpanel_on_focus.window_caption
1073           
1074        self._toolbar.update_button(application_name=application_name, 
1075                                        panel_name=panel_name)
1076       
1077        self._toolbar.Realize()
1078       
1079    def _add_menu_tool(self):
1080        """
1081        Tools menu
1082        Go through plug-ins and find tools to populate the tools menu
1083        """
1084        style = self.__gui_style & GUIFRAME.CALCULATOR_ON
1085        if style == GUIFRAME.CALCULATOR_ON:
1086            self._tool_menu = None
1087            for item in self.plugins:
1088                if hasattr(item, "get_tools"):
1089                    for tool in item.get_tools():
1090                        # Only create a menu if we have at least one tool
1091                        if self._tool_menu is None:
1092                            self._tool_menu = wx.Menu()
1093                        id = wx.NewId()
1094                        self._tool_menu.Append(id, tool[0], tool[1])
1095                        wx.EVT_MENU(self, id, tool[2])
1096            if self._tool_menu is not None:
1097                self._menubar.Append(self._tool_menu, '&Tool')
1098               
1099    def _add_current_plugin_menu(self):
1100        """
1101        add current plugin menu
1102        Look for plug-in menus
1103        Add available plug-in sub-menus.
1104        """
1105        if (self._menubar is None) or (self._current_perspective is None):
1106            return
1107        #replace or add a new menu for the current plugin
1108       
1109        pos = self._menubar.FindMenu(str(self._applications_menu_name))
1110        if pos != -1:
1111            menu_list = self._current_perspective.populate_menu(self)
1112            if menu_list:
1113                for (menu, name) in menu_list:
1114                    hidden_menu = self._menubar.Replace(pos, menu, name) 
1115                    self._applications_menu_name = name
1116                #self._applications_menu_pos = pos
1117            else:
1118                hidden_menu = self._menubar.Remove(pos)
1119                self._applications_menu_name = None
1120            #get the position of the menu when it first added
1121            self._applications_menu_pos = pos
1122           
1123        else:
1124            menu_list = self._current_perspective.populate_menu(self)
1125            if menu_list:
1126                for (menu,name) in menu_list:
1127                    if self._applications_menu_pos == -1:
1128                        self._menubar.Append(menu, name)
1129                    else:
1130                        self._menubar.Insert(self._applications_menu_pos, menu, name)
1131                    self._applications_menu_name = name
1132                 
1133    def _add_help_menu(self):
1134        """
1135        add help menu
1136        """
1137        # Help menu
1138        self._help_menu = wx.Menu()
1139        style = self.__gui_style & GUIFRAME.WELCOME_PANEL_ON
1140        if style == GUIFRAME.WELCOME_PANEL_ON or custom_config != None:
1141            # add the welcome panel menu item
1142            if config.WELCOME_PANEL_ON and self.defaultPanel is not None:
1143                id = wx.NewId()
1144                self._help_menu.Append(id, '&Welcome', '')
1145                self._help_menu.AppendSeparator()
1146                wx.EVT_MENU(self, id, self.show_welcome_panel)
1147        # Look for help item in plug-ins
1148        for item in self.plugins:
1149            if hasattr(item, "help"):
1150                id = wx.NewId()
1151                self._help_menu.Append(id,'&%s Help' % item.sub_menu, '')
1152                wx.EVT_MENU(self, id, item.help)
1153        if config._do_tutorial:
1154            self._help_menu.AppendSeparator()
1155            id = wx.NewId()
1156            self._help_menu.Append(id,'&Tutorial', 'Software tutorial')
1157            wx.EVT_MENU(self, id, self._onTutorial)
1158           
1159        if config._do_aboutbox:
1160            self._help_menu.AppendSeparator()
1161            id = wx.NewId()
1162            self._help_menu.Append(id,'&About', 'Software information')
1163            wx.EVT_MENU(self, id, self._onAbout)
1164       
1165        # Checking for updates needs major refactoring to work with py2exe
1166        # We need to make sure it doesn't hang the application if the server
1167        # is not up. We also need to make sure there's a proper executable to
1168        # run if we spawn a new background process.
1169        #id = wx.NewId()
1170        #self._help_menu.Append(id,'&Check for update',
1171        #'Check for the latest version of %s' % config.__appname__)
1172        #wx.EVT_MENU(self, id, self._check_update)
1173        self._menubar.Append(self._help_menu, '&Help')
1174           
1175    def _add_menu_view(self):
1176        """
1177        add menu items under view menu
1178        """
1179        if not VIEW_MENU:
1180            return
1181        self._view_menu = wx.Menu()
1182        style = self.__gui_style & GUIFRAME.MANAGER_ON
1183        id = wx.NewId()
1184        self._data_panel_menu = self._view_menu.Append(id,
1185                                                '&Show Data Explorer', '')
1186        wx.EVT_MENU(self, id, self.show_data_panel)
1187        if style == GUIFRAME.MANAGER_ON:
1188            self._data_panel_menu.SetText('Hide Data Explorer')
1189        else:
1190            self._data_panel_menu.SetText('Show Data Explorer')
1191        self._view_menu.AppendSeparator()
1192        id = wx.NewId()
1193        style1 = self.__gui_style & GUIFRAME.TOOLBAR_ON
1194        if style1 == GUIFRAME.TOOLBAR_ON:
1195            self._toolbar_menu = self._view_menu.Append(id,'&Hide Toolbar', '')
1196        else:
1197            self._toolbar_menu = self._view_menu.Append(id,'&Show Toolbar', '')
1198        wx.EVT_MENU(self, id, self._on_toggle_toolbar)
1199       
1200        if custom_config != None:
1201            self._view_menu.AppendSeparator()
1202            id = wx.NewId()
1203            preference_menu = self._view_menu.Append(id,'Startup Setting', '')
1204            wx.EVT_MENU(self, id, self._on_preference_menu)
1205           
1206        self._menubar.Append(self._view_menu, '&View')   
1207         
1208    def _on_preference_menu(self, event):     
1209        """
1210        Build a panel to allow to edit Mask
1211        """
1212       
1213        from sans.guiframe.startup_configuration \
1214        import StartupConfiguration as ConfDialog
1215       
1216        self.panel = ConfDialog(parent=self, gui=self.__gui_style)
1217        self.panel.ShowModal()
1218        #wx.PostEvent(self.parent, event)
1219       
1220
1221    def _add_menu_window(self):
1222        """
1223        add a menu window to the menu bar
1224        Window menu
1225        Attach a menu item for each panel in our
1226        panel list that also appears in a plug-in.
1227       
1228        Only add the panel menu if there is only one perspective and
1229        it has more than two panels.
1230        Note: the first plug-in is always the plotting plug-in.
1231        The first application
1232        #plug-in is always the second one in the list.
1233        """
1234        self._window_menu = wx.Menu()
1235        if self._plotting_plugin is not None:
1236            for (menu, name) in self._plotting_plugin.populate_menu(self):
1237                self._window_menu.AppendSubMenu(menu, name)
1238        self._menubar.Append(self._window_menu, '&Graph')
1239
1240        style = self.__gui_style & GUIFRAME.PLOTTING_ON
1241        if style == GUIFRAME.PLOTTING_ON:
1242           
1243            self._window_menu.AppendSeparator()
1244            id = wx.NewId()
1245            hint = "Hide all the graph panels"
1246            self._window_menu.Append(id, '&Hide  All', hint)
1247            wx.EVT_MENU(self, id, self.hide_all_plotpanels)
1248            id = wx.NewId()
1249            hint = "Show all the graph panels"
1250            self._window_menu.Append(id, '&Show All', hint)
1251            wx.EVT_MENU(self, id, self.show_all_plotpanels)
1252           
1253            self._window_menu.AppendSeparator()
1254            id = wx.NewId()
1255            preferences_menu = wx.Menu()
1256            hint = "All plot panels will floating"
1257            preferences_menu.AppendRadioItem(id, '&Float All', hint)
1258            wx.EVT_MENU(self, id, self.set_plotpanel_floating)
1259            style = self.__gui_style & GUIFRAME.FLOATING_PANEL
1260            f_menu = preferences_menu.FindItemById(id)
1261            if style == GUIFRAME.FLOATING_PANEL: 
1262                f_checked = True
1263            else:
1264                f_checked = False
1265            f_menu.Check(f_checked)
1266
1267            id = wx.NewId()
1268            hint = "All plot panels will displayed within the frame"
1269            preferences_menu.AppendRadioItem(id, '&Dock All', hint)
1270            wx.EVT_MENU(self, id, self.set_plotpanel_fixed) 
1271            if not f_checked:
1272                d_menu = preferences_menu.FindItemById(id)
1273                d_menu.Check(True)
1274            preferences_menu.AppendSeparator()
1275            id = wx.NewId()
1276            hint = "Clean up the dock area for plots on new-plot"
1277            preferences_menu.AppendCheckItem(id, '&CleanUp Dock on NewPlot', hint)
1278            wx.EVT_MENU(self, id, self.on_cleanup_dock)
1279            flag = self.cleanup_plots
1280            if self.cleanup_plots:
1281                c_menu = preferences_menu.FindItemById(id)
1282                c_menu.Check(True) 
1283            self._window_menu.AppendSubMenu(preferences_menu,'&Preferences')
1284        if self._window_menu.GetMenuItemCount() == 0:
1285            pos = self._menubar.FindMenu('Graph')
1286            self._menubar.Remove(pos)
1287        #wx.EVT_MENU(self, id, self.show_preferences_panel)   
1288        """
1289        if len(self.plugins) == 2:
1290            plug = self.plugins[1]
1291            pers = plug.get_perspective()
1292       
1293            if len(pers) > 1:
1294                self._window_menu = wx.Menu()
1295                for item in self.panels:
1296                    if item == 'default':
1297                        continue
1298                    panel = self.panels[item]
1299                    if panel.window_name in pers:
1300                        self._window_menu.Append(int(item),
1301                                                  panel.window_caption,
1302                                        "Show %s window" % panel.window_caption)
1303                        wx.EVT_MENU(self, int(item), self.on_view)
1304                self._menubar.Append(self._window_menu, '&Window')
1305                """
1306
1307               
1308    def _add_menu_application(self):
1309        """
1310       
1311        # Attach a menu item for each defined perspective or application.
1312        # Only add the perspective menu if there are more than one perspectives
1313        add menu application
1314        """
1315        #style = self.__gui_style & GUIFRAME.MULTIPLE_APPLICATIONS
1316        #if style == GUIFRAME.MULTIPLE_APPLICATIONS:
1317        if self._num_perspectives  > 1:
1318            plug_data_count = False
1319            plug_no_data_count = False
1320            self._applications_menu = wx.Menu()
1321            pos = 0
1322            separator = self._applications_menu.AppendSeparator()
1323            for plug in self.plugins:
1324                if len(plug.get_perspective()) > 0:
1325                    id = wx.NewId()
1326                    if plug.use_data():
1327                       
1328                        self._applications_menu.InsertCheckItem(pos, id, plug.sub_menu,
1329                                      "Switch to analysis: %s" % plug.sub_menu)
1330                        plug_data_count = True
1331                        pos += 1
1332                    else:
1333                        plug_no_data_count = True
1334                        self._applications_menu.AppendCheckItem(id, plug.sub_menu,
1335                                      "Switch to analysis: %s" % plug.sub_menu)
1336                    wx.EVT_MENU(self, id, plug.on_perspective)
1337            #self._applications_menu.
1338            if (not plug_data_count or not plug_no_data_count):
1339                self._applications_menu.RemoveItem(separator)
1340            self._menubar.Append(self._applications_menu, '&Analysis')
1341            self._check_applications_menu()
1342           
1343    def _populate_file_menu(self):
1344        """
1345        Insert menu item under file menu
1346        """
1347        for plugin in self.plugins:
1348            if len(plugin.populate_file_menu()) > 0:
1349                for item in plugin.populate_file_menu():
1350                    m_name, m_hint, m_handler = item
1351                    id = wx.NewId()
1352                    self._file_menu.Append(id, m_name, m_hint)
1353                    wx.EVT_MENU(self, id, m_handler)
1354                self._file_menu.AppendSeparator()
1355               
1356    def _add_menu_file(self):
1357        """
1358        add menu file
1359        """
1360       
1361         # File menu
1362        self._file_menu = wx.Menu()
1363        #append item from plugin under menu file if necessary
1364        self._populate_file_menu()
1365        style = self.__gui_style & GUIFRAME.DATALOADER_ON
1366        style1 = self.__gui_style & GUIFRAME.MULTIPLE_APPLICATIONS
1367        if OPEN_SAVE_MENU:
1368            id = wx.NewId()
1369            hint_load_file = "read all analysis states saved previously"
1370            self._save_appl_menu = self._file_menu.Append(id, 
1371                                    '&Open Project', hint_load_file)
1372            wx.EVT_MENU(self, id, self._on_open_state_project)
1373           
1374        if style1 == GUIFRAME.MULTIPLE_APPLICATIONS:
1375            # some menu of plugin to be seen under file menu
1376            hint_load_file = "Read a status files and load"
1377            hint_load_file += " them into the analysis"
1378            id = wx.NewId()
1379            self._save_appl_menu = self._file_menu.Append(id, 
1380                                    '&Open Analysis', hint_load_file)
1381            wx.EVT_MENU(self, id, self._on_open_state_application)
1382        if OPEN_SAVE_MENU:       
1383            self._file_menu.AppendSeparator()
1384            id = wx.NewId()
1385            self._file_menu.Append(id, '&Save Project',
1386                                 'Save the state of the whole analysis')
1387            wx.EVT_MENU(self, id, self._on_save_project)
1388        if style1 == GUIFRAME.MULTIPLE_APPLICATIONS:
1389            #self._file_menu.AppendSeparator()
1390            id = wx.NewId()
1391            self._save_appl_menu = self._file_menu.Append(id, 
1392                                                      '&Save Analysis',
1393                        'Save state of the current active analysis panel')
1394            wx.EVT_MENU(self, id, self._on_save_application)
1395            self._file_menu.AppendSeparator()
1396        self._file_menu.AppendSeparator()
1397        id = wx.NewId()
1398        hint = "Display content of the file into a grid"
1399        self._file_menu.Append(id, '&Open Batch Result', hint) 
1400        wx.EVT_MENU(self, id, self.on_read_batch_tofile)
1401        self._file_menu.AppendSeparator()
1402        id = wx.NewId()
1403        self._file_menu.Append(id, '&Quit', 'Exit') 
1404        wx.EVT_MENU(self, id, self.Close)
1405        # Add sub menus
1406        self._menubar.Append(self._file_menu, '&File')
1407       
1408    def _add_menu_edit(self):
1409        """
1410        add menu edit
1411        """
1412        if not EDIT_MENU:
1413            return
1414        # Edit Menu
1415        self._edit_menu = wx.Menu()
1416        self._edit_menu.Append(GUIFRAME_ID.UNDO_ID, '&Undo', 
1417                               'Undo the previous action')
1418        wx.EVT_MENU(self, GUIFRAME_ID.UNDO_ID, self.on_undo_panel)
1419        self._edit_menu.Append(GUIFRAME_ID.REDO_ID, '&Redo', 
1420                               'Redo the previous action')
1421        wx.EVT_MENU(self, GUIFRAME_ID.REDO_ID, self.on_redo_panel)
1422        self._edit_menu.AppendSeparator()
1423        self._edit_menu.Append(GUIFRAME_ID.COPY_ID, '&Copy Params', 
1424                               'Copy parameter values')
1425        wx.EVT_MENU(self, GUIFRAME_ID.COPY_ID, self.on_copy_panel)
1426        self._edit_menu.Append(GUIFRAME_ID.PASTE_ID, '&Paste Params', 
1427                               'Paste parameter values')
1428        wx.EVT_MENU(self, GUIFRAME_ID.PASTE_ID, self.on_paste_panel)
1429        self._edit_menu.AppendSeparator()
1430       
1431        self._edit_menu.Append(GUIFRAME_ID.PREVIEW_ID, '&Report Results',
1432                               'Preview current panel')
1433        wx.EVT_MENU(self, GUIFRAME_ID.PREVIEW_ID, self.on_preview_panel)
1434        #self._edit_menu.Append(GUIFRAME_ID.PRINT_ID, '&Print',
1435        #                       'Print current panel')
1436        #wx.EVT_MENU(self, GUIFRAME_ID.PRINT_ID, self.on_print_panel)
1437        self._edit_menu.Append(GUIFRAME_ID.RESET_ID, '&Reset Page', 
1438                               'Reset current panel')
1439        wx.EVT_MENU(self, GUIFRAME_ID.RESET_ID, self.on_reset_panel)
1440   
1441        self._menubar.Append(self._edit_menu,  '&Edit')
1442        self.enable_edit_menu()
1443       
1444    def get_style(self):
1445        """
1446        """
1447        return  self.__gui_style
1448   
1449    def _add_menu_data(self):
1450        """
1451        Add menu item item data to menu bar
1452        """
1453        if self._data_plugin is not None:
1454            menu_list = self._data_plugin.populate_menu(self)
1455            if menu_list:
1456                for (menu, name) in menu_list:
1457                    self._menubar.Append(menu, name)
1458       
1459                       
1460    def _on_toggle_toolbar(self, event=None):
1461        """
1462        hide or show toolbar
1463        """
1464        if self._toolbar is None:
1465            return
1466        if self._toolbar.IsShown():
1467            if self._toolbar_menu is not None:
1468                self._toolbar_menu.SetItemLabel('Show Toolbar')
1469            self._toolbar.Hide()
1470        else:
1471            if self._toolbar_menu is not None:
1472                self._toolbar_menu.SetItemLabel('Hide Toolbar')
1473            self._toolbar.Show()
1474        self._toolbar.Realize()
1475       
1476    def _on_status_event(self, evt):
1477        """
1478        Display status message
1479        """
1480        # This CallAfter fixes many crashes on MAC.
1481        wx.CallAfter(self.sb.set_status, evt)
1482       
1483    def on_view(self, evt):
1484        """
1485        A panel was selected to be shown. If it's not already
1486        shown, display it.
1487       
1488        :param evt: menu event
1489       
1490        """
1491        panel_id = str(evt.GetId())
1492        self.on_set_plot_focus(self.panels[panel_id])
1493        self.show_panel(evt.GetId(), 'on')     
1494        wx.CallLater(5, self.set_schedule(True))
1495        self.set_plot_unfocus()
1496       
1497    def on_close_welcome_panel(self):
1498        """
1499        Close the welcome panel
1500        """
1501        if self.defaultPanel is None:
1502            return 
1503        default_panel = self._mgr.GetPane(self.panels["default"].window_name)
1504        if default_panel.IsShown():
1505            default_panel.Hide()
1506            # Recover current perspective
1507            perspective = self._current_perspective
1508            perspective.on_perspective(event=None)
1509            self._mgr.Update()
1510            # Show toolbar
1511            #style = self.__gui_style & GUIFRAME.TOOLBAR_ON
1512            #if (style == GUIFRAME.TOOLBAR_ON) & (not self._toolbar.IsShown()):
1513            #    self._on_toggle_toolbar()
1514           
1515    def show_welcome_panel(self, event):
1516        """   
1517        Display the welcome panel
1518        """
1519        if self.defaultPanel is None:
1520            return 
1521        for id, panel in self.panels.iteritems():
1522            if id  ==  'default':
1523                # Show default panel
1524                if not self._mgr.GetPane(self.panels["default"].window_name).IsShown():
1525                    self._mgr.GetPane(self.panels["default"].window_name).Show(True)
1526            elif id == "data_panel":
1527                flag = self._mgr.GetPane(self.panels["data_panel"].window_name).IsShown()
1528                self._mgr.GetPane(self.panels["data_panel"].window_name).Show(flag)
1529            elif panel not in self.plot_panels.values() :
1530                self._mgr.GetPane(self.panels[id].window_name).IsShown()
1531                self._mgr.GetPane(self.panels[id].window_name).Hide()
1532        #style = self.__gui_style & GUIFRAME.TOOLBAR_ON
1533        #if (style == GUIFRAME.TOOLBAR_ON) & (self._toolbar.IsShown()):
1534        #    #    self._toolbar.Show(True)
1535        #    self._on_toggle_toolbar()
1536
1537        self._mgr.Update()
1538       
1539    def show_panel(self, uid, show=None):
1540        """
1541        Shows the panel with the given id
1542       
1543        :param uid: unique ID number of the panel to show
1544       
1545        """
1546        ID = str(uid)
1547        config.printEVT("show_panel: %s" % ID)
1548        if ID in self.panels.keys():
1549            if not self._mgr.GetPane(self.panels[ID].window_name).IsShown(): 
1550                if show == 'on':
1551                    self._mgr.GetPane(self.panels[ID].window_name).Show()   
1552                elif self.panels[ID].window_caption.split(" ")[0] == \
1553                                                            "Residuals":
1554                    self._mgr.GetPane(self.panels[ID].window_name).Hide()
1555                else:
1556                    self._mgr.GetPane(self.panels[ID].window_name).Show()
1557                # Hide default panel
1558                self._mgr.GetPane(self.panels["default"].window_name).Hide()
1559        self._mgr.Update()     
1560        self._redraw_idle()
1561
1562    def show_all_plotpanels(self, event):
1563        """
1564        Show all plotpanels shown
1565       
1566        :param event: menu event
1567        """
1568        #event.Skip()
1569        any_hidden = False
1570        for id in self.plot_panels.keys():
1571            if self._mgr.GetPane(self.plot_panels[id].window_name).IsShown():
1572                continue
1573            else:
1574                any_hidden = True
1575                self.show_panel(id)
1576        if not any_hidden:
1577            msg = "No graph panels to show."
1578        else:
1579            # Make sure the Checkmenuitem checked: Need this for-loop \
1580            # because the check menu is not responding on floating panel
1581            try:
1582                for item in self._plotting_plugin.menu.GetMenuItems():
1583                    item.Check(True)
1584            except:
1585                # MAC is not using checkmenuitem
1586                pass
1587            msg = "All graph panels are shown."
1588        wx.PostEvent(self, StatusEvent(status=msg))
1589           
1590    def hide_all_plotpanels(self, event):
1591        """
1592        Hide all plotpanels shown
1593       
1594        :param event: menu event
1595        """
1596        #event.Skip()
1597        any_shown = False
1598        for ID in self.plot_panels.keys():
1599            if self._mgr.GetPane(self.plot_panels[ID].window_name).IsShown():
1600                any_shown = True
1601                self.hide_panel(ID)
1602            else:
1603                continue
1604        if not any_shown:
1605            msg = "No graph panels to hide."
1606        else:
1607            # Make sure the Checkmenuitem unchecked: Need this for-loop
1608            # because the check menu is not responding on floating panel
1609            try:
1610                for item in self._plotting_plugin.menu.GetMenuItems():
1611                    item.Check(False)
1612            except:
1613                # MAC is not using checkmenuitem
1614                pass
1615            msg = "All graph panels are hidden."
1616        wx.PostEvent(self, StatusEvent(status=msg))
1617                   
1618    def hide_panel(self, uid):
1619        """
1620        hide panel except default panel
1621        """
1622        ID = str(uid)
1623        caption = self.panels[ID].window_caption
1624        config.printEVT("hide_panel: %s" % ID)
1625        if ID in self.panels.keys():
1626            if self._mgr.GetPane(self.panels[ID].window_name).IsShown():
1627                self._mgr.GetPane(self.panels[ID].window_name).Hide()
1628                if self._data_panel is not None and \
1629                            ID in self.plot_panels.keys():
1630                    self._data_panel.cb_plotpanel.Append(str(caption), p)
1631                # Do not Hide default panel here...
1632                #self._mgr.GetPane(self.panels["default"].window_name).Hide()
1633            self._mgr.Update()
1634               
1635    def delete_panel(self, uid):
1636        """
1637        delete panel given uid
1638        """
1639        ID = str(uid)
1640        config.printEVT("delete_panel: %s" % ID)
1641        caption = self.panels[ID].window_caption
1642        if ID in self.panels.keys():
1643            self.panel_on_focus = None
1644            panel = self.panels[ID]
1645            self._plotting_plugin.delete_panel(panel.group_id)
1646            self._mgr.DetachPane(panel)
1647            panel.Hide()
1648            panel.clear()
1649            panel.Close()
1650            #CallAfter: make sure panel is clear before updating mgr
1651            wx.CallAfter(self._mgr.Update)
1652            #delete uid number not str(uid)
1653            if uid in self.plot_panels.keys():
1654                del self.plot_panels[uid]
1655            return 
1656     
1657    def clear_panel(self):
1658        """
1659        """
1660        for item in self.panels:
1661            try:
1662                self.panels[item].clear_panel()
1663            except:
1664                pass
1665           
1666    def create_gui_data(self, data, path=None):
1667        """
1668        """
1669        return self._data_manager.create_gui_data(data, path)
1670   
1671    def get_data(self, path):
1672        """
1673        """
1674        message = ""
1675        log_msg = ''
1676        output = []
1677        error_message = ""
1678        basename  = os.path.basename(path)
1679        root, extension = os.path.splitext(basename)
1680        if extension.lower() not in EXTENSIONS:
1681            log_msg = "File Loader cannot "
1682            log_msg += "load: %s\n" % str(basename)
1683            log_msg += "Try Data opening...."
1684            logging.info(log_msg)
1685            self.load_complete(output=output, error_message=error_message,
1686                   message=log_msg, path=path)   
1687            return
1688       
1689        #reading a state file
1690        for plug in self.plugins:
1691            reader, ext = plug.get_extensions()
1692            if reader is not None:
1693                #read the state of the single plugin
1694                if extension == ext:
1695                    reader.read(path)
1696                    return
1697                elif extension == APPLICATION_STATE_EXTENSION:
1698                    reader.read(path)
1699       
1700        style = self.__gui_style & GUIFRAME.MANAGER_ON
1701        if style == GUIFRAME.MANAGER_ON:
1702            if self._data_panel is not None:
1703                #data_state = self._data_manager.get_selected_data()
1704                #self._data_panel.load_data_list(data_state)
1705                self._mgr.GetPane(self._data_panel.window_name).Show(True)
1706     
1707    def load_from_cmd(self,  path):   
1708        """
1709        load data from cmd or application
1710        """ 
1711        if path is None:
1712            return
1713        else:
1714            path = os.path.abspath(path)
1715            if not os.path.isfile(path) and not os.path.isdir(path):
1716               return
1717           
1718            if os.path.isdir(path):
1719                self.load_folder(path)
1720                return
1721
1722        basename  = os.path.basename(path)
1723        root, extension = os.path.splitext(basename)
1724        if extension.lower() not in EXTENSIONS:
1725            self.load_data(path)
1726        else:
1727            self.load_state(path)
1728
1729        self._default_save_location = os.path.dirname(path)
1730
1731    def load_state(self, path):   
1732        """
1733        load data from command line or application
1734        """
1735        if path and (path is not None) and os.path.isfile(path):
1736            basename  = os.path.basename(path)
1737            if APPLICATION_STATE_EXTENSION is not None \
1738                and basename.endswith(APPLICATION_STATE_EXTENSION):
1739                #Hide current plot_panels i
1740                for ID in self.plot_panels.keys():
1741                    panel = self._mgr.GetPane(self.plot_panels[ID].window_name)
1742                    if panel.IsShown():
1743                        panel.Hide()
1744            self.get_data(path)
1745        if self.defaultPanel is not None and \
1746            self._mgr.GetPane(self.panels["default"].window_name).IsShown():
1747            self.on_close_welcome_panel()
1748           
1749    def load_data(self, path):
1750        """
1751        load data from command line
1752        """
1753        if not os.path.isfile(path):
1754            return
1755        basename  = os.path.basename(path)
1756        root, extension = os.path.splitext(basename)
1757        if extension.lower() in EXTENSIONS:
1758            log_msg = "Data Loader cannot "
1759            log_msg += "load: %s\n" % str(path)
1760            log_msg += "Try File opening ...."
1761            print log_msg
1762            return
1763        message = ""
1764        log_msg = ''
1765        output = {}
1766        error_message = ""
1767        try:
1768            print "Loading Data...:\n" + str(path) + "\n"
1769            temp =  self.loader.load(path)
1770            if temp.__class__.__name__ == "list":
1771                for item in temp:
1772                    data = self.create_gui_data(item, path)
1773                    output[data.id] = data
1774            else:
1775                data = self.create_gui_data(temp, path)
1776                output[data.id] = data
1777           
1778            self.add_data(data_list=output)
1779        except:
1780            error_message = "Error while loading"
1781            error_message += " Data from cmd:\n %s\n" % str(path)
1782            error_message += str(sys.exc_value) + "\n"
1783            print error_message
1784 
1785    def load_folder(self, path):
1786        """
1787        Load entire folder
1788        """   
1789        if not os.path.isdir(path):
1790            return
1791        if self._data_plugin is None:
1792            return
1793        try:
1794            if path is not None:
1795                self._default_save_location = os.path.dirname(path)
1796                file_list = self._data_plugin.get_file_path(path)
1797                self._data_plugin.get_data(file_list)
1798            else:
1799                return 
1800        except:
1801            error_message = "Error while loading"
1802            error_message += " Data folder from cmd:\n %s\n" % str(path)
1803            error_message += str(sys.exc_value) + "\n"
1804            print error_message
1805           
1806    def _on_open_state_application(self, event):
1807        """
1808        """
1809        path = None
1810        if self._default_save_location == None:
1811            self._default_save_location = os.getcwd()
1812       
1813        plug_wlist = self._on_open_state_app_helper()
1814        dlg = wx.FileDialog(self, 
1815                            "Choose a file", 
1816                            self._default_save_location, "",
1817                            plug_wlist)
1818        if dlg.ShowModal() == wx.ID_OK:
1819            path = dlg.GetPath()
1820            if path is not None:
1821                self._default_save_location = os.path.dirname(path)
1822        dlg.Destroy()
1823        self.load_state(path=path) 
1824   
1825    def _on_open_state_app_helper(self):
1826        """
1827        Helps '_on_open_state_application()' to find the extension of
1828        the current perspective/application
1829        """
1830        # No current perspective or no extension attr
1831        if self._current_perspective is None:
1832            return PLUGINS_WLIST
1833        try:
1834            # Find the extension of the perspective and get that as 1st item in list
1835            ind = None
1836            app_ext = self._current_perspective._extensions
1837            plug_wlist = config.PLUGINS_WLIST
1838            for ext in set(plug_wlist):
1839                if ext.count(app_ext) > 0:
1840                    ind = ext
1841                    break
1842            # Found the extension
1843            if ind != None:
1844                plug_wlist.remove(ind)
1845                plug_wlist.insert(0, ind)
1846                try:
1847                    plug_wlist ='|'.join(plug_wlist)
1848                except:
1849                    plug_wlist = ''
1850
1851        except:
1852            plug_wlist = PLUGINS_WLIST
1853           
1854        return plug_wlist
1855           
1856    def _on_open_state_project(self, event):
1857        """
1858        """
1859        path = None
1860        if self._default_save_location == None:
1861            self._default_save_location = os.getcwd()
1862       
1863        dlg = wx.FileDialog(self, 
1864                            "Choose a file", 
1865                            self._default_save_location, "",
1866                             APPLICATION_WLIST)
1867        if dlg.ShowModal() == wx.ID_OK:
1868            path = dlg.GetPath()
1869            if path is not None:
1870                self._default_save_location = os.path.dirname(path)
1871        dlg.Destroy()
1872       
1873        #try:   
1874        #    os.popen(path)
1875        #    #self.Close()
1876        #except:
1877        self.load_state(path=path)
1878       
1879    def _on_save_application(self, event):
1880        """
1881        save the state of the current active application
1882        """
1883        if self.cpanel_on_focus is not None:
1884            try:
1885                self.cpanel_on_focus.on_save(event)
1886            except:
1887                msg = "Error occurred while saving: "
1888                msg += "To save, the application panel should have a data set.."
1889                wx.PostEvent(self, StatusEvent(status=msg)) 
1890           
1891    def _on_save_project(self, event):
1892        """
1893        save the state of the SansView as *.svs
1894        """
1895        if self._current_perspective is  None:
1896            return
1897        reader, ext = self._current_perspective.get_extensions()
1898        path = None
1899        extension = '*' + APPLICATION_STATE_EXTENSION
1900        dlg = wx.FileDialog(self, "Save Project file",
1901                            self._default_save_location, "sansview_proj",
1902                             extension, 
1903                             wx.SAVE)
1904        if dlg.ShowModal() == wx.ID_OK:
1905            path = dlg.GetPath()
1906            self._default_save_location = os.path.dirname(path)
1907        else:
1908            return None
1909        dlg.Destroy()
1910        try:
1911            if path is None:
1912                return
1913            # default cansas xml doc
1914            doc = None
1915            for panel in self.panels.values():
1916                temp = panel.save_project(doc)
1917                if temp is not None:
1918                    doc = temp
1919             
1920            # Write the XML document
1921            extens = APPLICATION_STATE_EXTENSION
1922            fName = os.path.splitext(path)[0] + extens
1923            if doc != None:
1924                fd = open(fName, 'w')
1925                fd.write(doc.toprettyxml())
1926                fd.close()
1927            else:
1928                msg = "%s cannot read %s\n" % (str(APPLICATION_NAME), str(path))
1929                logging.error(msg)
1930        except:
1931           msg = "Error occurred while saving: "
1932           msg += "To save, at leat one application panel "
1933           msg += "should have a data set.."
1934           wx.PostEvent(self, StatusEvent(status=msg))   
1935                   
1936    def on_save_helper(self, doc, reader, panel, path):
1937        """
1938        Save state into a file
1939        """
1940        try:
1941            if reader is not None:
1942                # case of a panel with multi-pages
1943                if hasattr(panel, "opened_pages"):
1944                    for uid, page in panel.opened_pages.iteritems():
1945                        data = page.get_data()
1946                        # state must be cloned
1947                        state = page.get_state().clone()
1948                        if data is not None:
1949                            new_doc = reader.write_toXML(data, state)
1950                            if doc != None and hasattr(doc, "firstChild"):
1951                                child = new_doc.firstChild.firstChild
1952                                doc.firstChild.appendChild(child) 
1953                            else:
1954                                doc = new_doc
1955                # case of only a panel
1956                else:
1957                    data = panel.get_data()
1958                    state = panel.get_state()
1959                    if data is not None:
1960                        new_doc = reader.write_toXML(data, state)
1961                        if doc != None and hasattr(doc, "firstChild"):
1962                            child = new_doc.firstChild.firstChild
1963                            doc.firstChild.appendChild(child) 
1964                        else:
1965                            doc = new_doc
1966        except: 
1967            raise
1968            #pass
1969
1970        return doc
1971
1972    def quit_guiframe(self):
1973        """
1974        Pop up message to make sure the user wants to quit the application
1975        """
1976        message = "\nDo you really want to exit this application?        \n\n"
1977        dial = wx.MessageDialog(self, message, 'Confirm Exit',
1978                           wx.YES_NO|wx.YES_DEFAULT|wx.ICON_QUESTION)
1979        if dial.ShowModal() == wx.ID_YES:
1980            return True
1981        else:
1982            return False   
1983       
1984    def Close(self, event=None):
1985        """
1986        Quit the application
1987        """
1988        flag = self.quit_guiframe()
1989        if flag:
1990            wx.Exit()
1991            sys.exit()
1992
1993    def _check_update(self, event=None): 
1994        """
1995        Check with the deployment server whether a new version
1996        of the application is available.
1997        A thread is started for the connecting with the server. The thread calls
1998        a call-back method when the current version number has been obtained.
1999        """
2000        if hasattr(config, "__update_URL__"):
2001            import version
2002            checker = version.VersionThread(config.__update_URL__,
2003                                            self._process_version,
2004                                            baggage=event==None)
2005            checker.start() 
2006   
2007    def _process_version(self, version, standalone=True):
2008        """
2009        Call-back method for the process of checking for updates.
2010        This methods is called by a VersionThread object once the current
2011        version number has been obtained. If the check is being done in the
2012        background, the user will not be notified unless there's an update.
2013       
2014        :param version: version string
2015        :param standalone: True of the update is being checked in
2016           the background, False otherwise.
2017           
2018        """
2019        try:
2020            if cmp(version, config.__version__) > 0:
2021                msg = "Version %s is available! See the Help "
2022                msg += "menu to download it." % version
2023                self.SetStatusText(msg)
2024                if not standalone:
2025                    import webbrowser
2026                    webbrowser.open(config.__download_page__)
2027            else:
2028                if not standalone:
2029                    msg = "You have the latest version"
2030                    msg += " of %s" % config.__appname__
2031                    self.SetStatusText(msg)
2032        except:
2033            msg = "guiframe: could not get latest application"
2034            msg += " version number\n  %s" % sys.exc_value
2035            logging.error(msg)
2036            if not standalone:
2037                msg = "Could not connect to the application server."
2038                msg += " Please try again later."
2039                self.SetStatusText(msg)
2040                   
2041    def _onAbout(self, evt):
2042        """
2043        Pop up the about dialog
2044       
2045        :param evt: menu event
2046       
2047        """
2048        if config._do_aboutbox:
2049            import aboutbox 
2050            dialog = aboutbox.DialogAbout(None, -1, "")
2051            dialog.ShowModal()   
2052                     
2053    def _onTutorial(self, evt):
2054        """
2055        Pop up the tutorial dialog
2056       
2057        :param evt: menu event
2058       
2059        """
2060        if config._do_tutorial:   
2061            path = config.TUTORIAL_PATH
2062            if IS_WIN:
2063                try:
2064                    from sans.guiframe.pdfview import PDFFrame
2065                   
2066                    dialog = PDFFrame(None, -1, "Tutorial", path)
2067                    #self.SetTopWindow(dialog)
2068                    dialog.Show(True) 
2069                except:
2070                    raise
2071                    msg = "This feature requires 'Adobe pdf Reader'\n"
2072                    msg += "Please install it first (Free)..."
2073                    wx.MessageBox(msg, 'Error')
2074            else:
2075                try:
2076                    command = "open "
2077                    command += path
2078                    os.system(command)
2079                except:
2080                    msg = "This feature requires 'Preview' Application\n"
2081                    msg += "Please install it first..."
2082                    wx.MessageBox(msg, 'Error')
2083
2084                     
2085    def set_manager(self, manager):
2086        """
2087        Sets the application manager for this frame
2088       
2089        :param manager: frame manager
2090        """
2091        self.app_manager = manager
2092       
2093    def post_init(self):
2094        """
2095        This initialization method is called after the GUI
2096        has been created and all plug-ins loaded. It calls
2097        the post_init() method of each plug-in (if it exists)
2098        so that final initialization can be done.
2099        """
2100        for item in self.plugins:
2101            if hasattr(item, "post_init"):
2102                item.post_init()
2103       
2104    def set_default_perspective(self):
2105        """
2106        Choose among the plugin the first plug-in that has
2107        "set_default_perspective" method and its return value is True will be
2108        as a default perspective when the welcome page is closed
2109        """
2110        for item in self.plugins:
2111            if hasattr(item, "set_default_perspective"):
2112                if item.set_default_perspective():
2113                    item.on_perspective(event=None)
2114                    return 
2115       
2116    def set_perspective(self, panels):
2117        """
2118        Sets the perspective of the GUI.
2119        Opens all the panels in the list, and closes
2120        all the others.
2121       
2122        :param panels: list of panels
2123        """
2124        #style = self.__gui_style & GUIFRAME.TOOLBAR_ON
2125        #if (style == GUIFRAME.TOOLBAR_ON) & (not self._toolbar.IsShown()):
2126        #    self._on_toggle_toolbar()
2127        for item in self.panels:
2128            # Check whether this is a sticky panel
2129            if hasattr(self.panels[item], "ALWAYS_ON"):
2130                if self.panels[item].ALWAYS_ON:
2131                    continue 
2132           
2133            if self.panels[item].window_name in panels:
2134                if not self._mgr.GetPane(self.panels[item].window_name).IsShown():
2135                    self._mgr.GetPane(self.panels[item].window_name).Show()
2136            else:
2137                # always show the data panel if enable
2138                style = self.__gui_style & GUIFRAME.MANAGER_ON
2139                if (style == GUIFRAME.MANAGER_ON) and self.panels[item] == self._data_panel:
2140                    if 'data_panel' in self.panels.keys():
2141                        flag = self._mgr.GetPane(self.panels['data_panel'].window_name).IsShown()
2142                        self._mgr.GetPane(self.panels['data_panel'].window_name).Show(flag)
2143                else:
2144                    if self._mgr.GetPane(self.panels[item].window_name).IsShown():
2145                        self._mgr.GetPane(self.panels[item].window_name).Hide()
2146               
2147        self._mgr.Update()
2148       
2149    def show_data_panel(self, event=None, action=True):
2150        """
2151        show the data panel
2152        """
2153        if self._data_panel_menu == None:
2154            return
2155        label = self._data_panel_menu.GetText()
2156        if label == 'Show Data Explorer':
2157            pane = self._mgr.GetPane(self.panels["data_panel"].window_name)
2158            #if not pane.IsShown():
2159            if action: 
2160                pane.Show(True)
2161                self._mgr.Update()
2162            self.__gui_style = self.__gui_style | GUIFRAME.MANAGER_ON
2163           
2164            self._data_panel_menu.SetText('Hide Data Explorer')
2165        else:
2166            pane = self._mgr.GetPane(self.panels["data_panel"].window_name)
2167            #if not pane.IsShown():
2168            if action:
2169                pane.Show(False)
2170                self._mgr.Update()
2171            self.__gui_style = self.__gui_style & (~GUIFRAME.MANAGER_ON)
2172            self._data_panel_menu.SetText('Show Data Explorer')
2173   
2174    def add_data_helper(self, data_list):
2175        """
2176        """
2177        if self._data_manager is not None:
2178            self._data_manager.add_data(data_list)
2179       
2180    def add_data(self, data_list):
2181        """
2182        receive a dictionary of data from loader
2183        store them its data manager if possible
2184        send to data the current active perspective if the data panel
2185        is not active.
2186        :param data_list: dictionary of data's ID and value Data
2187        """
2188        #Store data into manager
2189        self.add_data_helper(data_list)
2190        # set data in the data panel
2191        if self._data_panel is not None:
2192            data_state = self._data_manager.get_data_state(data_list.keys())
2193            self._data_panel.load_data_list(data_state)
2194        #if the data panel is shown wait for the user to press a button
2195        #to send data to the current perspective. if the panel is not
2196        #show  automatically send the data to the current perspective
2197        style = self.__gui_style & GUIFRAME.MANAGER_ON
2198        if style == GUIFRAME.MANAGER_ON:
2199            #wait for button press from the data panel to set_data
2200            if self._data_panel is not None:
2201                self._mgr.GetPane(self._data_panel.window_name).Show(True)
2202                self._mgr.Update() 
2203        else:
2204            #automatically send that to the current perspective
2205            self.set_data(data_id=data_list.keys())
2206            self.on_close_welcome_panel()
2207       
2208    def set_data(self, data_id, theory_id=None): 
2209        """
2210        set data to current perspective
2211        """
2212        list_data, _ = self._data_manager.get_by_id(data_id)
2213        if self._current_perspective is not None:
2214            if self.cleanup_plots:
2215                for uid, panel in self.plot_panels.iteritems():
2216                    #panel = self.plot_panels[uid]
2217                    window = self._mgr.GetPane(panel.window_name)
2218                    # To hide all docked plot panels when set the data
2219                    if not window.IsFloating():
2220                        self.hide_panel(uid)
2221            self._current_perspective.set_data(list_data.values())
2222            self.on_close_welcome_panel()
2223        else:
2224            msg = "Guiframe does not have a current perspective"
2225            logging.info(msg)
2226           
2227    def set_theory(self, state_id, theory_id=None):
2228        """
2229        """
2230        _, list_theory = self._data_manager.get_by_id(theory_id)
2231        if self._current_perspective is not None:
2232            try:
2233                self._current_perspective.set_theory(list_theory.values())
2234            except:
2235                msg = "Guiframe set_theory: \n" + str(sys.exc_value)
2236                logging.info(msg)
2237                wx.PostEvent(self, StatusEvent(status=msg, info="error"))
2238        else:
2239            msg = "Guiframe does not have a current perspective"
2240            logging.info(msg)
2241           
2242    def plot_data(self,  state_id, data_id=None,
2243                  theory_id=None, append=False):
2244        """
2245        send a list of data to plot
2246        """
2247        total_plot_list = []
2248        data_list, _ = self._data_manager.get_by_id(data_id)
2249        _, temp_list_theory = self._data_manager.get_by_id(theory_id)
2250        total_plot_list = data_list.values()
2251        for item in temp_list_theory.values():
2252            theory_data, theory_state = item
2253            total_plot_list.append(theory_data)
2254        GROUP_ID = wx.NewId()
2255        for new_plot in total_plot_list:
2256            if append:
2257                if self.panel_on_focus is None:
2258                    message = "cannot append plot. No plot panel on focus!"
2259                    message += "please click on any available plot to set focus"
2260                    wx.PostEvent(self, StatusEvent(status=message, 
2261                                                   info='warning'))
2262                    return 
2263                else:
2264                    if self.enable_add_data(new_plot):
2265                        new_plot.group_id = self.panel_on_focus.group_id
2266                    else:
2267                        message = "Only 1D Data can be append to"
2268                        message += " plot panel containing 1D data.\n"
2269                        message += "%s not be appended.\n" %str(new_plot.name)
2270                        message += "try new plot option.\n"
2271                        wx.PostEvent(self, StatusEvent(status=message, 
2272                                                   info='warning'))
2273            else:
2274                if self.cleanup_plots:
2275                    for id, panel in self.plot_panels.iteritems():
2276                        window = self._mgr.GetPane(panel.window_name)
2277                        # To hide all docked plot panels when set the data
2278                        if not window.IsFloating():
2279                            self.hide_panel(id)
2280                #if not append then new plot
2281                from sans.guiframe.dataFitting import Data2D
2282                if issubclass(Data2D, new_plot.__class__):
2283                    #for 2 D always plot in a separated new plot
2284                    new_plot.group_id = wx.NewId()
2285                else:
2286                    # plot all 1D in a new plot
2287                    new_plot.group_id = GROUP_ID
2288            title = "PLOT " + str(new_plot.title)
2289            wx.PostEvent(self, NewPlotEvent(plot=new_plot,
2290                                                  title=title,
2291                                                  group_id = new_plot.group_id))
2292           
2293    def remove_data(self, data_id, theory_id=None):
2294        """
2295        Delete data state if data_id is provide
2296        delete theory created with data of id data_id if theory_id is provide
2297        if delete all true: delete the all state
2298        else delete theory
2299        """
2300        temp = data_id + theory_id
2301        """
2302        value = [plug.is_in_use(temp) for plug in self.plugins]
2303        if len(value) > 0:
2304            print "value"
2305            return
2306            from data_panel import DataDialog
2307            dlg = DataDialog(data_list=data_list, nb_data=MAX_NBR_DATA)
2308            if dlg.ShowModal() == wx.ID_OK:
2309                selected_data_list = dlg.get_data()
2310            dlg.Destroy()
2311        """
2312        for plug in self.plugins:
2313            plug.delete_data(temp)
2314        total_plot_list = []
2315        data_list, _ = self._data_manager.get_by_id(data_id)
2316        _, temp_list_theory = self._data_manager.get_by_id(theory_id)
2317        total_plot_list = data_list.values()
2318        for item in temp_list_theory.values():
2319            theory_data, theory_state = item
2320            total_plot_list.append(theory_data)
2321        for new_plot in total_plot_list:
2322            id = new_plot.id
2323            for group_id in new_plot.list_group_id:
2324                wx.PostEvent(self, NewPlotEvent(id=id,
2325                                                   group_id=group_id,
2326                                                   action='remove'))
2327                #remove res plot: Todo: improve
2328                wx.CallAfter(self._remove_res_plot, id)
2329        self._data_manager.delete_data(data_id=data_id, 
2330                                       theory_id=theory_id)
2331           
2332    def _remove_res_plot(self, id):
2333        """
2334        Try to remove corresponding res plot
2335       
2336        : param id: id of the data
2337        """
2338        try:
2339            wx.PostEvent(self, NewPlotEvent(id=("res"+str(id)),
2340                                           group_id=("res"+str(id)),
2341                                           action='remove'))
2342        except:
2343            pass
2344                         
2345    def set_current_perspective(self, perspective):
2346        """
2347        set the current active perspective
2348        """
2349        self._current_perspective = perspective
2350        name = "No current analysis selected"
2351        if self._current_perspective is not None:
2352            self._add_current_plugin_menu()
2353            for panel in self.panels.values():
2354                if hasattr(panel, 'CENTER_PANE') and panel.CENTER_PANE:
2355                    for name in self._current_perspective.get_perspective():
2356                        if name == panel.window_name:
2357                            panel.on_set_focus(event=None)
2358                            break               
2359            name = self._current_perspective.sub_menu
2360            if self._data_panel is not None:
2361                self._data_panel.set_active_perspective(name)
2362                self._check_applications_menu()
2363            #Set the SansView title
2364            self._set_title_name(name)
2365         
2366           
2367    def _set_title_name(self, name):
2368        """
2369        Set the SansView title w/ the current application name
2370       
2371        : param name: application name [string]
2372        """
2373        # Set SanView Window title w/ application anme
2374        title = self.title + "  - " + name + " -"
2375        self.SetTitle(title)
2376           
2377    def _check_applications_menu(self):
2378        """
2379        check the menu of the current application
2380        """
2381        if self._applications_menu is not None:
2382            for menu in self._applications_menu.GetMenuItems():
2383                if self._current_perspective is not None:
2384                    name = self._current_perspective.sub_menu
2385                    if menu.IsCheckable():
2386                        if menu.GetLabel() == name:
2387                            menu.Check(True)
2388                        else:
2389                             menu.Check(False) 
2390           
2391    def set_plotpanel_floating(self, event=None):
2392        """
2393        make the plot panel floatable
2394        """
2395       
2396        self.__gui_style &= (~GUIFRAME.FIXED_PANEL)
2397        self.__gui_style |= GUIFRAME.FLOATING_PANEL
2398        plot_panel = []
2399        id = event.GetId()
2400        menu = self._window_menu.FindItemById(id)
2401        if self._plotting_plugin is not None:
2402            plot_panel = self.plot_panels.values()
2403            for p in plot_panel:
2404                self._popup_floating_panel(p)
2405            menu.Check(True)
2406           
2407    def set_plotpanel_fixed(self, event=None):
2408        """
2409        make the plot panel fixed
2410        """
2411        self.__gui_style &= (~GUIFRAME.FLOATING_PANEL)
2412        self.__gui_style |= GUIFRAME.FIXED_PANEL
2413        plot_panel = []
2414        id = event.GetId()
2415        menu = self._window_menu.FindItemById(id)
2416        if self._plotting_plugin is not None:
2417            plot_panel = self.plot_panels.values()
2418            for p in plot_panel:
2419                self._popup_fixed_panel(p)
2420            menu.Check(True)
2421           
2422    def on_cleanup_dock(self, event=None):     
2423        """
2424        Set Cleanup Dock option
2425        """
2426        if event == None:
2427            return
2428        id = event.GetId()
2429        menu = self._window_menu.FindItemById(id)
2430        Flag = self.cleanup_plots
2431        if not Flag:
2432            menu.Check(True)
2433            self.cleanup_plots = True
2434            msg = "Cleanup-Dock option set to 'ON'."
2435        else:
2436            menu.Check(False)
2437            self.cleanup_plots = False
2438            msg = "Cleanup-Dock option set to 'OFF'."
2439
2440        wx.PostEvent(self, StatusEvent(status= msg))
2441         
2442    def _popup_fixed_panel(self, p):
2443        """
2444        """
2445        style = self.__gui_style & GUIFRAME.FIXED_PANEL
2446        if style == GUIFRAME.FIXED_PANEL:
2447            self._mgr.GetPane(p.window_name).Dock()
2448            self._mgr.GetPane(p.window_name).Floatable()
2449            self._mgr.GetPane(p.window_name).Right()
2450            self._mgr.GetPane(p.window_name).TopDockable(False)
2451            self._mgr.GetPane(p.window_name).BottomDockable(False)
2452            self._mgr.GetPane(p.window_name).LeftDockable(False)
2453            self._mgr.GetPane(p.window_name).RightDockable(True)
2454            self._mgr.Update()
2455           
2456    def _popup_floating_panel(self, p):
2457        """
2458        """
2459        style = self.__gui_style &  GUIFRAME.FLOATING_PANEL
2460        if style == GUIFRAME.FLOATING_PANEL: 
2461            self._mgr.GetPane(p.window_name).Floatable(True)
2462            self._mgr.GetPane(p.window_name).Float()
2463            self._mgr.GetPane(p.window_name).Dockable(False)
2464            self._mgr.Update()
2465           
2466    def enable_add_data(self, new_plot):
2467        """
2468        Enable append data on a plot panel
2469        """
2470
2471        if self.panel_on_focus not in self._plotting_plugin.plot_panels.values():
2472            return
2473        is_theory = len(self.panel_on_focus.plots) <= 1 and \
2474            self.panel_on_focus.plots.values()[0].__class__.__name__ == "Theory1D"
2475           
2476        is_data2d = hasattr(new_plot, 'data')
2477       
2478        is_data1d = self.panel_on_focus.__class__.__name__ == "ModelPanel1D"\
2479            and self.panel_on_focus.group_id is not None
2480        has_meta_data = hasattr(new_plot, 'meta_data')
2481       
2482        #disable_add_data if the data is being recovered from  a saved state file.
2483        is_state_data = False
2484        if has_meta_data:
2485            if 'invstate' in new_plot.meta_data: is_state_data = True
2486            if  'prstate' in new_plot.meta_data: is_state_data = True
2487            if  'fitstate' in new_plot.meta_data: is_state_data = True
2488   
2489        return is_data1d and not is_data2d and not is_theory and not is_state_data
2490   
2491    def enable_edit_menu(self):
2492        """
2493        enable menu item under edit menu depending on the panel on focus
2494        """
2495        if self.cpanel_on_focus is not None and self._edit_menu is not None:
2496            flag = self.cpanel_on_focus.get_undo_flag()
2497            self._edit_menu.Enable(GUIFRAME_ID.UNDO_ID, flag)
2498            flag = self.cpanel_on_focus.get_redo_flag()
2499            self._edit_menu.Enable(GUIFRAME_ID.REDO_ID, flag)
2500            flag = self.cpanel_on_focus.get_copy_flag()
2501            self._edit_menu.Enable(GUIFRAME_ID.COPY_ID, flag)
2502            flag = self.cpanel_on_focus.get_paste_flag()
2503            self._edit_menu.Enable(GUIFRAME_ID.PASTE_ID, flag)
2504            #flag = self.cpanel_on_focus.get_print_flag()
2505            #self._edit_menu.Enable(GUIFRAME_ID.PRINT_ID, flag)
2506            flag = self.cpanel_on_focus.get_preview_flag()
2507            self._edit_menu.Enable(GUIFRAME_ID.PREVIEW_ID, flag)
2508            flag = self.cpanel_on_focus.get_reset_flag()
2509            self._edit_menu.Enable(GUIFRAME_ID.RESET_ID, flag)
2510        else:
2511            flag = False
2512            self._edit_menu.Enable(GUIFRAME_ID.UNDO_ID, flag)
2513            self._edit_menu.Enable(GUIFRAME_ID.REDO_ID, flag)
2514            self._edit_menu.Enable(GUIFRAME_ID.COPY_ID, flag)
2515            self._edit_menu.Enable(GUIFRAME_ID.PASTE_ID, flag)
2516            #self._edit_menu.Enable(GUIFRAME_ID.PRINT_ID, flag)
2517            self._edit_menu.Enable(GUIFRAME_ID.PREVIEW_ID, flag)
2518            self._edit_menu.Enable(GUIFRAME_ID.RESET_ID, flag)
2519           
2520    def on_undo_panel(self, event=None):
2521        """
2522        undo previous action of the last panel on focus if possible
2523        """
2524        if self.cpanel_on_focus is not None:
2525            self.cpanel_on_focus.on_undo(event)
2526           
2527    def on_redo_panel(self, event=None):
2528        """
2529        redo the last cancel action done on the last panel on focus
2530        """
2531        if self.cpanel_on_focus is not None:
2532            self.cpanel_on_focus.on_redo(event)
2533           
2534    def on_copy_panel(self, event=None):
2535        """
2536        copy the last panel on focus if possible
2537        """
2538        if self.cpanel_on_focus is not None:
2539            self.cpanel_on_focus.on_copy(event)
2540           
2541    def on_paste_panel(self, event=None):
2542        """
2543        paste clipboard to the last panel on focus
2544        """
2545        if self.cpanel_on_focus is not None:
2546            self.cpanel_on_focus.on_paste(event)
2547                   
2548    def on_bookmark_panel(self, event=None):
2549        """
2550        bookmark panel
2551        """
2552        if self.cpanel_on_focus is not None:
2553            self.cpanel_on_focus.on_bookmark(event)
2554           
2555    def append_bookmark(self, event=None):
2556        """
2557        Bookmark available information of the panel on focus
2558        """
2559        self._toolbar.append_bookmark(event)
2560           
2561    def on_save_panel(self, event=None):
2562        """
2563        save possible information on the current panel
2564        """
2565        if self.cpanel_on_focus is not None:
2566            self.cpanel_on_focus.on_save(event)
2567           
2568    def on_preview_panel(self, event=None):
2569        """
2570        preview information on the panel on focus
2571        """
2572        if self.cpanel_on_focus is not None:
2573            self.cpanel_on_focus.on_preview(event)
2574           
2575    def on_print_panel(self, event=None):
2576        """
2577        print available information on the last panel on focus
2578        """
2579        if self.cpanel_on_focus is not None:
2580            self.cpanel_on_focus.on_print(event)
2581           
2582    def on_zoom_panel(self, event=None):
2583        """
2584        zoom on the current panel if possible
2585        """
2586        if self.cpanel_on_focus is not None:
2587            self.cpanel_on_focus.on_zoom(event)
2588           
2589    def on_zoom_in_panel(self, event=None):
2590        """
2591        zoom in of the panel on focus
2592        """
2593        if self.cpanel_on_focus is not None:
2594            self.cpanel_on_focus.on_zoom_in(event)
2595           
2596    def on_zoom_out_panel(self, event=None):
2597        """
2598        zoom out on the panel on focus
2599        """
2600        if self.cpanel_on_focus is not None:
2601            self.cpanel_on_focus.on_zoom_out(event)
2602           
2603    def on_drag_panel(self, event=None):
2604        """
2605        drag apply to the panel on focus
2606        """
2607        if self.cpanel_on_focus is not None:
2608            self.cpanel_on_focus.on_drag(event)
2609           
2610    def on_reset_panel(self, event=None):
2611        """
2612        reset the current panel
2613        """
2614        if self.cpanel_on_focus is not None:
2615            self.cpanel_on_focus.on_reset(event)
2616           
2617    def on_change_caption(self, name, old_caption, new_caption):     
2618        """
2619        Change the panel caption
2620       
2621        :param name: window_name of the pane
2622        :param old_caption: current caption [string]
2623        :param new_caption: new caption [string]
2624        """
2625        # wx.aui.AuiPaneInfo
2626        pane_info = self.get_paneinfo(name) 
2627        # update the data_panel.cb_plotpanel
2628        if 'data_panel' in self.panels.keys():
2629            # remove from data_panel combobox
2630            data_panel = self.panels["data_panel"]
2631            if data_panel.cb_plotpanel is not None:
2632                # Check if any panel has the same caption
2633                has_newstring = data_panel.cb_plotpanel.FindString\
2634                                                            (str(new_caption)) 
2635                caption = new_caption
2636                if has_newstring != wx.NOT_FOUND:
2637                    captions = self._get_plotpanel_captions()
2638                    # Append nummber
2639                    inc = 1
2640                    while (1):
2641                        caption = new_caption + '_%s'% str(inc)
2642                        if caption not in captions:
2643                            break
2644                        inc += 1
2645                    # notify to users
2646                    msg = "Found Same Title: Added '_%s'"% str(inc)
2647                    wx.PostEvent(self, StatusEvent(status=msg))
2648                # update data_panel cb
2649                pos = data_panel.cb_plotpanel.FindString(str(old_caption)) 
2650                if pos != wx.NOT_FOUND:
2651                    data_panel.cb_plotpanel.SetString(pos, caption)
2652                    data_panel.cb_plotpanel.SetStringSelection(caption)
2653        # update window Show menu
2654        if self._window_menu != None:
2655            for item in self._window_menu.GetMenuItems():
2656                pos = self._window_menu.FindItem(old_caption)
2657                if self._window_menu.GetLabel(pos) == str(old_caption):
2658                    self._window_menu.SetLabel(pos, caption)
2659                break
2660        # New Caption
2661        pane_info.Caption(caption)
2662        # update aui manager
2663        self._mgr.Update()
2664        return caption
2665       
2666    def get_paneinfo(self, name):
2667        """
2668        Get pane Caption from window_name
2669       
2670        :param name: window_name in AuiPaneInfo
2671        : return: AuiPaneInfo of the name
2672        """
2673        return self._mgr.GetPane(name) 
2674   
2675    def enable_undo(self):
2676        """
2677        enable undo related control
2678        """
2679        if self.cpanel_on_focus is not None:
2680            self._toolbar.enable_undo(self.cpanel_on_focus)
2681           
2682    def enable_redo(self):
2683        """
2684        enable redo
2685        """
2686        if self.cpanel_on_focus is not None:
2687            self._toolbar.enable_redo(self.cpanel_on_focus)
2688           
2689    def enable_copy(self):
2690        """
2691        enable copy related control
2692        """
2693        if self.cpanel_on_focus is not None:
2694            self._toolbar.enable_copy(self.cpanel_on_focus)
2695           
2696    def enable_paste(self):
2697        """
2698        enable paste
2699        """
2700        if self.cpanel_on_focus is not None:
2701            self._toolbar.enable_paste(self.cpanel_on_focus)
2702                       
2703    def enable_bookmark(self):
2704        """
2705        Bookmark
2706        """
2707        if self.cpanel_on_focus is not None:
2708            self._toolbar.enable_bookmark(self.cpanel_on_focus)
2709           
2710    def enable_save(self):
2711        """
2712        save
2713        """
2714        if self.cpanel_on_focus is not None:
2715            self._toolbar.enable_save(self.cpanel_on_focus)
2716           
2717    def enable_preview(self):
2718        """
2719        preview
2720        """
2721        if self.cpanel_on_focus is not None:
2722            self._toolbar.enable_preview(self.cpanel_on_focus)
2723           
2724    def enable_print(self):
2725        """
2726        print
2727        """
2728        if self.cpanel_on_focus is not None:
2729            self._toolbar.enable_print(self.cpanel_on_focus)
2730           
2731    def enable_zoom(self):
2732        """
2733        zoom
2734        """
2735        if self.cpanel_on_focus is not None:
2736            self._toolbar.enable_zoom(self.panel_on_focus)
2737           
2738    def enable_zoom_in(self):
2739        """
2740        zoom in
2741        """
2742        if self.cpanel_on_focus is not None:
2743            self._toolbar.enable_zoom_in(self.panel_on_focus)
2744           
2745    def enable_zoom_out(self):
2746        """
2747        zoom out
2748        """
2749        if self.cpanel_on_focus is not None:
2750            self._toolbar.enable_zoom_out(self.panel_on_focus)
2751           
2752    def enable_drag(self, event=None):
2753        """
2754        drag
2755        """
2756        if self.cpanel_on_focus is not None:
2757            self._toolbar.enable_drag(self.panel_on_focus)
2758           
2759    def enable_reset(self):
2760        """
2761        reset the current panel
2762        """
2763        if self.cpanel_on_focus is not None:
2764            self._toolbar.enable_reset(self.panel_on_focus)
2765
2766    def set_schedule_full_draw(self, panel=None, func='del'):
2767        """
2768        Add/subtract the schedule full draw list with the panel given
2769       
2770        :param panel: plot panel
2771        :param func: append or del [string]
2772        """
2773
2774        # append this panel in the schedule list if not in yet
2775        if func == 'append':
2776            if not panel in self.schedule_full_draw_list:
2777                self.schedule_full_draw_list.append(panel) 
2778        # remove this panel from schedule list
2779        elif func == 'del':
2780            if len(self.schedule_full_draw_list) > 0:
2781                if panel in self.schedule_full_draw_list:
2782                    self.schedule_full_draw_list.remove(panel)
2783
2784        # reset the schdule
2785        if len(self.schedule_full_draw_list) == 0:
2786            self.schedule = False
2787        else:
2788            self.schedule = True   
2789       
2790    def full_draw(self):
2791        """
2792        Draw the panels with axes in the schedule to full dwar list
2793        """
2794        count = len(self.schedule_full_draw_list)
2795        #if not self.schedule:
2796        if count < 1:
2797            self.set_schedule(False)
2798            return
2799        else:
2800            ind = 0
2801            # if any of the panel is shown do full_draw
2802            for panel in self.schedule_full_draw_list:
2803                ind += 1
2804                if self._mgr.GetPane(panel.window_name).IsShown():
2805                    break
2806                # otherwise, return
2807                if ind == count:
2808                    return
2809
2810        #Simple redraw only for a panel shown
2811        def f_draw(panel):
2812            """
2813            Draw A panel in the full dwar list
2814            """
2815            try:
2816                # This checking of GetCapture is to stop redrawing
2817                # while any panel is capture.
2818                if self.GetCapture() == None:
2819                    # draw if possible
2820                    panel.set_resizing(False)
2821                    panel.Show(False)
2822                    panel.draw_plot()
2823                   
2824                    # Check if the panel is not shown
2825                    if not self._mgr.GetPane(panel.window_name).IsShown():
2826                        self._mgr.GetPane(panel.window_name).Hide()
2827                    else:
2828                        panel.Show(True)
2829            except:
2830                pass
2831       
2832        # Draw all panels       
2833        map(f_draw, self.schedule_full_draw_list)
2834       
2835        # Reset the attr 
2836        if len(self.schedule_full_draw_list) == 0:
2837            self.set_schedule(False)
2838        else:
2839            self.set_schedule(True)
2840        # do not update mgr
2841        #self._mgr.Update()
2842       
2843    def set_schedule(self, schedule=False): 
2844        """
2845        Set schedule
2846        """
2847        self.schedule = schedule
2848               
2849    def get_schedule(self): 
2850        """
2851        Get schedule
2852        """
2853        return self.schedule
2854   
2855    def on_set_plot_focus(self, panel):
2856        """
2857        Set focus on a plot panel
2858        """
2859        self.set_plot_unfocus()
2860        panel.on_set_focus(None) 
2861        # set focusing panel
2862        self.panel_on_focus = panel 
2863        self.set_panel_on_focus(None)
2864
2865    def set_plot_unfocus(self): 
2866        """
2867        Un focus all plot panels
2868        """
2869        for plot in self.plot_panels.values():
2870            plot.on_kill_focus(None)
2871
2872    def _onDrawIdle(self, *args, **kwargs):
2873        """
2874        ReDraw with axes
2875        """
2876        try:
2877            # check if it is time to redraw
2878            if self.GetCapture() == None:
2879                # Draw plot, changes resizing too
2880                self.full_draw()
2881        except:
2882            pass
2883           
2884        # restart idle       
2885        self._redraw_idle(*args, **kwargs)
2886
2887           
2888    def _redraw_idle(self, *args, **kwargs):
2889        """
2890        Restart Idle
2891        """
2892        # restart idle   
2893        self.idletimer.Restart(55, *args, **kwargs)
2894
2895       
2896class DefaultPanel(wx.Panel, PanelBase):
2897    """
2898    Defines the API for a panels to work with
2899    the GUI manager
2900    """
2901    ## Internal nickname for the window, used by the AUI manager
2902    window_name = "default"
2903    ## Name to appear on the window title bar
2904    window_caption = "Welcome panel"
2905    ## Flag to tell the AUI manager to put this panel in the center pane
2906    CENTER_PANE = True
2907    def __init__(self, parent, *args, **kwds):
2908        wx.Panel.__init__(self, parent, *args, **kwds)
2909        PanelBase.__init__(self, parent)
2910   
2911
2912
2913# Toy application to test this Frame
2914class ViewApp(wx.App):
2915    """
2916    """
2917    def OnInit(self):
2918        """
2919        """
2920        pos, size = self.window_placement((GUIFRAME_WIDTH, GUIFRAME_HEIGHT))
2921        self.frame = ViewerFrame(parent=None, 
2922                                 title=APPLICATION_NAME, 
2923                                 pos=pos, 
2924                                 gui_style = DEFAULT_STYLE,
2925                                 size=size) 
2926        self.frame.Hide()
2927        self.s_screen = None
2928        temp_path = None
2929        try:
2930            _change_current_dir()
2931        except:
2932            pass
2933        try:
2934            self.open_file()
2935        except:
2936            msg = "%s Could not load " % str(APPLICATION_NAME)
2937            msg += "input file from command line.\n"
2938            logging.error(msg)
2939        # Display a splash screen on top of the frame.
2940        if len(sys.argv) > 1 and '--time' in sys.argv[1:]:
2941            log_time("Starting to display the splash screen")
2942        try:
2943            if os.path.isfile(SPLASH_SCREEN_PATH):
2944                self.s_screen = self.display_splash_screen(parent=self.frame, 
2945                                        path=SPLASH_SCREEN_PATH)
2946            else:
2947                self.frame.Show()   
2948        except:
2949            if self.s_screen is not None:
2950                self.s_screen.Close()
2951            msg = "Cannot display splash screen\n"
2952            msg += str (sys.exc_value)
2953            logging.error(msg)
2954            self.frame.Show()
2955 
2956        if hasattr(self.frame, 'special'):
2957            self.frame.special.SetCurrent()
2958        self.SetTopWindow(self.frame)
2959 
2960        return True
2961
2962    def open_file(self):
2963        """
2964        open a state file at the start of the application
2965        """
2966        input_file = None
2967        if len(sys.argv) >= 2:
2968            cmd = sys.argv[0].lower()
2969            basename  = os.path.basename(cmd)
2970            app_base = str(APPLICATION_NAME).lower()
2971            if os.path.isfile(cmd) or basename.lower() == app_base:
2972                app_py = app_base + '.py'
2973                app_exe = app_base + '.exe'
2974                app_app = app_base + '.app'
2975                if basename.lower() in [app_py, app_exe, app_app, app_base]:
2976                    data_base = sys.argv[1]
2977                    input_file = os.path.normpath(os.path.join(DATAPATH, 
2978                                                               data_base))
2979        if input_file is None:
2980            return
2981        if self.frame is not None:
2982            self.frame.set_input_file(input_file=input_file)
2983         
2984           
2985    def set_manager(self, manager):
2986        """
2987        Sets a reference to the application manager
2988        of the GUI manager (Frame)
2989        """
2990        self.frame.set_manager(manager)
2991       
2992    def build_gui(self):
2993        """
2994        Build the GUI
2995        """
2996        #try to load file at the start
2997        try:
2998            self.open_file()
2999        except:
3000            raise
3001        self.frame.build_gui()
3002        #if self.s_screen is not None and self.s_screen.IsShown():
3003        #    self.s_screen.Close()
3004       
3005    def set_welcome_panel(self, panel_class):
3006        """
3007        Set the welcome panel
3008       
3009        :param panel_class: class of the welcome panel to be instantiated
3010       
3011        """
3012        self.frame.set_welcome_panel(panel_class)
3013       
3014    def add_perspective(self, perspective):
3015        """
3016        Manually add a perspective to the application GUI
3017        """
3018        self.frame.add_perspective(perspective)
3019   
3020    def window_placement(self, size):
3021        """
3022        Determines the position and size of the application frame such that it
3023        fits on the user's screen without obstructing (or being obstructed by)
3024        the Windows task bar.  The maximum initial size in pixels is bounded by
3025        WIDTH x HEIGHT.  For most monitors, the application
3026        will be centered on the screen; for very large monitors it will be
3027        placed on the left side of the screen.
3028        """
3029        window_width, window_height = size
3030        screen_size = wx.GetDisplaySize()
3031        window_height = window_height if screen_size[1]>window_height else screen_size[1]-10
3032        window_width  = window_width if screen_size[0]> window_width else screen_size[0]-10
3033        xpos = ypos = 0
3034
3035        # Note that when running Linux and using an Xming (X11) server on a PC
3036        # with a dual  monitor configuration, the reported display size may be
3037        # that of both monitors combined with an incorrect display count of 1.
3038        # To avoid displaying this app across both monitors, we check for
3039        # screen 'too big'.  If so, we assume a smaller width which means the
3040        # application will be placed towards the left hand side of the screen.
3041
3042        _, _, x, y = wx.Display().GetClientArea() # size excludes task bar
3043        if len(sys.argv) > 1 and '--platform' in sys.argv[1:]:
3044            w, h = wx.DisplaySize()  # size includes task bar area
3045        # display on left side, not centered on screen
3046        if x > 1920 and x > (2*y): x = x / 2 
3047        if x > window_width:  xpos = (x - window_width)/2
3048        if y > window_height: ypos = (y - window_height)/2
3049
3050        # Return the suggested position and size for the application frame.
3051        return (xpos, ypos), (min(x, window_width), min(y, window_height))
3052   
3053    def display_splash_screen(self, parent, 
3054                              path=SPLASH_SCREEN_PATH):
3055        """Displays the splash screen.  It will exactly cover the main frame."""
3056       
3057        # Prepare the picture.  On a 2GHz intel cpu, this takes about a second.
3058        x, y = parent.GetSizeTuple()
3059        image = wx.Image(path, wx.BITMAP_TYPE_PNG)
3060        image.Rescale(SPLASH_SCREEN_WIDTH, 
3061                      SPLASH_SCREEN_HEIGHT, wx.IMAGE_QUALITY_HIGH)
3062        bm = image.ConvertToBitmap()
3063
3064        # Create and show the splash screen.  It will disappear only when the
3065        # program has entered the event loop AND either the timeout has expired
3066        # or the user has left clicked on the screen.  Thus any processing
3067        # performed in this routine (including sleeping) or processing in the
3068        # calling routine (including doing imports) will prevent the splash
3069        # screen from disappearing.
3070        #
3071        # Note that on Linux, the timeout appears to occur immediately in which
3072        # case the splash screen disappears upon entering the event loop.
3073        s_screen = wx.SplashScreen(bitmap=bm,
3074                         splashStyle=(wx.SPLASH_TIMEOUT|
3075                                              wx.SPLASH_CENTRE_ON_SCREEN),
3076                                 style=(wx.SIMPLE_BORDER|
3077                                        wx.FRAME_NO_TASKBAR|
3078                                        wx.STAY_ON_TOP),
3079                                       
3080                        milliseconds=SS_MAX_DISPLAY_TIME,
3081                        parent=parent,
3082                        id=wx.ID_ANY)
3083        from gui_statusbar import SPageStatusbar
3084        statusBar = SPageStatusbar(s_screen)
3085        s_screen.SetStatusBar(statusBar)
3086        s_screen.Bind(wx.EVT_CLOSE, self.on_close_splash_screen)
3087        s_screen.Show()
3088        return s_screen
3089       
3090       
3091    def on_close_splash_screen(self, event):
3092        """
3093        """
3094        self.frame.Show(True)
3095        event.Skip()
3096     
3097if __name__ == "__main__": 
3098    app = ViewApp(0)
3099    app.MainLoop()
3100
3101             
Note: See TracBrowser for help on using the repository browser.