source: sasview/sansguiframe/src/sans/guiframe/gui_manager.py @ 4d9bce0

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

added separator in the front of the pyconsole

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