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

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 e89c135 was d03a356, checked in by Gervaise Alina <gervyh@…>, 13 years ago

working on data processor

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