source: sasview/sansguiframe/src/sans/guiframe/gui_manager.py @ 108470e6

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 108470e6 was 9a56619, checked in by Jae Cho <jhjcho@…>, 13 years ago

added frame icons

  • Property mode set to 100644
File size: 120.8 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_set_focus(None)
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                    raise
2142                    msg = "This feature requires 'Adobe pdf Reader'\n"
2143                    msg += "Please install it first (Free)..."
2144                    wx.MessageBox(msg, 'Error')
2145            else:
2146                try:
2147                    command = "open "
2148                    command += path
2149                    os.system(command)
2150                except:
2151                    msg = "This feature requires 'Preview' Application\n"
2152                    msg += "Please install it first..."
2153                    wx.MessageBox(msg, 'Error')
2154
2155                     
2156    def set_manager(self, manager):
2157        """
2158        Sets the application manager for this frame
2159       
2160        :param manager: frame manager
2161        """
2162        self.app_manager = manager
2163       
2164    def post_init(self):
2165        """
2166        This initialization method is called after the GUI
2167        has been created and all plug-ins loaded. It calls
2168        the post_init() method of each plug-in (if it exists)
2169        so that final initialization can be done.
2170        """
2171        for item in self.plugins:
2172            if hasattr(item, "post_init"):
2173                item.post_init()
2174       
2175    def set_default_perspective(self):
2176        """
2177        Choose among the plugin the first plug-in that has
2178        "set_default_perspective" method and its return value is True will be
2179        as a default perspective when the welcome page is closed
2180        """
2181        for item in self.plugins:
2182            if hasattr(item, "set_default_perspective"):
2183                if item.set_default_perspective():
2184                    item.on_perspective(event=None)
2185                    return 
2186       
2187    def set_perspective(self, panels):
2188        """
2189        Sets the perspective of the GUI.
2190        Opens all the panels in the list, and closes
2191        all the others.
2192       
2193        :param panels: list of panels
2194        """
2195        #style = self.__gui_style & GUIFRAME.TOOLBAR_ON
2196        #if (style == GUIFRAME.TOOLBAR_ON) & (not self._toolbar.IsShown()):
2197        #    self._on_toggle_toolbar()
2198        for item in self.panels:
2199            # Check whether this is a sticky panel
2200            if hasattr(self.panels[item], "ALWAYS_ON"):
2201                if self.panels[item].ALWAYS_ON:
2202                    continue 
2203           
2204            if self.panels[item].window_name in panels:
2205                if not self._mgr.GetPane(self.panels[item].window_name).IsShown():
2206                    self._mgr.GetPane(self.panels[item].window_name).Show()
2207            else:
2208                # always show the data panel if enable
2209                style = self.__gui_style & GUIFRAME.MANAGER_ON
2210                if (style == GUIFRAME.MANAGER_ON) and self.panels[item] == self._data_panel:
2211                    if 'data_panel' in self.panels.keys():
2212                        flag = self._mgr.GetPane(self.panels['data_panel'].window_name).IsShown()
2213                        self._mgr.GetPane(self.panels['data_panel'].window_name).Show(flag)
2214                else:
2215                    if self._mgr.GetPane(self.panels[item].window_name).IsShown():
2216                        self._mgr.GetPane(self.panels[item].window_name).Hide()
2217               
2218        self._mgr.Update()
2219       
2220    def show_data_panel(self, event=None, action=True):
2221        """
2222        show the data panel
2223        """
2224        if self._data_panel_menu == None:
2225            return
2226        label = self._data_panel_menu.GetText()
2227        if label == 'Show Data Explorer':
2228            pane = self._mgr.GetPane(self.panels["data_panel"].window_name)
2229            #if not pane.IsShown():
2230            if action: 
2231                pane.Show(True)
2232                self._mgr.Update()
2233            self.__gui_style = self.__gui_style | GUIFRAME.MANAGER_ON
2234           
2235            self._data_panel_menu.SetText('Hide Data Explorer')
2236        else:
2237            pane = self._mgr.GetPane(self.panels["data_panel"].window_name)
2238            #if not pane.IsShown():
2239            if action:
2240                pane.Show(False)
2241                self._mgr.Update()
2242            self.__gui_style = self.__gui_style & (~GUIFRAME.MANAGER_ON)
2243            self._data_panel_menu.SetText('Show Data Explorer')
2244   
2245    def add_data_helper(self, data_list):
2246        """
2247        """
2248        if self._data_manager is not None:
2249            self._data_manager.add_data(data_list)
2250       
2251    def add_data(self, data_list):
2252        """
2253        receive a dictionary of data from loader
2254        store them its data manager if possible
2255        send to data the current active perspective if the data panel
2256        is not active.
2257        :param data_list: dictionary of data's ID and value Data
2258        """
2259        #Store data into manager
2260        self.add_data_helper(data_list)
2261        # set data in the data panel
2262        if self._data_panel is not None:
2263            data_state = self._data_manager.get_data_state(data_list.keys())
2264            self._data_panel.load_data_list(data_state)
2265        #if the data panel is shown wait for the user to press a button
2266        #to send data to the current perspective. if the panel is not
2267        #show  automatically send the data to the current perspective
2268        style = self.__gui_style & GUIFRAME.MANAGER_ON
2269        if style == GUIFRAME.MANAGER_ON:
2270            #wait for button press from the data panel to set_data
2271            if self._data_panel is not None:
2272                self._mgr.GetPane(self._data_panel.window_name).Show(True)
2273                self._mgr.Update() 
2274        else:
2275            #automatically send that to the current perspective
2276            self.set_data(data_id=data_list.keys())
2277            self.on_close_welcome_panel()
2278       
2279    def set_data(self, data_id, theory_id=None): 
2280        """
2281        set data to current perspective
2282        """
2283        list_data, _ = self._data_manager.get_by_id(data_id)
2284        if self._current_perspective is not None:
2285            if self.cleanup_plots:
2286                for uid, panel in self.plot_panels.iteritems():
2287                    #panel = self.plot_panels[uid]
2288                    window = self._mgr.GetPane(panel.window_name)
2289                    # To hide all docked plot panels when set the data
2290                    if not window.IsFloating():
2291                        self.hide_panel(uid)
2292            self._current_perspective.set_data(list_data.values())
2293            self.on_close_welcome_panel()
2294        else:
2295            msg = "Guiframe does not have a current perspective"
2296            logging.info(msg)
2297           
2298    def set_theory(self, state_id, theory_id=None):
2299        """
2300        """
2301        _, list_theory = self._data_manager.get_by_id(theory_id)
2302        if self._current_perspective is not None:
2303            try:
2304                self._current_perspective.set_theory(list_theory.values())
2305            except:
2306                msg = "Guiframe set_theory: \n" + str(sys.exc_value)
2307                logging.info(msg)
2308                wx.PostEvent(self, StatusEvent(status=msg, info="error"))
2309        else:
2310            msg = "Guiframe does not have a current perspective"
2311            logging.info(msg)
2312           
2313    def plot_data(self,  state_id, data_id=None,
2314                  theory_id=None, append=False):
2315        """
2316        send a list of data to plot
2317        """
2318        total_plot_list = []
2319        data_list, _ = self._data_manager.get_by_id(data_id)
2320        _, temp_list_theory = self._data_manager.get_by_id(theory_id)
2321        total_plot_list = data_list.values()
2322        for item in temp_list_theory.values():
2323            theory_data, theory_state = item
2324            total_plot_list.append(theory_data)
2325        GROUP_ID = wx.NewId()
2326        for new_plot in total_plot_list:
2327            if append:
2328                if self.panel_on_focus is None:
2329                    message = "cannot append plot. No plot panel on focus!"
2330                    message += "please click on any available plot to set focus"
2331                    wx.PostEvent(self, StatusEvent(status=message, 
2332                                                   info='warning'))
2333                    return 
2334                else:
2335                    if self.enable_add_data(new_plot):
2336                        new_plot.group_id = self.panel_on_focus.group_id
2337                    else:
2338                        message = "Only 1D Data can be append to"
2339                        message += " plot panel containing 1D data.\n"
2340                        message += "%s not be appended.\n" %str(new_plot.name)
2341                        message += "try new plot option.\n"
2342                        wx.PostEvent(self, StatusEvent(status=message, 
2343                                                   info='warning'))
2344            else:
2345                if self.cleanup_plots:
2346                    for id, panel in self.plot_panels.iteritems():
2347                        window = self._mgr.GetPane(panel.window_name)
2348                        # To hide all docked plot panels when set the data
2349                        if not window.IsFloating():
2350                            self.hide_panel(id)
2351                #if not append then new plot
2352                from sans.guiframe.dataFitting import Data2D
2353                if issubclass(Data2D, new_plot.__class__):
2354                    #for 2 D always plot in a separated new plot
2355                    new_plot.group_id = wx.NewId()
2356                else:
2357                    # plot all 1D in a new plot
2358                    new_plot.group_id = GROUP_ID
2359            title = "PLOT " + str(new_plot.title)
2360            wx.PostEvent(self, NewPlotEvent(plot=new_plot,
2361                                                  title=title,
2362                                                  group_id = new_plot.group_id))
2363           
2364    def remove_data(self, data_id, theory_id=None):
2365        """
2366        Delete data state if data_id is provide
2367        delete theory created with data of id data_id if theory_id is provide
2368        if delete all true: delete the all state
2369        else delete theory
2370        """
2371        temp = data_id + theory_id
2372        """
2373        value = [plug.is_in_use(temp) for plug in self.plugins]
2374        if len(value) > 0:
2375            print "value"
2376            return
2377            from data_panel import DataDialog
2378            dlg = DataDialog(data_list=data_list, nb_data=MAX_NBR_DATA)
2379            if dlg.ShowModal() == wx.ID_OK:
2380                selected_data_list = dlg.get_data()
2381            dlg.Destroy()
2382        """
2383        for plug in self.plugins:
2384            plug.delete_data(temp)
2385        total_plot_list = []
2386        data_list, _ = self._data_manager.get_by_id(data_id)
2387        _, temp_list_theory = self._data_manager.get_by_id(theory_id)
2388        total_plot_list = data_list.values()
2389        for item in temp_list_theory.values():
2390            theory_data, theory_state = item
2391            total_plot_list.append(theory_data)
2392        for new_plot in total_plot_list:
2393            id = new_plot.id
2394            for group_id in new_plot.list_group_id:
2395                wx.PostEvent(self, NewPlotEvent(id=id,
2396                                                   group_id=group_id,
2397                                                   action='remove'))
2398                #remove res plot: Todo: improve
2399                wx.CallAfter(self._remove_res_plot, id)
2400        self._data_manager.delete_data(data_id=data_id, 
2401                                       theory_id=theory_id)
2402           
2403    def _remove_res_plot(self, id):
2404        """
2405        Try to remove corresponding res plot
2406       
2407        : param id: id of the data
2408        """
2409        try:
2410            wx.PostEvent(self, NewPlotEvent(id=("res"+str(id)),
2411                                           group_id=("res"+str(id)),
2412                                           action='remove'))
2413        except:
2414            pass
2415                         
2416    def set_current_perspective(self, perspective):
2417        """
2418        set the current active perspective
2419        """
2420        self._current_perspective = perspective
2421        name = "No current analysis selected"
2422        if self._current_perspective is not None:
2423            self._add_current_plugin_menu()
2424            for panel in self.panels.values():
2425                if hasattr(panel, 'CENTER_PANE') and panel.CENTER_PANE:
2426                    for name in self._current_perspective.get_perspective():
2427                        if name == panel.window_name:
2428                            panel.on_set_focus(event=None)
2429                            break               
2430            name = self._current_perspective.sub_menu
2431            if self._data_panel is not None:
2432                self._data_panel.set_active_perspective(name)
2433                self._check_applications_menu()
2434            #Set the SansView title
2435            self._set_title_name(name)
2436         
2437           
2438    def _set_title_name(self, name):
2439        """
2440        Set the SansView title w/ the current application name
2441       
2442        : param name: application name [string]
2443        """
2444        # Set SanView Window title w/ application anme
2445        title = self.title + "  - " + name + " -"
2446        self.SetTitle(title)
2447           
2448    def _check_applications_menu(self):
2449        """
2450        check the menu of the current application
2451        """
2452        if self._applications_menu is not None:
2453            for menu in self._applications_menu.GetMenuItems():
2454                if self._current_perspective is not None:
2455                    name = self._current_perspective.sub_menu
2456                    if menu.IsCheckable():
2457                        if menu.GetLabel() == name:
2458                            menu.Check(True)
2459                        else:
2460                             menu.Check(False) 
2461           
2462    def set_plotpanel_floating(self, event=None):
2463        """
2464        make the plot panel floatable
2465        """
2466       
2467        self.__gui_style &= (~GUIFRAME.FIXED_PANEL)
2468        self.__gui_style |= GUIFRAME.FLOATING_PANEL
2469        plot_panel = []
2470        id = event.GetId()
2471        menu = self._window_menu.FindItemById(id)
2472        if self._plotting_plugin is not None:
2473            plot_panel = self.plot_panels.values()
2474            for p in plot_panel:
2475                self._popup_floating_panel(p)
2476            menu.Check(True)
2477           
2478    def set_plotpanel_fixed(self, event=None):
2479        """
2480        make the plot panel fixed
2481        """
2482        self.__gui_style &= (~GUIFRAME.FLOATING_PANEL)
2483        self.__gui_style |= GUIFRAME.FIXED_PANEL
2484        plot_panel = []
2485        id = event.GetId()
2486        menu = self._window_menu.FindItemById(id)
2487        if self._plotting_plugin is not None:
2488            plot_panel = self.plot_panels.values()
2489            for p in plot_panel:
2490                self._popup_fixed_panel(p)
2491            menu.Check(True)
2492           
2493    def on_cleanup_dock(self, event=None):     
2494        """
2495        Set Cleanup Dock option
2496        """
2497        if event == None:
2498            return
2499        id = event.GetId()
2500        menu = self._window_menu.FindItemById(id)
2501        Flag = self.cleanup_plots
2502        if not Flag:
2503            menu.Check(True)
2504            self.cleanup_plots = True
2505            msg = "Cleanup-Dock option set to 'ON'."
2506        else:
2507            menu.Check(False)
2508            self.cleanup_plots = False
2509            msg = "Cleanup-Dock option set to 'OFF'."
2510
2511        wx.PostEvent(self, StatusEvent(status= msg))
2512         
2513    def _popup_fixed_panel(self, p):
2514        """
2515        """
2516        style = self.__gui_style & GUIFRAME.FIXED_PANEL
2517        if style == GUIFRAME.FIXED_PANEL:
2518            self._mgr.GetPane(p.window_name).Dock()
2519            self._mgr.GetPane(p.window_name).Floatable()
2520            self._mgr.GetPane(p.window_name).Right()
2521            self._mgr.GetPane(p.window_name).TopDockable(False)
2522            self._mgr.GetPane(p.window_name).BottomDockable(False)
2523            self._mgr.GetPane(p.window_name).LeftDockable(False)
2524            self._mgr.GetPane(p.window_name).RightDockable(True)
2525            self._mgr.Update()
2526           
2527    def _popup_floating_panel(self, p):
2528        """
2529        """
2530        style = self.__gui_style &  GUIFRAME.FLOATING_PANEL
2531        if style == GUIFRAME.FLOATING_PANEL: 
2532            self._mgr.GetPane(p.window_name).Floatable(True)
2533            self._mgr.GetPane(p.window_name).Float()
2534            self._mgr.GetPane(p.window_name).Dockable(False)
2535            self._mgr.Update()
2536           
2537    def enable_add_data(self, new_plot):
2538        """
2539        Enable append data on a plot panel
2540        """
2541
2542        if self.panel_on_focus not in self._plotting_plugin.plot_panels.values():
2543            return
2544        is_theory = len(self.panel_on_focus.plots) <= 1 and \
2545            self.panel_on_focus.plots.values()[0].__class__.__name__ == "Theory1D"
2546           
2547        is_data2d = hasattr(new_plot, 'data')
2548       
2549        is_data1d = self.panel_on_focus.__class__.__name__ == "ModelPanel1D"\
2550            and self.panel_on_focus.group_id is not None
2551        has_meta_data = hasattr(new_plot, 'meta_data')
2552       
2553        #disable_add_data if the data is being recovered from  a saved state file.
2554        is_state_data = False
2555        if has_meta_data:
2556            if 'invstate' in new_plot.meta_data: is_state_data = True
2557            if  'prstate' in new_plot.meta_data: is_state_data = True
2558            if  'fitstate' in new_plot.meta_data: is_state_data = True
2559   
2560        return is_data1d and not is_data2d and not is_theory and not is_state_data
2561   
2562    def enable_edit_menu(self):
2563        """
2564        enable menu item under edit menu depending on the panel on focus
2565        """
2566        if self.cpanel_on_focus is not None and self._edit_menu is not None:
2567            flag = self.cpanel_on_focus.get_undo_flag()
2568            self._edit_menu.Enable(GUIFRAME_ID.UNDO_ID, flag)
2569            flag = self.cpanel_on_focus.get_redo_flag()
2570            self._edit_menu.Enable(GUIFRAME_ID.REDO_ID, flag)
2571            flag = self.cpanel_on_focus.get_copy_flag()
2572            self._edit_menu.Enable(GUIFRAME_ID.COPY_ID, flag)
2573            flag = self.cpanel_on_focus.get_paste_flag()
2574            self._edit_menu.Enable(GUIFRAME_ID.PASTE_ID, flag)
2575            #flag = self.cpanel_on_focus.get_print_flag()
2576            #self._edit_menu.Enable(GUIFRAME_ID.PRINT_ID, flag)
2577            flag = self.cpanel_on_focus.get_preview_flag()
2578            self._edit_menu.Enable(GUIFRAME_ID.PREVIEW_ID, flag)
2579            flag = self.cpanel_on_focus.get_reset_flag()
2580            self._edit_menu.Enable(GUIFRAME_ID.RESET_ID, flag)
2581        else:
2582            flag = False
2583            self._edit_menu.Enable(GUIFRAME_ID.UNDO_ID, flag)
2584            self._edit_menu.Enable(GUIFRAME_ID.REDO_ID, flag)
2585            self._edit_menu.Enable(GUIFRAME_ID.COPY_ID, flag)
2586            self._edit_menu.Enable(GUIFRAME_ID.PASTE_ID, flag)
2587            #self._edit_menu.Enable(GUIFRAME_ID.PRINT_ID, flag)
2588            self._edit_menu.Enable(GUIFRAME_ID.PREVIEW_ID, flag)
2589            self._edit_menu.Enable(GUIFRAME_ID.RESET_ID, flag)
2590           
2591    def on_undo_panel(self, event=None):
2592        """
2593        undo previous action of the last panel on focus if possible
2594        """
2595        if self.cpanel_on_focus is not None:
2596            self.cpanel_on_focus.on_undo(event)
2597           
2598    def on_redo_panel(self, event=None):
2599        """
2600        redo the last cancel action done on the last panel on focus
2601        """
2602        if self.cpanel_on_focus is not None:
2603            self.cpanel_on_focus.on_redo(event)
2604           
2605    def on_copy_panel(self, event=None):
2606        """
2607        copy the last panel on focus if possible
2608        """
2609        if self.cpanel_on_focus is not None:
2610            self.cpanel_on_focus.on_copy(event)
2611           
2612    def on_paste_panel(self, event=None):
2613        """
2614        paste clipboard to the last panel on focus
2615        """
2616        if self.cpanel_on_focus is not None:
2617            self.cpanel_on_focus.on_paste(event)
2618                   
2619    def on_bookmark_panel(self, event=None):
2620        """
2621        bookmark panel
2622        """
2623        if self.cpanel_on_focus is not None:
2624            self.cpanel_on_focus.on_bookmark(event)
2625           
2626    def append_bookmark(self, event=None):
2627        """
2628        Bookmark available information of the panel on focus
2629        """
2630        self._toolbar.append_bookmark(event)
2631           
2632    def on_save_panel(self, event=None):
2633        """
2634        save possible information on the current panel
2635        """
2636        if self.cpanel_on_focus is not None:
2637            self.cpanel_on_focus.on_save(event)
2638           
2639    def on_preview_panel(self, event=None):
2640        """
2641        preview information on the panel on focus
2642        """
2643        if self.cpanel_on_focus is not None:
2644            self.cpanel_on_focus.on_preview(event)
2645           
2646    def on_print_panel(self, event=None):
2647        """
2648        print available information on the last panel on focus
2649        """
2650        if self.cpanel_on_focus is not None:
2651            self.cpanel_on_focus.on_print(event)
2652           
2653    def on_zoom_panel(self, event=None):
2654        """
2655        zoom on the current panel if possible
2656        """
2657        if self.cpanel_on_focus is not None:
2658            self.cpanel_on_focus.on_zoom(event)
2659           
2660    def on_zoom_in_panel(self, event=None):
2661        """
2662        zoom in of the panel on focus
2663        """
2664        if self.cpanel_on_focus is not None:
2665            self.cpanel_on_focus.on_zoom_in(event)
2666           
2667    def on_zoom_out_panel(self, event=None):
2668        """
2669        zoom out on the panel on focus
2670        """
2671        if self.cpanel_on_focus is not None:
2672            self.cpanel_on_focus.on_zoom_out(event)
2673           
2674    def on_drag_panel(self, event=None):
2675        """
2676        drag apply to the panel on focus
2677        """
2678        if self.cpanel_on_focus is not None:
2679            self.cpanel_on_focus.on_drag(event)
2680           
2681    def on_reset_panel(self, event=None):
2682        """
2683        reset the current panel
2684        """
2685        if self.cpanel_on_focus is not None:
2686            self.cpanel_on_focus.on_reset(event)
2687           
2688    def on_change_caption(self, name, old_caption, new_caption):     
2689        """
2690        Change the panel caption
2691       
2692        :param name: window_name of the pane
2693        :param old_caption: current caption [string]
2694        :param new_caption: new caption [string]
2695        """
2696        # wx.aui.AuiPaneInfo
2697        pane_info = self.get_paneinfo(name) 
2698        # update the data_panel.cb_plotpanel
2699        if 'data_panel' in self.panels.keys():
2700            # remove from data_panel combobox
2701            data_panel = self.panels["data_panel"]
2702            if data_panel.cb_plotpanel is not None:
2703                # Check if any panel has the same caption
2704                has_newstring = data_panel.cb_plotpanel.FindString\
2705                                                            (str(new_caption)) 
2706                caption = new_caption
2707                if has_newstring != wx.NOT_FOUND:
2708                    captions = self._get_plotpanel_captions()
2709                    # Append nummber
2710                    inc = 1
2711                    while (1):
2712                        caption = new_caption + '_%s'% str(inc)
2713                        if caption not in captions:
2714                            break
2715                        inc += 1
2716                    # notify to users
2717                    msg = "Found Same Title: Added '_%s'"% str(inc)
2718                    wx.PostEvent(self, StatusEvent(status=msg))
2719                # update data_panel cb
2720                pos = data_panel.cb_plotpanel.FindString(str(old_caption)) 
2721                if pos != wx.NOT_FOUND:
2722                    data_panel.cb_plotpanel.SetString(pos, caption)
2723                    data_panel.cb_plotpanel.SetStringSelection(caption)
2724        # update window Show menu
2725        if self._window_menu != None:
2726            for item in self._window_menu.GetMenuItems():
2727                pos = self._window_menu.FindItem(old_caption)
2728                if self._window_menu.GetLabel(pos) == str(old_caption):
2729                    self._window_menu.SetLabel(pos, caption)
2730                break
2731        # New Caption
2732        pane_info.Caption(caption)
2733        # update aui manager
2734        self._mgr.Update()
2735        return caption
2736       
2737    def get_paneinfo(self, name):
2738        """
2739        Get pane Caption from window_name
2740       
2741        :param name: window_name in AuiPaneInfo
2742        : return: AuiPaneInfo of the name
2743        """
2744        return self._mgr.GetPane(name) 
2745   
2746    def enable_undo(self):
2747        """
2748        enable undo related control
2749        """
2750        if self.cpanel_on_focus is not None:
2751            self._toolbar.enable_undo(self.cpanel_on_focus)
2752           
2753    def enable_redo(self):
2754        """
2755        enable redo
2756        """
2757        if self.cpanel_on_focus is not None:
2758            self._toolbar.enable_redo(self.cpanel_on_focus)
2759           
2760    def enable_copy(self):
2761        """
2762        enable copy related control
2763        """
2764        if self.cpanel_on_focus is not None:
2765            self._toolbar.enable_copy(self.cpanel_on_focus)
2766           
2767    def enable_paste(self):
2768        """
2769        enable paste
2770        """
2771        if self.cpanel_on_focus is not None:
2772            self._toolbar.enable_paste(self.cpanel_on_focus)
2773                       
2774    def enable_bookmark(self):
2775        """
2776        Bookmark
2777        """
2778        if self.cpanel_on_focus is not None:
2779            self._toolbar.enable_bookmark(self.cpanel_on_focus)
2780           
2781    def enable_save(self):
2782        """
2783        save
2784        """
2785        if self.cpanel_on_focus is not None:
2786            self._toolbar.enable_save(self.cpanel_on_focus)
2787           
2788    def enable_preview(self):
2789        """
2790        preview
2791        """
2792        if self.cpanel_on_focus is not None:
2793            self._toolbar.enable_preview(self.cpanel_on_focus)
2794           
2795    def enable_print(self):
2796        """
2797        print
2798        """
2799        if self.cpanel_on_focus is not None:
2800            self._toolbar.enable_print(self.cpanel_on_focus)
2801           
2802    def enable_zoom(self):
2803        """
2804        zoom
2805        """
2806        if self.cpanel_on_focus is not None:
2807            self._toolbar.enable_zoom(self.panel_on_focus)
2808           
2809    def enable_zoom_in(self):
2810        """
2811        zoom in
2812        """
2813        if self.cpanel_on_focus is not None:
2814            self._toolbar.enable_zoom_in(self.panel_on_focus)
2815           
2816    def enable_zoom_out(self):
2817        """
2818        zoom out
2819        """
2820        if self.cpanel_on_focus is not None:
2821            self._toolbar.enable_zoom_out(self.panel_on_focus)
2822           
2823    def enable_drag(self, event=None):
2824        """
2825        drag
2826        """
2827        if self.cpanel_on_focus is not None:
2828            self._toolbar.enable_drag(self.panel_on_focus)
2829           
2830    def enable_reset(self):
2831        """
2832        reset the current panel
2833        """
2834        if self.cpanel_on_focus is not None:
2835            self._toolbar.enable_reset(self.panel_on_focus)
2836
2837    def set_schedule_full_draw(self, panel=None, func='del'):
2838        """
2839        Add/subtract the schedule full draw list with the panel given
2840       
2841        :param panel: plot panel
2842        :param func: append or del [string]
2843        """
2844
2845        # append this panel in the schedule list if not in yet
2846        if func == 'append':
2847            if not panel in self.schedule_full_draw_list:
2848                self.schedule_full_draw_list.append(panel) 
2849        # remove this panel from schedule list
2850        elif func == 'del':
2851            if len(self.schedule_full_draw_list) > 0:
2852                if panel in self.schedule_full_draw_list:
2853                    self.schedule_full_draw_list.remove(panel)
2854
2855        # reset the schdule
2856        if len(self.schedule_full_draw_list) == 0:
2857            self.schedule = False
2858        else:
2859            self.schedule = True   
2860       
2861    def full_draw(self):
2862        """
2863        Draw the panels with axes in the schedule to full dwar list
2864        """
2865        count = len(self.schedule_full_draw_list)
2866        #if not self.schedule:
2867        if count < 1:
2868            self.set_schedule(False)
2869            return
2870        else:
2871            ind = 0
2872            # if any of the panel is shown do full_draw
2873            for panel in self.schedule_full_draw_list:
2874                ind += 1
2875                if self._mgr.GetPane(panel.window_name).IsShown():
2876                    break
2877                # otherwise, return
2878                if ind == count:
2879                    return
2880
2881        #Simple redraw only for a panel shown
2882        def f_draw(panel):
2883            """
2884            Draw A panel in the full dwar list
2885            """
2886            try:
2887                # This checking of GetCapture is to stop redrawing
2888                # while any panel is capture.
2889                if self.GetCapture() == None:
2890                    # draw if possible
2891                    panel.set_resizing(False)
2892                    panel.Show(False)
2893                    panel.draw_plot()
2894                   
2895                    # Check if the panel is not shown
2896                    if not self._mgr.GetPane(panel.window_name).IsShown():
2897                        self._mgr.GetPane(panel.window_name).Hide()
2898                    else:
2899                        panel.Show(True)
2900            except:
2901                pass
2902       
2903        # Draw all panels       
2904        map(f_draw, self.schedule_full_draw_list)
2905       
2906        # Reset the attr 
2907        if len(self.schedule_full_draw_list) == 0:
2908            self.set_schedule(False)
2909        else:
2910            self.set_schedule(True)
2911        # do not update mgr
2912        #self._mgr.Update()
2913       
2914    def set_schedule(self, schedule=False): 
2915        """
2916        Set schedule
2917        """
2918        self.schedule = schedule
2919               
2920    def get_schedule(self): 
2921        """
2922        Get schedule
2923        """
2924        return self.schedule
2925   
2926    def on_set_plot_focus(self, panel):
2927        """
2928        Set focus on a plot panel
2929        """
2930        self.set_plot_unfocus()
2931        panel.on_set_focus(None) 
2932        # set focusing panel
2933        self.panel_on_focus = panel 
2934        self.set_panel_on_focus(None)
2935
2936    def set_plot_unfocus(self): 
2937        """
2938        Un focus all plot panels
2939        """
2940        for plot in self.plot_panels.values():
2941            plot.on_kill_focus(None)
2942
2943    def _onDrawIdle(self, *args, **kwargs):
2944        """
2945        ReDraw with axes
2946        """
2947        try:
2948            # check if it is time to redraw
2949            if self.GetCapture() == None:
2950                # Draw plot, changes resizing too
2951                self.full_draw()
2952        except:
2953            pass
2954           
2955        # restart idle       
2956        self._redraw_idle(*args, **kwargs)
2957
2958           
2959    def _redraw_idle(self, *args, **kwargs):
2960        """
2961        Restart Idle
2962        """
2963        # restart idle   
2964        self.idletimer.Restart(55*TIME_FACTOR, *args, **kwargs)
2965
2966       
2967class DefaultPanel(wx.Panel, PanelBase):
2968    """
2969    Defines the API for a panels to work with
2970    the GUI manager
2971    """
2972    ## Internal nickname for the window, used by the AUI manager
2973    window_name = "default"
2974    ## Name to appear on the window title bar
2975    window_caption = "Welcome panel"
2976    ## Flag to tell the AUI manager to put this panel in the center pane
2977    CENTER_PANE = True
2978    def __init__(self, parent, *args, **kwds):
2979        wx.Panel.__init__(self, parent, *args, **kwds)
2980        PanelBase.__init__(self, parent)
2981   
2982
2983
2984# Toy application to test this Frame
2985class ViewApp(wx.App):
2986    """
2987    """
2988    def OnInit(self):
2989        """
2990        """
2991        pos, size = self.window_placement((GUIFRAME_WIDTH, GUIFRAME_HEIGHT))
2992        self.frame = ViewerFrame(parent=None, 
2993                                 title=APPLICATION_NAME, 
2994                                 pos=pos, 
2995                                 gui_style = DEFAULT_STYLE,
2996                                 size=size) 
2997        self.frame.Hide()
2998        self.s_screen = None
2999        temp_path = None
3000        try:
3001            _change_current_dir()
3002        except:
3003            pass
3004        try:
3005            self.open_file()
3006        except:
3007            msg = "%s Could not load " % str(APPLICATION_NAME)
3008            msg += "input file from command line.\n"
3009            logging.error(msg)
3010        # Display a splash screen on top of the frame.
3011        if len(sys.argv) > 1 and '--time' in sys.argv[1:]:
3012            log_time("Starting to display the splash screen")
3013        try:
3014            if os.path.isfile(SPLASH_SCREEN_PATH):
3015                self.s_screen = self.display_splash_screen(parent=self.frame, 
3016                                        path=SPLASH_SCREEN_PATH)
3017            else:
3018                self.frame.Show()   
3019        except:
3020            if self.s_screen is not None:
3021                self.s_screen.Close()
3022            msg = "Cannot display splash screen\n"
3023            msg += str (sys.exc_value)
3024            logging.error(msg)
3025            self.frame.Show()
3026 
3027        if hasattr(self.frame, 'special'):
3028            self.frame.special.SetCurrent()
3029        self.SetTopWindow(self.frame)
3030 
3031        return True
3032
3033    def open_file(self):
3034        """
3035        open a state file at the start of the application
3036        """
3037        input_file = None
3038        if len(sys.argv) >= 2:
3039            cmd = sys.argv[0].lower()
3040            basename  = os.path.basename(cmd)
3041            app_base = str(APPLICATION_NAME).lower()
3042            if os.path.isfile(cmd) or basename.lower() == app_base:
3043                app_py = app_base + '.py'
3044                app_exe = app_base + '.exe'
3045                app_app = app_base + '.app'
3046                if basename.lower() in [app_py, app_exe, app_app, app_base]:
3047                    data_base = sys.argv[1]
3048                    input_file = os.path.normpath(os.path.join(DATAPATH, 
3049                                                               data_base))
3050        if input_file is None:
3051            return
3052        if self.frame is not None:
3053            self.frame.set_input_file(input_file=input_file)
3054         
3055           
3056    def set_manager(self, manager):
3057        """
3058        Sets a reference to the application manager
3059        of the GUI manager (Frame)
3060        """
3061        self.frame.set_manager(manager)
3062       
3063    def build_gui(self):
3064        """
3065        Build the GUI
3066        """
3067        #try to load file at the start
3068        try:
3069            self.open_file()
3070        except:
3071            raise
3072        self.frame.build_gui()
3073        #if self.s_screen is not None and self.s_screen.IsShown():
3074        #    self.s_screen.Close()
3075       
3076    def set_welcome_panel(self, panel_class):
3077        """
3078        Set the welcome panel
3079       
3080        :param panel_class: class of the welcome panel to be instantiated
3081       
3082        """
3083        self.frame.set_welcome_panel(panel_class)
3084       
3085    def add_perspective(self, perspective):
3086        """
3087        Manually add a perspective to the application GUI
3088        """
3089        self.frame.add_perspective(perspective)
3090   
3091    def window_placement(self, size):
3092        """
3093        Determines the position and size of the application frame such that it
3094        fits on the user's screen without obstructing (or being obstructed by)
3095        the Windows task bar.  The maximum initial size in pixels is bounded by
3096        WIDTH x HEIGHT.  For most monitors, the application
3097        will be centered on the screen; for very large monitors it will be
3098        placed on the left side of the screen.
3099        """
3100        window_width, window_height = size
3101        screen_size = wx.GetDisplaySize()
3102        window_height = window_height if screen_size[1]>window_height else screen_size[1]-10
3103        window_width  = window_width if screen_size[0]> window_width else screen_size[0]-10
3104        xpos = ypos = 0
3105
3106        # Note that when running Linux and using an Xming (X11) server on a PC
3107        # with a dual  monitor configuration, the reported display size may be
3108        # that of both monitors combined with an incorrect display count of 1.
3109        # To avoid displaying this app across both monitors, we check for
3110        # screen 'too big'.  If so, we assume a smaller width which means the
3111        # application will be placed towards the left hand side of the screen.
3112
3113        _, _, x, y = wx.Display().GetClientArea() # size excludes task bar
3114        if len(sys.argv) > 1 and '--platform' in sys.argv[1:]:
3115            w, h = wx.DisplaySize()  # size includes task bar area
3116        # display on left side, not centered on screen
3117        if x > 1920 and x > (2*y): x = x / 2 
3118        if x > window_width:  xpos = (x - window_width)/2
3119        if y > window_height: ypos = (y - window_height)/2
3120
3121        # Return the suggested position and size for the application frame.
3122        return (xpos, ypos), (min(x, window_width), min(y, window_height))
3123   
3124    def display_splash_screen(self, parent, 
3125                              path=SPLASH_SCREEN_PATH):
3126        """Displays the splash screen.  It will exactly cover the main frame."""
3127       
3128        # Prepare the picture.  On a 2GHz intel cpu, this takes about a second.
3129        x, y = parent.GetSizeTuple()
3130        image = wx.Image(path, wx.BITMAP_TYPE_PNG)
3131        image.Rescale(SPLASH_SCREEN_WIDTH, 
3132                      SPLASH_SCREEN_HEIGHT, wx.IMAGE_QUALITY_HIGH)
3133        bm = image.ConvertToBitmap()
3134
3135        # Create and show the splash screen.  It will disappear only when the
3136        # program has entered the event loop AND either the timeout has expired
3137        # or the user has left clicked on the screen.  Thus any processing
3138        # performed in this routine (including sleeping) or processing in the
3139        # calling routine (including doing imports) will prevent the splash
3140        # screen from disappearing.
3141        #
3142        # Note that on Linux, the timeout appears to occur immediately in which
3143        # case the splash screen disappears upon entering the event loop.
3144        s_screen = wx.SplashScreen(bitmap=bm,
3145                         splashStyle=(wx.SPLASH_TIMEOUT|
3146                                              wx.SPLASH_CENTRE_ON_SCREEN),
3147                                 style=(wx.SIMPLE_BORDER|
3148                                        wx.FRAME_NO_TASKBAR|
3149                                        wx.STAY_ON_TOP),
3150                                       
3151                        milliseconds=SS_MAX_DISPLAY_TIME,
3152                        parent=parent,
3153                        id=wx.ID_ANY)
3154        from gui_statusbar import SPageStatusbar
3155        statusBar = SPageStatusbar(s_screen)
3156        s_screen.SetStatusBar(statusBar)
3157        s_screen.Bind(wx.EVT_CLOSE, self.on_close_splash_screen)
3158        s_screen.Show()
3159        return s_screen
3160       
3161       
3162    def on_close_splash_screen(self, event):
3163        """
3164        """
3165        self.frame.Show(True)
3166        event.Skip()
3167     
3168if __name__ == "__main__": 
3169    app = ViewApp(0)
3170    app.MainLoop()
3171
3172             
Note: See TracBrowser for help on using the repository browser.