source: sasview/sansguiframe/src/sans/guiframe/gui_manager.py @ 15f68ce

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 15f68ce was 58fc26c, checked in by Jae Cho <jhjcho@…>, 13 years ago

fixed unstable c_panel focusing problem

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