Ignore:
Timestamp:
Jul 16, 2010 9:24:21 AM (14 years ago)
Author:
Jae Cho <jhjcho@…>
Branches:
master, ESS_GUI, ESS_GUI_Docs, ESS_GUI_batch_fitting, ESS_GUI_bumps_abstraction, ESS_GUI_iss1116, ESS_GUI_iss879, ESS_GUI_iss959, ESS_GUI_opencl, ESS_GUI_ordering, ESS_GUI_sync_sascalc, costrafo411, magnetic_scatt, release-4.1.1, release-4.1.2, release-4.2.2, release_4.0.1, ticket-1009, ticket-1094-headless, ticket-1242-2d-resolution, ticket-1243, ticket-1249, ticket885, unittest-saveload
Children:
b5a21aa
Parents:
855546d
Message:

Invariant: undo, redo, bookmark, and saving works now: needs plottool fix for making right order on plotting from file: also need some cleaning-up and doc.

Location:
invariantview/perspectives/invariant
Files:
1 added
3 edited

Legend:

Unmodified
Added
Removed
  • invariantview/perspectives/invariant/invariant.py

    rd7a39e5 r4e1c362  
    1111#copyright 2009, University of Tennessee 
    1212################################################################################ 
    13  
     13import os 
     14import sys 
    1415import wx 
    15  
     16import copy 
     17import logging, time 
    1618from sans.invariant import invariant 
    1719 
     
    2123from sans.guicomm.events import NewPlotEvent, StatusEvent 
    2224from sans.guicomm.events import ERR_DATA 
     25from invariant_state import Reader as reader 
     26from DataLoader.loader import Loader 
     27from invariant_panel import InvariantPanel 
    2328 
    2429class Plugin: 
    2530    """ 
    2631    This class defines the interface for invariant Plugin class 
    27     that can be used by the gui_manager. 
    28           
     32    that can be used by the gui_manager.        
    2933    """ 
    3034     
     
    4347        #  for your plug-in. This defines your plug-in "perspective" 
    4448        self.perspective = [] 
     49         
     50        self.state_reader = None    
     51        """ 
     52        # Create a CanSAS/Pr reader 
     53        self.state_reader = Reader(self.set_state) 
     54        l = Loader() 
     55        l.associate_file_reader('.inv', self.state_reader)   
     56        """    
     57        # Log startup 
     58        logging.info("Invariant plug-in started") 
    4559        
    4660    def populate_menu(self, id, parent): 
     
    5367         
    5468        :return: plug-in menu 
    55          
    5669        """ 
    5770        return [] 
     
    6073        """ 
    6174        Show a general help dialog.  
    62      
    6375        """ 
    6476        from help_panel import  HelpWindow 
     
    7890         
    7991        :return: list of panels 
    80          
    8192        """ 
    8293        ## Save a reference to the parent 
     
    8495        #add error back to the data 
    8596        self.parent.Bind(ERR_DATA, self._on_data_error) 
    86         from invariant_panel import InvariantPanel 
     97         
     98         
    8799        self.invariant_panel = InvariantPanel(parent=self.parent) 
    88100        self.invariant_panel.set_manager(manager=self) 
    89         self.perspective.append(self.invariant_panel.window_name)    
     101        self.perspective.append(self.invariant_panel.window_name)   
     102        #Create reader when fitting panel are created 
     103        self.state_reader = reader(self.set_state)    
     104        #append that reader to list of available reader  
     105        loader = Loader() 
     106        loader.associate_file_reader(".inv", self.state_reader) 
    90107        # Return the list of panels 
    91108        return [self.invariant_panel] 
     
    118135         
    119136        :return: a list of menu items with call-back function 
    120          
    121137        """ 
    122138        self.graph = graph 
     
    148164         
    149165        :param event: menu event 
    150          
    151166        """ 
    152167        self.parent.set_perspective(self.perspective) 
     
    171186        receive a data 1D and the list of errors on dy 
    172187        and create a new data1D data 
    173          
    174188        """ 
    175189        id = None 
     
    182196        data.dy = dy 
    183197        data.name = item.name 
     198         
    184199        ## allow to highlight data when plotted 
    185200        data.interactive = item.interactive 
     
    217232                # Set the data set to be user for invariant calculation 
    218233                self.invariant_panel.set_data(data=data) 
     234                 
     235    def save_file(self, filepath, state=None): 
     236        """ 
     237        Save data in provided state object. 
     238                 
     239        :param filepath: path of file to write to 
     240        :param state: invariant state  
     241        """      
     242         
     243        # Write the state to file 
     244        # First, check that the data is of the right type 
     245 
     246        current_plottable = self.__data 
     247 
     248        if issubclass(current_plottable.__class__, LoaderData1D): 
     249            self.state_reader.write(filepath, current_plottable, state) 
     250        else: 
     251            raise RuntimeError, "invariant.save_file: the data being saved is not a DataLoader.data_info.Data1D object"  
     252 
     253    def set_state(self, state, datainfo=None):     
     254        """ 
     255        Call-back method for the state reader. 
     256        This method is called when a .inv file is loaded. 
     257         
     258        :param state: State object 
     259        """ 
     260         
     261        try: 
     262            if datainfo is None: 
     263                raise RuntimeError, "invariant.set_state: datainfo parameter cannot be None in standalone mode" 
     264            datainfo.meta_data['invstate'].file = datainfo.meta_data['invstate'].file+"_copy" 
     265            datainfo.name = datainfo.meta_data['invstate'].file 
     266            datainfo.filename = datainfo.meta_data['invstate'].file 
     267            self.__data = datainfo 
     268            self.__data.group_id = datainfo.filename 
     269            self.__data.id = datainfo.filename 
     270 
     271            temp_state = copy.deepcopy(state) 
     272             
     273            # Load the invariant states 
     274            # Make sure the user sees the invariant panel after loading 
     275            self.parent.set_perspective(self.perspective) 
     276 
     277            # set state 
     278            self.invariant_panel.set_state(state=temp_state,data=self.__data)                 
     279 
     280        except: 
     281            logging.error("invariant.set_state: %s" % sys.exc_value) 
     282         
     283     
    219284         
    220285    def plot_theory(self, data=None, name=None): 
     
    224289        :param data: extrapolated data to be plotted 
    225290        :param name: Data's name to use for the legend 
    226          
    227         """ 
     291        """ 
     292        import copy 
    228293        if data is None: 
    229294            new_plot = Theory1D(x=[], y=[], dy=None) 
     
    245310        new_plot.group_id = self.__data.group_id 
    246311        new_plot.id = self.__data.id + name 
     312        # Save theory_data in a state 
     313        if data != None: 
     314            name_head = name.split('-') 
     315            if name_head[0]=='Low': 
     316                self.invariant_panel.state.theory_lowQ = copy.deepcopy(new_plot) 
     317            elif name_head[0]=='High': 
     318                self.invariant_panel.state.theory_highQ = copy.deepcopy(new_plot) 
     319 
    247320        wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot, title=self.__data.name)) 
    248321         
     
    255328        new_plot.group_id = self.__data.group_id 
    256329        new_plot.id = self.__data.id  
     330        
     331        # Save data in a state: but seems to never happen  
     332        if new_plot != None: 
     333            self.invariant_panel.state.data = copy.deepcopy(new_plot) 
    257334        wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot, title=new_plot.name)) 
    258335         
  • invariantview/perspectives/invariant/invariant_panel.py

    r90b9a17 r4e1c362  
    66import wx 
    77 
    8 import sys 
     8import sys,os 
    99from wx.lib.scrolledpanel import ScrolledPanel 
    1010from sans.invariant import invariant 
     
    1313from invariant_details import InvariantDetailsPanel, InvariantContainer 
    1414from invariant_widgets import OutputTextCtrl, InvTextCtrl 
    15  
     15from invariant_state import InvariantState as IState 
     16import copy,time 
    1617# The minimum q-value to be used when extrapolating 
    1718Q_MINIMUM  = 1e-5 
     
    3233#Invariant panel size  
    3334_BOX_WIDTH = 76 
     35 
    3436 
    3537if sys.platform.count("win32")>0: 
     
    7072        self._scale = SCALE  
    7173        self._background = BACKGROUND 
    72  
     74        self._bmark = None 
     75        self.bookmark_num = 0 
     76         
     77        self._set_bookmark_menu() 
     78        #Init state 
     79        self.set_state() 
     80        # default flags for state 
     81        self.new_state = False 
     82        self.is_power_out = False 
     83         
    7384        #container of invariant value 
    7485        self.inv_container = None 
     
    7687        self._do_layout() 
    7788        self.reset_panel() 
     89        self._reset_state_list() 
     90         
    7891        if self.parent is not None: 
    7992            msg = "" 
    8093            wx.PostEvent(self.parent,StatusEvent(status=msg, info="info")) 
    81  
     94             
     95        ## Default file location for save 
     96        self._default_save_location = os.getcwd() 
     97  
    8298    def err_check_on_data(self): 
    8399        """ 
     
    100116        """ 
    101117        Set the data 
    102         """ 
     118         
     119        : return: True/False; if False, it will not set_data 
     120        """ 
     121        # warn the users 
     122        if self._data != None and data != None: 
     123            if not self._show_message(): 
     124                return False 
     125             
    103126        self._data = data 
     127        # reset popUpMenu 
     128        self._set_bookmark_menu() 
    104129        #edit the panel 
    105130        if self._data is not None: 
     131             
    106132            self.err_check_on_data() 
     133            self.get_state_by_num(0) 
    107134            data_name = self._data.name 
    108135            data_qmin = min (self._data.x) 
    109136            data_qmax = max (self._data.x) 
    110             self.data_name_tcl.SetValue(str(data_name)) 
     137            self.data_name_tcl.SetValue(str(data_name))       
    111138            self.data_min_tcl.SetLabel(str(data_qmin)) 
    112139            self.data_max_tcl.SetLabel(str(data_qmax)) 
     140            self.button_save.Enable(True)   
    113141            self.reset_panel() 
    114142            self.compute_invariant(event=None) 
    115               
     143            #Reset the list of states 
     144            self.state.data = copy.deepcopy(data) 
     145            self._reset_state_list() 
     146             
     147        return True      
     148 
    116149    def set_message(self): 
    117150        """ 
     
    137170        """ 
    138171        self._manager = manager  
    139      
     172         
     173    def set_state(self,state=None,data=None): 
     174        """ 
     175        set state when loading it from a .inv file 
     176        """ 
     177        if state == None or data == None: 
     178            self.state = IState() 
     179        else: 
     180            if not self.set_data(data): 
     181                return 
     182            self.new_state = True 
     183            self.state = state    
     184 
     185            num = self.state.saved_state['state_num'] 
     186            self.get_state_by_num(state_num=num) 
     187             
     188            if num >0 : 
     189                self._undo_enable() 
     190            if num < len(state.state_list)-1: 
     191                self._redo_enable() 
     192                 
     193             
     194            # get bookmarks 
     195            self.bookmark_num = len(self.state.bookmark_list) 
     196            total_bookmark_num = self.bookmark_num+1 
     197            for ind in range(1,total_bookmark_num): 
     198                #bookmark_num = ind 
     199                value = self.state.bookmark_list[ind] 
     200                name = "%d] bookmarked at %s on %s"% (ind,value[0], value[1]) 
     201                # append it to menu 
     202                id = wx.NewId() 
     203                self.popUpMenu.Append(id,name,str('')) 
     204                wx.EVT_MENU(self, id, self._back_to_bookmark)    
     205            self.new_state = False  
     206 
     207 
    140208    def get_background(self): 
    141209        """ 
     
    272340                wx.PostEvent(self.parent, StatusEvent(status= msg, type="stop")) 
    273341        else: 
    274             self._manager.plot_theory(name="Low-Q extrapolation") 
     342            try: 
     343                self._manager.plot_theory(name="Low-Q extrapolation") 
     344            except: pass 
    275345             
    276346    def get_high_qstar(self, inv, high_q=False): 
     
    296366                wx.PostEvent(self.parent, StatusEvent(status= msg, type="stop")) 
    297367        else: 
    298             self._manager.plot_theory(name="High-Q extrapolation") 
    299              
     368            try: 
     369                self._manager.plot_theory(name="High-Q extrapolation") 
     370            except: pass 
     371 
    300372    def get_qstar(self, inv): 
    301373        """ 
     
    341413                                   function=function_low, power=power_low)     
    342414        return inv, npts_low   
    343          
     415     
     416 
    344417    def set_extrapolation_high(self, inv, high_q=False): 
    345418        """ 
     
    387460        compute invariant  
    388461        """ 
    389         msg= "" 
    390         wx.PostEvent(self.parent, StatusEvent(status=msg)) 
     462        if self._data == None: 
     463            msg = "\n\nData must be loaded first in order to perform a compution..." 
     464            wx.PostEvent(self.parent, StatusEvent(status=msg)) 
     465        # set a state for this computation for saving 
     466        elif event != None:  
     467            self._set_compute_state(state='compute') 
     468            msg= "\n\nStarting a new invariant computation..."             
     469            wx.PostEvent(self.parent, StatusEvent(status=msg)) 
     470 
    391471        if self._data is None or self.err_check_on_data(): 
    392472            return 
    393      
     473         
    394474        #clear outputs textctrl  
    395475        self._reset_output() 
     
    442522        porod_const = self.get_porod_const()         
    443523        contrast = self.get_contrast() 
     524         
    444525        try: 
    445526            #Compute volume and set value to txtcrtl 
     
    453534            self.get_surface(inv=inv, contrast=contrast, porod_const=porod_const,  
    454535                                    extrapolation=extrapolation) 
     536             
    455537        except: 
    456538            msg = "Error occurred computing invariant: %s"%sys.exc_value 
     
    460542        #compute percentage of each invariant 
    461543        self.inv_container.compute_percentage() 
     544         
    462545        #display a message 
    463546        self.set_message() 
     547         
     548        # reset power_out to default to get ready for another '_on_text' 
     549        if self.is_power_out == True: 
     550            self.state.container = copy.deepcopy(self.inv_container) 
     551            self.state.timestamp= self._get_time_stamp() 
     552            msg = self.state.__str__() 
     553            self.is_power_out = False 
     554            wx.PostEvent(self.parent, StatusEvent(status = msg )) 
     555         
    464556        #enable the button_ok for more details 
    465557        self.button_details.Enable() 
     558         
    466559        self.button_details.SetFocus() 
    467          
     560        if event != None:  
     561            wx.PostEvent(self.parent, StatusEvent(status = '\nFinished invariant computation...')) 
     562     
     563    def undo(self,event=None): 
     564        """ 
     565        Go back to the previous state 
     566         
     567        : param event: undo button event 
     568         
     569        """ 
     570        if event != None: event.Skip() 
     571        if self.state.state_num <0: return 
     572        self.is_power_out = True 
     573        # get the previous state_num 
     574        pre_state_num = int(self.state.saved_state['state_num']) - 1 
     575        self.get_state_by_num(state_num=str(pre_state_num)) 
     576         
     577        if float(pre_state_num) <=0: 
     578            self.button_undo.Disable() 
     579        elif not self.button_undo.Enabled: 
     580            self.button_undo.Enable(True) 
     581 
     582        self._redo_enable() 
     583        self.is_power_out = False   
     584        self._info_state_num() 
     585         
     586 
     587         
     588    def redo(self,event=None): 
     589        """ 
     590        Go forward to the previous state 
     591         
     592        : param event: redo button event 
     593         
     594        """ 
     595        if event != None: event.Skip() 
     596        self.is_power_out = True 
     597        next_state_num = int(self.state.saved_state['state_num']) + 1 
     598 
     599        self.get_state_by_num(state_num=str(next_state_num)) 
     600         
     601        if float(next_state_num)+2 > len(self.state.state_list): 
     602            self.button_redo.Disable() 
     603        elif not self.button_redo.Enabled: 
     604            self.button_redo.Enable(True) 
     605         
     606        self._undo_enable() 
     607        self.is_power_out = False 
     608        self._info_state_num() 
     609         
     610    def get_state_by_num(self,state_num=None): 
     611        """ 
     612        Get the state given by number 
     613         
     614        : param state_num: the given state number 
     615         
     616        """ 
     617        
     618        if state_num == None: 
     619            return 
     620 
     621        backup_state_list = copy.deepcopy(self.state.state_list) 
     622 
     623        # get the previous state 
     624        try: 
     625            current_state = copy.deepcopy(self.state.state_list[str(state_num)]) 
     626            # get the previously computed state number (computation before the state changes happened) 
     627            current_compute_num = str(current_state['compute_num']) 
     628        except : 
     629            raise ValueError,  "No such state exists in history" 
     630 
     631        # get the state at pre_compute_num 
     632        comp_state = copy.deepcopy(self.state.state_list[current_compute_num]) 
     633 
     634        # set the parameters 
     635        for key in comp_state: 
     636            value = comp_state[key] 
     637            try: 
     638                exec "self.%s.SetValue(str(%s))" % (key, value) 
     639            except TypeError: 
     640                exec "self.%s.SetValue(%s)" % (key, value) 
     641            except: 
     642                pass 
     643             
     644        self.compute_invariant(event=None) 
     645        # set the input params at the state at pre_state_num 
     646        for key in current_state: 
     647            # Do not reset set some outputs 
     648            #key_split = key.split('_')  
     649            #if key_split[0] == 'surface' or key_split[0] == 'volume': 
     650            #    continue 
     651            # set the inputs and boxes 
     652            value = current_state[key] 
     653 
     654            try: 
     655                exec 'self.%s.SetValue(str(%s))' % (key, value) 
     656            except TypeError: 
     657                exec 'self.%s.SetValue(%s)' % (key, value) 
     658            except: 
     659                pass 
     660 
     661         
     662        self._enable_high_q_section(event=None) 
     663        self._enable_low_q_section(event=None) 
     664        self.state.state_list = backup_state_list 
     665        self.state.saved_state = current_state 
     666        self.state.state_num = state_num 
     667 
     668         
     669    def get_bookmark_by_num(self, num=None): 
     670        """ 
     671        Get the bookmark state given by number 
     672         
     673        : param num: the given bookmark number 
     674         
     675        """ 
     676        current_state = {} 
     677        comp_state = {} 
     678        backup_state_list = copy.deepcopy(self.state.state_list) 
     679 
     680        # get the previous state 
     681        try: 
     682            time,date,current_state,comp_state = self.state.bookmark_list[int(num)]  
     683        except : 
     684            raise ValueError,  "No such bookmark exists" 
     685 
     686        # set the parameters 
     687        for key in comp_state: 
     688            value = comp_state[key] 
     689            try: 
     690                exec "self.%s.SetValue(str(%s))" % (key, value) 
     691            except TypeError: 
     692                exec "self.%s.SetValue(%s)" % (key, value) 
     693            except: 
     694                pass 
     695 
     696        self.compute_invariant(event=None) 
     697        # set the input params at the state of pre_state_num 
     698        for key in current_state: 
     699            value = current_state[key] 
     700            try: 
     701                exec 'self.%s.SetValue(str(%s))' % (key, value) 
     702            except TypeError: 
     703                exec 'self.%s.SetValue(%s)' % (key, value) 
     704            except: 
     705                pass 
     706        self.state.saved_state = copy.deepcopy(current_state) 
     707 
     708        self._enable_high_q_section(event=None) 
     709        self._enable_low_q_section(event=None) 
     710        self.state.state_list = backup_state_list 
     711        #self.state.saved_state = current_state 
     712        #self.state.state_num = state_num 
     713 
    468714    def reset_panel(self): 
    469715        """ 
     
    490736        self._enable_high_q_section() 
    491737        self._reset_output() 
     738        self.button_undo.Disable() 
     739        self.button_redo.Disable() 
    492740        self.button_calculate.SetFocus() 
     741        #self.SetupScrolling() 
     742         
     743    def _set_state(self, event): 
     744        """ 
     745        Set the state list 
     746         
     747        :param event: rb/cb event 
     748         
     749        """ 
     750        if event == None: 
     751            return 
     752        obj = event.GetEventObject() 
     753        name = str(obj.GetName()) 
     754        value = str(obj.GetValue()) 
     755        rb_list = [['power_law_low','guinier'],['fit_enable_low','fix_enable_low'],['fit_enable_high','fix_enable_high']] 
     756 
     757        try: 
     758            if value == None or value.lstrip().rstrip() =='': 
     759                value = 'None' 
     760            exec 'self.state.%s = %s' % (name, value) 
     761            exec "self.state.saved_state['%s'] = %s" %  (name, value) 
     762             
     763            # set the count part of radio button clicked False for the saved_state 
     764            for title,content in rb_list: 
     765                if name ==  title: 
     766                    name = content  
     767                    value = False      
     768                elif name == content: 
     769                    name = title 
     770                    value = False  
     771            exec "self.state.saved_state['%s'] = %s" %  (name, value)      
     772             
     773            # Instead of changing the future, create a new future. 
     774            max_state_num = len(self.state.state_list)-1    
     775            self.state.saved_state['state_num'] = max_state_num    
     776             
     777            self.state.saved_state['state_num'] +=1 
     778            self.state.state_num = self.state.saved_state['state_num'] 
     779            self.state.state_list[str(self.state.state_num)] = self.state.clone_state()#copy.deepcopy(self.state.saved_state) 
     780 
     781        except:            
     782            pass 
     783 
     784        event.Skip() 
     785        self._undo_enable() 
     786        self._redo_disable() 
     787             
     788    def _set_compute_state(self,state=None): 
     789        """ 
     790        Notify the compute_invariant state to self.state 
     791         
     792        : param state: set 'compute' when the computation is activated by the 'compute' button, else None 
     793         
     794        """ 
     795        # reset the default 
     796        if state != 'compute': 
     797            self.new_state = False 
     798            self.is_power_out = False 
     799        else: 
     800            self.is_power_out = True 
     801        # Instead of changing the future, create a new future. 
     802        max_state_num = len(self.state.state_list)-1    
     803        self.state.saved_state['state_num'] = max_state_num         
     804        # A new computation is also A state 
     805        temp_saved_states = self.state.clone_state()#copy.deepcopy(self.state.saved_state) 
     806        temp_saved_states['state_num'] +=1 
     807        self.state.state_num = temp_saved_states['state_num'] 
     808 
     809                 
     810        # set the state number of the computation  
     811        if state == 'compute': 
     812            temp_saved_states['compute_num'] = self.state.state_num 
     813        self.state.saved_state= copy.deepcopy(temp_saved_states) 
     814        self.state.state_list[str(self.state.state_num)] = self.state.clone_state()#copy.deepcopy(self.state.saved_state) 
     815         
     816        # A computation is a new state, so delete the states with any higher state numbers 
     817        for i in range(self.state.state_num+1,len(self.state.state_list)): 
     818            try: 
     819                del (self.state.state_list[str(i)]) 
     820            except:  
     821                pass 
     822        # Enable the undo button if it was not 
     823        self._undo_enable() 
     824        self._redo_disable() 
     825         
     826    def _reset_state_list(self,data=None): 
     827        """ 
     828        Reset the state_list just before data was loading: Used in 'set_data()' 
     829        """ 
     830        #if data == None: return 
     831        #temp_state = self.state.clone_state()#copy.deepcopy(self.state.saved_state) 
     832        # Clear the list  
     833        self.state.state_list.clear() 
     834        self.state.bookmark_list.clear() 
     835        # Set defaults 
     836        self.state.saved_state['state_num'] = 0 
     837        self.state.saved_state['compute_num'] = 0 
     838        if self._data != None: 
     839            self.state.saved_state['file'] = str(self._data.name) 
     840        else: 
     841            self.state.saved_state['file'] = 'None' 
     842        self.state.file = self.state.saved_state['file'] 
     843 
     844        self.state.state_num = self.state.saved_state['state_num'] 
     845        # Put only the current state in the list 
     846        self.state.state_list[str(self.state.state_num)] = self.state.clone_state()#copy.deepcopy(self.state.saved_state) 
     847        self._undo_disable() 
     848         
     849    def _on_text(self, event): 
     850        """ 
     851        Catch text change event to add the state to the state_list 
     852         
     853        :param event: txtctr event ; assumes not None 
     854         
     855        """ 
     856        if self._data == None:  
     857            return 
     858        # check if this event is from do/undo button 
     859        if self.state.saved_state['is_time_machine'] or self.new_state: 
     860            event.Skip() 
     861            return 
     862         
     863        # get the object 
     864        obj = event.GetEventObject() 
     865        name = str(obj.GetName()) 
     866        value = str(obj.GetValue()) 
     867        state_num = self.state.saved_state['state_num'] 
     868 
     869        # text event is a new state, so delete the states with higher state_num 
     870        # i.e., change the future 
     871        for i in range(int(state_num)+1,len(self.state.state_list)): 
     872            try: 
     873                del (self.state.state_list[str(i)]) 
     874            except:  
     875                pass 
     876         
     877        # Instead of changing the future, create a new future. 
     878        #max_state_num = len(self.state.state_list)-1    
     879        #self.state.saved_state['state_num'] = max_state_num 
     880 
     881        # try to add new state of the text changes in the state_list 
     882        try: 
     883            if value.strip() == None: value = '' 
     884            exec "self.state.%s = '%s'" % (name, value) 
     885            exec "self.state.saved_state['%s'] = '%s'" %  (name, value) 
     886            exec "self.state.input_list['%s'] = '%s'" % (name, value) 
     887            if not self.is_power_out: 
     888                if name != 'power_low_tcl' and name !='power_high_tcl': 
     889                    self.state.saved_state['state_num'] += 1 
     890            self.state.state_num = self.state.saved_state['state_num'] 
     891            self.state.state_list[str(self.state.state_num)] = self.state.clone_state()#copy.deepcopy(self.state.saved_state) 
     892        except: 
     893            pass 
     894 
     895        event.Skip() 
     896        self._undo_enable() 
     897        self._redo_disable() 
     898         
     899    def _on_out_text(self, event):      
     900        """ 
     901        Catch ouput text change to add the state  
     902         
     903        :param event: txtctr event ; assumes not None 
     904         
     905        """     
     906        # get the object 
     907        obj = event.GetEventObject() 
     908        name = str(obj.GetName()) 
     909        value = str(obj.GetValue()) 
     910        try: 
     911            exec "self.state.saved_state['%s'] = '%s'" %  (name, value) 
     912            self.state.state_list[str(self.state.state_num)] = self.state.clone_state() 
     913        except: 
     914            pass 
     915        if event != None: event.Skip()\ 
     916         
     917    def _set_bookmark_menu(self): 
     918        """ 
     919        Setup 'bookmark' context menu 
     920        """ 
     921        ## Create context menu for page 
     922        self.popUpMenu = wx.Menu() 
     923        id = wx.NewId() 
     924        self._bmark = wx.MenuItem(self.popUpMenu,id,"BookMark"," Bookmark the panel to recall it later") 
     925        self.popUpMenu.AppendItem(self._bmark) 
     926        self._bmark.Enable(True) 
     927        wx.EVT_MENU(self, id, self._on_bookmark) 
     928        self.popUpMenu.AppendSeparator() 
     929        self.Bind(wx.EVT_CONTEXT_MENU, self._on_context_menu) 
     930         
     931    def _on_bookmark(self,event): 
     932        """ 
     933        Save the panel state in memory and add the list on the popup menu on bookmark context menu event 
     934        """  
     935        if self._data == None: return 
     936        if event == None: return 
     937        self.bookmark_num += 1 
     938        # date and time of the event 
     939        #year, month, day,hour,minute,second,tda,ty,tm_isdst= time.localtime() 
     940        #my_time= str(hour)+" : "+str(minute)+" : "+str(second)+" " 
     941        #date= str( month)+"/"+str(day)+"/"+str(year) 
     942        my_time, date = self._get_time_stamp() 
     943        state_num = self.state.state_num 
     944        compute_num = self.state.saved_state['compute_num'] 
     945        # name and message of the bookmark list 
     946        msg=  "State saved at %s on %s"%(my_time, date) 
     947         ## post help message for the selected model  
     948        msg +=" Saved! right click on this page to retrieve this model" 
     949        #wx.PostEvent(self.parent.parent, StatusEvent(status = msg )) 
     950        name = "%d] bookmarked at %s on %s"%(self.bookmark_num,my_time, date) 
     951         
     952        # append it to menu 
     953        id = wx.NewId() 
     954        self.popUpMenu.Append(id,name,str(msg)) 
     955        wx.EVT_MENU(self, id, self._back_to_bookmark ) 
     956        state = self.state.clone_state() 
     957        comp_state = copy.deepcopy(self.state.state_list[str(compute_num)]) 
     958        self.state.bookmark_list[self.bookmark_num] = [my_time,date,state,comp_state] 
     959        self.state.toXML(self, doc=None, entry_node=None) 
     960 
     961    def _back_to_bookmark(self,event): 
     962        """ 
     963        Bring the panel back to the state of bookmarked requested by context menu event 
     964        and set it as a new state 
     965        """ 
     966        ## post help message for the selected model  
     967        msg = self.popUpMenu.GetHelpString(event.GetId()) 
     968        msg +=" reloaded" 
     969        wx.PostEvent(self.parent, StatusEvent(status = msg )) 
     970         
     971        name= self.popUpMenu.GetLabel(event.GetId()) 
     972        num,time = name.split(']') 
     973        current_state_num = self.state.state_num   
     974        self.get_bookmark_by_num(num) 
     975        state_num = int(current_state_num)+1 
     976         
     977        self.state.saved_state['state_num'] = state_num 
     978        self.state.state_list[str(state_num)] = self.state.clone_state()#copy.deepcopy(self.state.saved_state) 
     979        self.state.state_num = state_num 
     980        self._undo_enable() 
     981        self._info_bookmark_num(event) 
     982         
     983    def _info_bookmark_num(self,event=None): 
     984        """ 
     985        print the bookmark number in info 
     986         
     987        : event: popUpMenu event 
     988        """ 
     989        if event == None: return 
     990        # get the object 
     991        item = self.popUpMenu.FindItemById(event.GetId()) 
     992        text = item.GetText() 
     993        num = text.split(']')[0] 
     994        msg = "bookmark num = %s "% num 
     995         
     996        wx.PostEvent(self.parent, StatusEvent(status = msg )) 
     997         
     998    def _info_state_num(self): 
     999        """ 
     1000        print the current state number in info 
     1001        """ 
     1002        msg = "state num = " 
     1003        msg += self.state.state_num 
     1004         
     1005        wx.PostEvent(self.parent, StatusEvent(status = msg)) 
     1006                          
     1007    def _get_time_stamp(self): 
     1008        """ 
     1009        return time and date stings 
     1010        """ 
     1011        # date and time  
     1012        year, month, day,hour,minute,second,tda,ty,tm_isdst= time.localtime() 
     1013        my_time= str(hour)+":"+str(minute)+":"+str(second) 
     1014        date= str( month)+"/"+str(day)+"/"+str(year) 
     1015        return my_time, date 
     1016     
     1017    def _undo_enable(self): 
     1018        """ 
     1019        Enable undo button 
     1020        """ 
     1021        if not self.button_undo.IsEnabled(): 
     1022            self.button_undo.Enable(True) 
     1023 
     1024    def _undo_disable(self): 
     1025        """ 
     1026        Disable undo button 
     1027        """ 
     1028        if self.button_undo.IsEnabled(): 
     1029            self.button_undo.Disable() 
     1030 
     1031    def _redo_enable(self): 
     1032        """ 
     1033        Enable redo button 
     1034        """ 
     1035        if not self.button_redo.IsEnabled(): 
     1036            self.button_redo.Enable(True) 
     1037 
     1038    def _redo_disable(self): 
     1039        """ 
     1040        Disable redo button 
     1041        """ 
     1042        if self.button_redo.IsEnabled(): 
     1043            self.button_redo.Disable() 
     1044             
     1045    def _on_save_button(self, evt=None):  
     1046        """ 
     1047        Save invariant state into a file 
     1048        """ 
     1049        # Ask the user the location of the file to write to. 
     1050        path = None 
     1051        dlg = wx.FileDialog(self, "Choose a file", self._default_save_location, "", "*.inv", wx.SAVE) 
     1052        if dlg.ShowModal() == wx.ID_OK: 
     1053            path = dlg.GetPath() 
     1054            self._default_save_location = os.path.dirname(path) 
     1055        else: 
     1056            return None 
     1057         
     1058        dlg.Destroy() 
     1059         
     1060        self._manager.save_file(filepath=path, state=self.state) 
     1061         
     1062    def _show_message(self, mssg='',msg='Warning'): 
     1063        """ 
     1064        Show warning message when resetting data 
     1065        """ 
     1066         
     1067        mssg += 'Loading a new data set will reset all the work done in this panel. \n\r' 
     1068        mssg += 'Please make sure to save it first... \n\r' 
     1069        answer = wx.MessageBox(mssg, msg, wx.CANCEL|wx.OK|wx.ICON_EXCLAMATION) 
     1070 
     1071        if answer == wx.OK: 
     1072            return True 
     1073        else: 
     1074            return False 
    4931075         
    4941076    def _reset_output(self): 
     
    5041086        #prepare a new container to put result of invariant 
    5051087        self.inv_container = InvariantContainer() 
     1088 
     1089     
     1090    def _on_context_menu(self,event): 
     1091         
     1092        pos = event.GetPosition() 
     1093        pos = self.ScreenToClient(pos) 
    5061094        
     1095        self.PopupMenu(self.popUpMenu, pos)  
     1096       
    5071097    def _define_structure(self): 
    5081098        """ 
     
    5501140        #Sizer related to button 
    5511141        self.button_sizer = wx.BoxSizer(wx.HORIZONTAL) 
    552         
     1142        #Sizer related to save button 
     1143        self.save_button_sizer = wx.BoxSizer(wx.HORIZONTAL) 
     1144         
    5531145    def _layout_data_name(self): 
    5541146        """ 
     
    5571149        #Sizer hint  
    5581150        hint_msg = "First open data file from 'File' menu.  Then Highlight and right click on the data plot. \n" 
    559         hint_msg += "Finally, select 'Compute Invariant'. \n" 
     1151        hint_msg += "Finally, select 'Compute Invariant'." 
    5601152        self.hint_msg_txt = wx.StaticText(self, -1, hint_msg)   
    5611153        self.hint_msg_txt.SetForegroundColour("red") 
     
    5661158        data_name_txt = wx.StaticText(self, -1, 'Data : ')   
    5671159        
    568         self.data_name_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH*5, 20), style=0)  
     1160        self.data_name_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH*5, 20), style=0, name='data_name_tcl')  
    5691161        self.data_name_tcl.SetToolTipString("Data's name.") 
    5701162        self.data_name_sizer.AddMany([(data_name_txt, 0, wx.LEFT|wx.RIGHT, 10), 
     
    5731165        data_range_txt = wx.StaticText(self, -1, 'Total Q Range (1/A): ')  
    5741166        data_min_txt = wx.StaticText(self, -1, 'Min : ')   
    575         self.data_min_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH, 20), style=0) 
     1167        self.data_min_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH, 20), style=0, name='data_min_tcl') 
    5761168        self.data_min_tcl.SetToolTipString("The minimum value of q range.") 
    5771169        data_max_txt = wx.StaticText(self, -1, 'Max : ')  
    578         self.data_max_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH, 20), style=0)  
     1170        self.data_max_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH, 20), style=0, name='data_max_tcl')  
    5791171        self.data_max_tcl.SetToolTipString("The maximum value of q range.") 
    5801172        self.data_range_sizer.AddMany([(data_range_txt, 0, wx.RIGHT, 10), 
     
    5831175                                       (data_max_txt, 0, wx.RIGHT, 10), 
    5841176                                       (self.data_max_tcl, 0, wx.RIGHT, 10)]) 
    585         self.data_name_boxsizer.AddMany([(self.hint_msg_sizer, 0 , wx.ALL, 10), 
     1177        self.data_name_boxsizer.AddMany([(self.hint_msg_sizer, 0 , wx.ALL, 5), 
    5861178                                         (self.data_name_sizer, 0 , wx.RIGHT, 10), 
    5871179                                         (self.data_range_sizer, 0 , wx.ALL, 10)]) 
     
    5921184        """ 
    5931185        background_txt = wx.StaticText(self, -1, 'Background : ')   
    594         self.background_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH, 20), style=0)  
    595         background_hint_txt = "background" 
     1186        self.background_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH, 20), style=0, name='background_tcl')  
     1187        wx.EVT_TEXT(self, self.background_tcl.GetId(), self._on_text) 
     1188        background_hint_txt = "Background" 
    5961189        self.background_tcl.SetToolTipString(background_hint_txt) 
    5971190        background_unit_txt = wx.StaticText(self, -1, '[1/cm]')   
    5981191        scale_txt = wx.StaticText(self, -1, 'Scale : ')   
    599         self.scale_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH, 20), style=0) 
     1192        self.scale_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH, 20), style=0, name='scale_tcl') 
     1193        wx.EVT_TEXT(self, self.scale_tcl.GetId(), self._on_text) 
    6001194        scale_hint_txt = "Scale" 
    6011195        self.scale_tcl.SetToolTipString(scale_hint_txt) 
     
    6111205        """ 
    6121206        contrast_txt = wx.StaticText(self, -1, 'Contrast : ')   
    613         self.contrast_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH, 20), style=0) 
     1207        self.contrast_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH, 20), style=0,name='contrast_tcl') 
     1208        wx.EVT_TEXT(self, self.contrast_tcl.GetId(), self._on_text) 
    6141209        contrast_hint_txt = "Contrast" 
    6151210        self.contrast_tcl.SetToolTipString(contrast_hint_txt) 
     
    6171212        porod_const_txt = wx.StaticText(self, -1, 'Porod Constant:')   
    6181213        self.porod_constant_tcl = InvTextCtrl(self, -1,  
    619                                               size=(_BOX_WIDTH, 20), style=0)  
     1214                                              size=(_BOX_WIDTH, 20), style=0,name='porod_constant_tcl')  
     1215        wx.EVT_TEXT(self, self.porod_constant_tcl.GetId(), self._on_text) 
    6201216        porod_const_hint_txt = "Porod Constant" 
    6211217        self.porod_constant_tcl.SetToolTipString(porod_const_hint_txt) 
     
    6321228        Enable and disable the power value editing 
    6331229        """ 
     1230        if event != None:  
     1231            print "enable fit==>event!=None" 
     1232 
    6341233        if self.fix_enable_low.IsEnabled(): 
     1234             
    6351235            if self.fix_enable_low.GetValue(): 
     1236                self.fit_enable_low.SetValue(False) 
    6361237                self.power_low_tcl.Enable() 
    6371238            else: 
     1239                self.fit_enable_low.SetValue(True) 
    6381240                self.power_low_tcl.Disable() 
    639              
     1241        self._set_state(event=event) 
     1242            
    6401243    def _enable_low_q_section(self, event=None): 
    6411244        """ 
    6421245        Disable or enable some button if the user enable low q extrapolation 
    6431246        """ 
     1247        #if event != None: self._set_compute_state() 
    6441248        if self.enable_low_cbox.GetValue(): 
    6451249            self.npts_low_tcl.Enable() 
     
    6551259            self.guinier.Disable() 
    6561260            self.power_law_low.Disable() 
     1261         
    6571262        self._enable_power_law_low() 
    6581263        self._enable_fit_power_law_low() 
     1264        self._set_state(event=event) 
    6591265        self.button_calculate.SetFocus() 
    660      
     1266         
    6611267    def _enable_power_law_low(self, event=None): 
    6621268        """ 
    6631269        Enable editing power law section at low q range 
    6641270        """ 
     1271        #if event != None: self._set_compute_state() 
    6651272        if self.guinier.GetValue(): 
     1273            self.power_law_low.SetValue(False) 
    6661274            self.fix_enable_low.Disable() 
    6671275            self.fit_enable_low.Disable() 
    6681276            self.power_low_tcl.Disable() 
    6691277        else: 
     1278            self.power_law_low.SetValue(True) 
    6701279            self.fix_enable_low.Enable() 
    6711280            self.fit_enable_low.Enable() 
    6721281            self.power_low_tcl.Enable() 
    6731282        self._enable_fit_power_law_low() 
     1283        self._set_state(event=event) 
    6741284             
    6751285    def _layout_extrapolation_low(self): 
     
    6771287        Draw widgets related to extrapolation at low q range 
    6781288        """ 
    679         self.enable_low_cbox = wx.CheckBox(self, -1, "Enable Extrapolate Low Q") 
     1289        self.enable_low_cbox = wx.CheckBox(self, -1, "Enable Extrapolate Low Q",name='enable_low_cbox') 
    6801290        wx.EVT_CHECKBOX(self, self.enable_low_cbox.GetId(), 
    6811291                                         self._enable_low_q_section) 
    6821292        self.fix_enable_low = wx.RadioButton(self, -1, 'Fix', 
    683                                          (10, 10),style=wx.RB_GROUP) 
    684         self.fit_enable_low = wx.RadioButton(self, -1, 'Fit', (10, 10)) 
     1293                                         (10, 10),style=wx.RB_GROUP,name='fix_enable_low') 
    6851294        self.Bind(wx.EVT_RADIOBUTTON, self._enable_fit_power_law_low, 
    6861295                                     id=self.fix_enable_low.GetId()) 
     1296        self.fit_enable_low = wx.RadioButton(self, -1, 'Fit', (10, 10),name='fit_enable_low') 
    6871297        self.Bind(wx.EVT_RADIOBUTTON, self._enable_fit_power_law_low,  
    6881298                                        id=self.fit_enable_low.GetId()) 
    6891299        self.guinier = wx.RadioButton(self, -1, 'Guinier', 
    690                                          (10, 10),style=wx.RB_GROUP) 
    691         self.power_law_low = wx.RadioButton(self, -1, 'Power Law', (10, 10)) 
     1300                                         (10, 10),style=wx.RB_GROUP, name='guinier') 
    6921301        self.Bind(wx.EVT_RADIOBUTTON, self._enable_power_law_low, 
    693                                      id=self.guinier.GetId()) 
     1302                                     id=self.guinier.GetId())         
     1303        self.power_law_low = wx.RadioButton(self, -1, 'Power Law', (10, 10),name='power_law_low') 
    6941304        self.Bind(wx.EVT_RADIOBUTTON, self._enable_power_law_low,  
    6951305                                        id=self.power_law_low.GetId()) 
    6961306         
    6971307        npts_low_txt = wx.StaticText(self, -1, 'Npts') 
    698         self.npts_low_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH*2/3, -1)) 
     1308        self.npts_low_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH*2/3, -1),name='npts_low_tcl') 
     1309        wx.EVT_TEXT(self, self.npts_low_tcl.GetId(), self._on_text) 
    6991310        msg_hint = "Number of Q points to consider" 
    7001311        msg_hint +="while extrapolating the low-Q region" 
    7011312        self.npts_low_tcl.SetToolTipString(msg_hint) 
    7021313        power_txt = wx.StaticText(self, -1, 'Power') 
    703         self.power_low_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH*2/3, -1)) 
     1314        self.power_low_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH*2/3, -1),name='power_low_tcl') 
     1315        wx.EVT_TEXT(self, self.power_low_tcl.GetId(), self._on_text) 
    7041316        
    7051317        power_hint_txt = "Exponent to apply to the Power_law function." 
     
    7471359        Enable and disable the power value editing 
    7481360        """ 
     1361        #if event != None: self._set_compute_state() 
    7491362        if self.fix_enable_high.IsEnabled(): 
    7501363            if self.fix_enable_high.GetValue(): 
     1364                self.fit_enable_high.SetValue(False) 
    7511365                self.power_high_tcl.Enable() 
    7521366            else: 
     1367                self.fit_enable_high.SetValue(True) 
    7531368                self.power_high_tcl.Disable() 
     1369        self._set_state(event=event) 
    7541370         
    7551371    def _enable_high_q_section(self, event=None): 
     
    7571373        Disable or enable some button if the user enable high q extrapolation 
    7581374        """ 
     1375        #if event != None: self._set_compute_state() 
    7591376        if self.enable_high_cbox.GetValue(): 
    7601377            self.npts_high_tcl.Enable() 
     
    7701387            self.fit_enable_high.Disable() 
    7711388        self._enable_fit_power_law_high() 
     1389        self._set_state(event=event) 
    7721390        self.button_calculate.SetFocus() 
    7731391  
     
    7761394        Draw widgets related to extrapolation at high q range 
    7771395        """ 
    778         self.enable_high_cbox = wx.CheckBox(self, -1, "Enable Extrapolate high-Q") 
     1396        self.enable_high_cbox = wx.CheckBox(self, -1, "Enable Extrapolate high-Q", name='enable_high_cbox') 
    7791397        wx.EVT_CHECKBOX(self, self.enable_high_cbox.GetId(), 
    7801398                                         self._enable_high_q_section) 
    781        
    7821399        self.fix_enable_high = wx.RadioButton(self, -1, 'Fix', 
    783                                          (10, 10),style=wx.RB_GROUP) 
    784         self.fit_enable_high = wx.RadioButton(self, -1, 'Fit', (10, 10)) 
     1400                                         (10, 10),style=wx.RB_GROUP,name='fix_enable_high') 
    7851401        self.Bind(wx.EVT_RADIOBUTTON, self._enable_fit_power_law_high, 
    7861402                                     id=self.fix_enable_high.GetId()) 
     1403        self.fit_enable_high = wx.RadioButton(self, -1, 'Fit', (10, 10),name='fit_enable_high')      
    7871404        self.Bind(wx.EVT_RADIOBUTTON, self._enable_fit_power_law_high,  
    7881405                                        id=self.fit_enable_high.GetId()) 
     
    7921409        self.power_law_high.SetToolTipString(msg_hint) 
    7931410        npts_high_txt = wx.StaticText(self, -1, 'Npts') 
    794         self.npts_high_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH*2/3, -1)) 
     1411        self.npts_high_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH*2/3, -1),name='npts_high_tcl') 
     1412        wx.EVT_TEXT(self, self.npts_high_tcl.GetId(), self._on_text) 
    7951413        msg_hint = "Number of Q points to consider" 
    7961414        msg_hint += "while extrapolating the high-Q region" 
    7971415        self.npts_high_tcl.SetToolTipString(msg_hint) 
    7981416        power_txt = wx.StaticText(self, -1, 'Power') 
    799         self.power_high_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH*2/3, -1)) 
     1417        self.power_high_tcl = InvTextCtrl(self, -1, size=(_BOX_WIDTH*2/3, -1),name='power_high_tcl') 
     1418        wx.EVT_TEXT(self, self.power_high_tcl.GetId(), self._on_text) 
    8001419        power_hint_txt = "Exponent to apply to the Power_law function." 
    8011420        self.power_high_tcl.SetToolTipString(power_hint_txt) 
     
    8411460        extra_hint_txt = wx.StaticText(self, -1, extra_hint) 
    8421461        #Extrapolation range [string] 
    843         extrapolation_min_txt = wx.StaticText(self, -1, 'Min : ')   
     1462        extrapolation_min_txt = wx.StaticText(self, -1, 'Min :')   
    8441463        self.extrapolation_min_tcl = OutputTextCtrl(self, -1,  
    845                                                 size=(_BOX_WIDTH, 20), style=0) 
     1464                                                size=(_BOX_WIDTH, 20), style=0,name='extrapolation_min_tcl') 
    8461465        self.extrapolation_min_tcl.SetValue(str(Q_MINIMUM)) 
    8471466        self.extrapolation_min_tcl.SetToolTipString("The minimum extrapolated q value.") 
    848         extrapolation_max_txt = wx.StaticText(self, -1, 'Max : ')  
     1467        extrapolation_max_txt = wx.StaticText(self, -1, 'Max :')  
    8491468        self.extrapolation_max_tcl = OutputTextCtrl(self, -1, 
    850                                                   size=(_BOX_WIDTH, 20), style=0)  
     1469                                                  size=(_BOX_WIDTH, 20), style=0,name='extrapolation_max_tcl')  
    8511470        self.extrapolation_max_tcl.SetValue(str(Q_MAXIMUM)) 
    8521471        self.extrapolation_max_tcl.SetToolTipString("The maximum extrapolated q value.") 
     
    8621481        self._layout_extrapolation_high() 
    8631482        self.extrapolation_low_high_sizer.AddMany([(self.low_extrapolation_sizer, 
    864                                                      0, wx.ALL, 10), 
     1483                                                     0, wx.ALL, 5), 
    8651484                                                   (self.high_extrapolation_sizer, 
    866                                                     0, wx.ALL, 10)]) 
     1485                                                    0, wx.ALL, 5)]) 
    8671486        self.extrapolation_sizer.AddMany([(self.extrapolation_range_sizer, 0, 
    868                                             wx.RIGHT, 10), 
     1487                                            wx.RIGHT, 5), 
    8691488                                        (self.extrapolation_low_high_sizer, 0, 
    870                                            wx.ALL, 10)]) 
     1489                                           wx.ALL, 5)]) 
    8711490         
    8721491    def _layout_volume_surface_sizer(self): 
     
    8781497        uncertainty = "+/-"  
    8791498        volume_txt = wx.StaticText(self, -1, 'Volume Fraction      ') 
    880         self.volume_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH,-1)) 
     1499        self.volume_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH,-1),name='volume_tcl') 
     1500        wx.EVT_TEXT(self, self.volume_tcl.GetId(), self._on_out_text) 
    8811501        self.volume_tcl.SetToolTipString("Volume fraction.") 
    882         self.volume_err_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH,-1)) 
     1502        self.volume_err_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH,-1),name='volume_err_tcl') 
     1503        wx.EVT_TEXT(self, self.volume_err_tcl.GetId(), self._on_out_text) 
    8831504        self.volume_err_tcl.SetToolTipString("Uncertainty on the volume fraction.") 
    8841505        volume_units_txt = wx.StaticText(self, -1, unit_volume) 
    8851506         
    8861507        surface_txt = wx.StaticText(self, -1, 'Specific Surface') 
    887         self.surface_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH,-1)) 
     1508        self.surface_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH,-1),name='surface_tcl') 
     1509        wx.EVT_TEXT(self, self.surface_tcl.GetId(), self._on_out_text) 
    8881510        self.surface_tcl.SetToolTipString("Specific surface value.") 
    889         self.surface_err_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH,-1)) 
     1511        self.surface_err_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH,-1),name='surface_err_tcl') 
     1512        wx.EVT_TEXT(self, self.surface_err_tcl.GetId(), self._on_out_text) 
    8901513        self.surface_err_tcl.SetToolTipString("Uncertainty on the specific surface.") 
    8911514        surface_units_txt = wx.StaticText(self, -1, unit_surface) 
     
    9301553        unit_invariant = '[1/(cm * A)]' 
    9311554        invariant_total_txt = wx.StaticText(self, -1, 'Invariant Total [Q*]') 
    932         self.invariant_total_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH,-1)) 
     1555        self.invariant_total_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH,-1),name='invariant_total_tcl') 
    9331556        msg_hint = "Total invariant [Q*], including extrapolated regions." 
    9341557        self.invariant_total_tcl.SetToolTipString(msg_hint) 
    935         self.invariant_total_err_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH,-1)) 
     1558        self.invariant_total_err_tcl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH,-1),name='invariant_total_err_tcl') 
    9361559        self.invariant_total_err_tcl.SetToolTipString("Uncertainty on invariant.") 
    9371560        invariant_total_units_txt = wx.StaticText(self, -1, unit_invariant) 
     
    9801603        #compute button 
    9811604        id = wx.NewId() 
    982         self.button_calculate = wx.Button(self, id, "Compute") 
     1605        self.button_calculate = wx.Button(self, id, "Compute", name ='compute_invariant' ) 
    9831606        self.button_calculate.SetToolTipString("Compute invariant") 
    9841607        self.Bind(wx.EVT_BUTTON, self.compute_invariant, id=id)    
     
    9861609        id = wx.NewId() 
    9871610        self.button_details = wx.Button(self, id, "Details?") 
    988         self.button_details.SetToolTipString("Give Details on Computation") 
     1611        self.button_details.SetToolTipString("Details about the results of the computation") 
    9891612        self.Bind(wx.EVT_BUTTON, self.display_details, id=id) 
    9901613        details = "Details on Invariant Total Calculations" 
    9911614        details_txt = wx.StaticText(self, -1, details) 
    992         self.button_sizer.AddMany([((10,10), 0 , wx.LEFT,0), 
     1615        self.button_sizer.AddMany([((50,10), 0 , wx.LEFT,0), 
    9931616                                   (details_txt, 0 ,  
    9941617                                    wx.RIGHT|wx.BOTTOM|wx.TOP, 10), 
    9951618                                   (self.button_details, 0 , wx.ALL, 10), 
    996                         (self.button_calculate, 0 , wx.RIGHT|wx.TOP|wx.BOTTOM, 10)]) 
    997          
     1619                        (self.button_calculate, 0 , wx.RIGHT|wx.TOP|wx.BOTTOM, 10)])#, 
     1620                                   #(self.button_undo, 0 , wx.ALL, 10), 
     1621                                   #(self.button_redo, 0 , wx.ALL, 10)]) 
     1622    def _layout_save_button(self):   
     1623        """ 
     1624        Do the layout for the save button widgets 
     1625        """  
     1626        import sans.perspectives.invariant as invariant 
     1627        path = invariant.get_data_path(media='media') 
     1628        self.undo_png = os.path.join(path,"undo.png") 
     1629        self.redo_png = os.path.join(path,"redo.png") 
     1630        self.save_png = os.path.join(path,"save.png") 
     1631        #undo button 
     1632        id = wx.NewId() 
     1633        self.button_undo = wx.BitmapButton(self, id,wx.Bitmap(self.undo_png))#wx.Button(self, id, "Undo",size=(50,20)) 
     1634        self.button_undo.SetToolTipString("Undo") 
     1635        self.Bind(wx.EVT_BUTTON, self.undo, id=id) 
     1636        self.button_undo.Disable() 
     1637        #redo button 
     1638        id = wx.NewId() 
     1639        self.button_redo = wx.BitmapButton(self, id,wx.Bitmap(self.redo_png))#wx.Button(self, id, "Redo",size=(50,20)) 
     1640        self.button_redo.SetToolTipString("Redo") 
     1641        self.Bind(wx.EVT_BUTTON, self.redo, id=id) 
     1642        self.button_redo.Disable()    
     1643        #save button 
     1644        id = wx.NewId() 
     1645        self.button_save = wx.BitmapButton(self, id,wx.Bitmap(self.save_png), name ='Save_invariant')#wx.Button(self, id, "Save", name ='Save_invariant' ) 
     1646        self.button_save.SetToolTipString("Save as a file") 
     1647        self.Bind(wx.EVT_BUTTON, self._on_save_button, id=id)    
     1648        self.button_save.Disable()   
     1649        self.save_button_sizer.AddMany([((PANEL_WIDTH/1.5,20), 1 , wx.EXPAND|wx.ADJUST_MINSIZE,0), 
     1650                                   (self.button_undo, 0 ,wx.LEFT|wx.ADJUST_MINSIZE, 10), 
     1651                                   (self.button_redo, 0 ,wx.LEFT|wx.ADJUST_MINSIZE, 10), 
     1652                                   (self.button_save, 0 ,wx.LEFT|wx.ADJUST_MINSIZE, 10)])         
    9981653    def _do_layout(self): 
    9991654        """ 
     
    10061661        self._layout_outputs_sizer() 
    10071662        self._layout_button() 
     1663        self._layout_save_button() 
    10081664        self.main_sizer.AddMany([(self.data_name_boxsizer,0, wx.ALL, 10), 
    10091665                                  (self.outputs_sizer, 0, 
     
    10141670                                  wx.LEFT|wx.RIGHT|wx.BOTTOM, 10), 
    10151671                                  (self.extrapolation_sizer, 0, 
     1672                                  wx.LEFT|wx.RIGHT|wx.BOTTOM, 10),\ 
     1673                                  (self.save_button_sizer,0, 
    10161674                                  wx.LEFT|wx.RIGHT|wx.BOTTOM, 10)]) 
    10171675        self.SetSizer(self.main_sizer) 
     
    10371695        wx.Frame.__init__(self, parent, id, title, size=(PANEL_WIDTH +100, 
    10381696                                                             PANEL_HEIGHT+100)) 
    1039          
     1697        from DataLoader.loader import  Loader 
     1698        self.loader = Loader() 
     1699        import invariant 
     1700 
     1701        data= self.loader.load("C:/ECLPS/workspace/trunk/DataLoader/test/ascii_test_3.txt") 
    10401702        self.panel = InvariantPanel(self) 
     1703 
     1704        data.name = data.filename 
     1705        self.panel.set_data(data) 
    10411706        self.Centre() 
    10421707        self.Show(True) 
  • invariantview/perspectives/invariant/invariant_widgets.py

    rd7a39e5 r4e1c362  
    1515import wx 
    1616import os 
     17from invariant_state import InvariantState as IState 
     18import copy 
    1719 
    1820class InvTextCtrl(wx.TextCtrl): 
     
    2224    """ 
    2325    def __init__(self, *args, **kwds): 
    24          
    2526        wx.TextCtrl.__init__(self, *args, **kwds) 
    26          
    2727        ## Set to True when the mouse is clicked while the whole string is selected 
    28         full_selection = False 
     28        self.full_selection = False 
    2929        ## Call back for EVT_SET_FOCUS events 
    3030        _on_set_focus_callback = None 
     31 
    3132        # Bind appropriate events 
    3233        self.Bind(wx.EVT_LEFT_UP, self._highlight_text) 
    3334        self.Bind(wx.EVT_SET_FOCUS, self._on_set_focus) 
    34  
     35         
    3536    def _on_set_focus(self, event): 
    3637        """ 
     
    3940         
    4041        :param event: mouse event 
    41          
    4242        """ 
    4343        event.Skip() 
     
    4949         
    5050        :param event: mouse event 
    51          
    5251        """ 
    5352        # Make sure the mouse event is available to other listeners 
     
    6362                if start==end: 
    6463                    control.SetSelection(-1,-1) 
     64            
    6565 
     66     
    6667class OutputTextCtrl(wx.TextCtrl): 
    6768    """ 
     
    7879        # The event will be skipped once the call-back 
    7980        # is called. 
     81         
    8082        self.Bind(wx.EVT_MOUSE_EVENTS, self._click) 
     83 
    8184         
    8285    def _click(self, event): 
     
    8689        """  
    8790        pass 
     91     
     92     
     93 
    8894  
Note: See TracChangeset for help on using the changeset viewer.