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

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

Adde close/show all plotpanels

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