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

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

fixed an error that the 2Dmodel panel was not completely removed after deleting the data (broken 2D panel)

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