source: sasview/sansview/perspectives/fitting/fitpanel.py @ 240b9966

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 240b9966 was 240b9966, checked in by Gervaise Alina <gervyh@…>, 15 years ago

working on undo and redo

  • Property mode set to 100644
File size: 16.2 KB
Line 
1import wx
2import wx.aui
3import wx.lib
4import numpy
5import string 
6
7
8import basepage
9
10_BOX_WIDTH = 80
11
12
13class StateIterator(object):
14    """
15        Contains all saved state of a given page.
16        Provide position of the current state of a page, the first save state
17        and the last state for a given page.
18        Allow easy undo or redo for a given page 
19    """
20    def __init__(self):
21        self._current=0
22       
23   
24    def __iter__(self):
25        return self
26   
27   
28    def first(self):
29        self._current =0
30        return self._current
31   
32    def next(self, max ):
33        if self._current < max:
34            self._current += 1
35        return self._current
36   
37    def previous(self):
38        if self._current > 0:
39            self._current = self._current -1
40        return self._current
41   
42    def currentPosition(self):
43        return self._current
44   
45    def setPosition(self, value):
46        if value >=0:
47            self._current = int(value)
48       
49       
50   
51 
52class ListOfState(list):     
53    def __init__(self, *args, **kw):
54        list.__init__(self, *args, **kw)
55        self.iterator = StateIterator()
56       
57    def appendItem(self, x):
58        self.append(x)
59        self.iterator.setPosition(value= len(self)-1)
60       
61    def removeItem(self, x):
62        self.iterator.previous()
63        self.remove(x)
64       
65    def getPreviousItem(self):
66        position = self.iterator.previous()
67       
68        if position < 0:
69            return None
70        else:
71            return self[position]
72       
73    def getNextItem(self):
74        position = self.iterator.next(max= len(self)-1)
75        if position >= len(self):
76            return None
77        else:
78            return self[position]
79       
80    def getCurrentItem(self):
81        postion = self.iterator.currentPosition()
82        if postion >= 0 and position < len(self):
83            return self[postion]
84        else:
85            return None
86       
87    def getCurrentPosition(self):
88        return self.iterator.currentPosition()
89       
90
91       
92       
93       
94class PageInfo(object):
95    """
96        this class contains the minimum numbers of data members
97        a fitpage or model page need to be initialized.
98    """
99    data = None
100    model= None
101    manager= None
102    event_owner= None
103    model_list_box = None
104    name=None
105    ## Internal name for the AUI manager
106    window_name = "Page"
107    ## Title to appear on top of the window
108    window_caption = "Page"
109   
110    def __init__(self, model=None,data=None, manager=None,
111                  event_owner=None,model_list_box=None , name=None):
112        """
113            Initialize data members
114        """
115        self.data = data
116        self.model= model
117        self.manager= manager
118        self.event_owner= event_owner
119        self.model_list_box = model_list_box
120        self.name=None
121        self.window_name = "Page"
122        self.window_caption = "Page"
123   
124class FitPanel(wx.aui.AuiNotebook):   
125
126    """
127        FitPanel class contains fields allowing to fit  models and  data
128        @note: For Fit to be performed the user should check at least one parameter
129        on fit Panel window.
130       
131    """
132    ## Internal name for the AUI manager
133    window_name = "Fit panel"
134    ## Title to appear on top of the window
135    window_caption = "Fit Panel "
136    CENTER_PANE = True
137   
138    def __init__(self, parent, *args, **kwargs):
139        wx.aui.AuiNotebook.__init__(self,parent,-1,
140                    style= wx.aui.AUI_NB_WINDOWLIST_BUTTON|wx.aui.AUI_NB_DEFAULT_STYLE|wx.CLIP_CHILDREN  )
141   
142        self.manager=None
143        self.parent=parent
144        self.event_owner=None
145       
146        pageClosedEvent = wx.aui.EVT_AUINOTEBOOK_PAGE_CLOSE
147        self.Bind(wx.aui.EVT_AUINOTEBOOK_PAGE_CLOSE, self.onClosePage)
148        ##Creating the default page --welcomed page
149        self.about_page=None
150        from welcome_panel import PanelAbout
151        self.about_page = PanelAbout(self, -1)
152        self.AddPage(self.about_page,"Welcome!")
153     
154       
155        #dictionary of miodel {model class name, model class}
156        self.model_list_box={}
157        ##dictionary of page info
158        self.page_info_dict={}
159        ## save the title of the last page tab added
160        self.fit_page_name={}
161        ## list of existing fit page
162        self.list_fitpage_name=[]
163   
164        #model page info
165        self.model_page_number=None
166        ## fit page number for model plot
167        self.fit_page1D_number=None
168        self.fit_page2D_number=None
169        self.model_page=None
170        self.sim_page=None
171        ## get the state of a page
172        self.Bind(basepage.EVT_PAGE_INFO, self._onGetstate)
173        self.Bind(basepage.EVT_PREVIOUS_STATE, self._onUndo)
174        self.Bind(basepage.EVT_NEXT_STATE, self._onRedo)
175       
176        # increment number for model name
177        self.count=0
178        #updating the panel
179        self.Update()
180        self.Center()
181       
182       
183    def onClosePage(self, event):
184        """
185             close page and remove all references to the closed page
186        """
187        selected_page = self.GetPage(self.GetSelection())
188        ## removing about page
189        if selected_page==self.about_page:
190            self.about_page=None
191            return 
192        ## removing sim_page
193        if selected_page == self.sim_page:
194            self.manager.sim_page=None 
195            return
196       
197        ## closing other pages
198        state = selected_page.createMemento()
199        page_name = selected_page.window_name
200        page_finder = self.manager.get_page_finder() 
201        fitproblem = None
202        ## removing model page
203        if selected_page == self.model_page:
204            fitproblem = selected_page.model.clone()
205            self.model_page = None
206            self.count =0
207            ## page on menu
208            self.manager._add_page_onmenu(page_name, fitproblem)
209        else:
210            if selected_page in page_finder:
211       
212                fitproblem= page_finder[selected_page].clone()
213                if self.GetPageIndex(selected_page)==self.fit_page1D_number:
214                    self.fit_page1D_number=None
215                if self.GetPageIndex(selected_page)==self.fit_page2D_number:
216                    self.fit_page2D_number=None
217                ## page on menu
218                self.manager._add_page_onmenu(page_name, fitproblem)
219                del page_finder[selected_page]
220            ##remove the check box link to the model name of this page (selected_page)
221            try:
222                self.sim_page.draw_page()
223            except:
224                ## that page is already deleted no need to remove check box on
225                ##non existing page
226                pass
227               
228        #Delete the name of the page into the list of open page
229        if selected_page.window_name in self.list_fitpage_name:
230            self.list_fitpage_name.remove(selected_page.window_name)
231           
232       
233    def set_manager(self, manager):
234        """
235             set panel manager
236             @param manager: instance of plugin fitting
237        """
238        self.manager = manager
239
240       
241    def set_owner(self,owner):
242        """
243            set and owner for fitpanel
244            @param owner: the class responsible of plotting
245        """
246        self.event_owner = owner
247   
248    def set_model_list(self,dict):
249         """
250             copy a dictionary of model into its own dictionary
251             @param dict: dictionnary made of model name as key and model class
252             as value
253         """
254         self.model_list_box = dict
255       
256 
257    def get_current_page(self):
258        """
259            @return the current page selected
260        """
261        return self.GetPage(self.GetSelection() )
262   
263    def add_sim_page(self):
264        """
265            Add the simultaneous fit page
266        """
267        from simfitpage import SimultaneousFitPage
268        page_finder= self.manager.get_page_finder()
269        self.sim_page = SimultaneousFitPage(self,page_finder=page_finder, id=-1)
270       
271        self.AddPage(self.sim_page,caption="Simultaneous Fit",select=True)
272        self.sim_page.set_manager(self.manager)
273        return self.sim_page
274       
275    def add_fit_page( self,data, reset=False ):
276        """
277            Add a fitting page on the notebook contained by fitpanel
278            @param data: data to fit
279            @return panel : page just added for further used. is used by fitting module
280        """     
281        if data.is_data:
282            name = data.name
283        else:
284            if data.__class__.__name__=="Data2D":
285                name = 'Model 2D Fit'
286            else:
287                name = 'Model 1D Fit'
288        if not name in self.list_fitpage_name:
289            myinfo = PageInfo( data=data, name=name )
290            myinfo.model_list_box = self.model_list_box.get_list()
291            myinfo.event_owner = self.event_owner
292            myinfo.manager = self.manager
293            myinfo.window_name = name
294            myinfo.window_caption = name
295       
296            #if not name in self.fit_page_name :
297            from fitpage import FitPage
298            panel = FitPage(parent= self, page_info=myinfo)
299           
300            self.AddPage(page=panel, caption=name, select=True)
301            if name == 'Model 1D Fit':
302                self.fit_page1D_number= self.GetPageIndex(panel)
303            if name =='Model 2D Fit':
304                self.fit_page2D_number= self.GetPageIndex(panel)
305               
306            self.list_fitpage_name.append(name)
307            if reset:
308                if name in self.fit_page_name.keys():
309                    memento= self.fit_page_name[name][0]
310                    panel.reset_page(memento)
311            else:
312                self.fit_page_name[name]=ListOfState()
313               
314                #self.fit_page_name[name].appendItem(panel.createMemento())
315            #GetPage(self, page_idx)
316            return panel
317        elif name =='Model 1D Fit':
318            if self.fit_page1D_number!=None:
319                panel =self.GetPage(self.fit_page1D_number) 
320                #self.fit_page_name[name]=[]
321                self.fit_page_name[name]= ListOfState()
322                #self.fit_page_name[name].insert(0,panel.createMemento())
323                #self.fit_page_name[name].append(panel.createMemento())
324                return panel
325            return None
326        elif name =='Model 2D Fit':
327            if self.fit_page2D_number!=None:
328                panel =self.GetPage(self.fit_page2D_number) 
329                self.fit_page_name[name]=ListOfState()
330                #self.fit_page_name[name].append(panel.createMemento())
331                return panel
332            return None
333        return None
334       
335   
336    def add_model_page(self,model,page_title="Model", qmin=0.0001, qmax=0.13,
337                        npts=50, topmenu=False, reset=False):
338        """
339            Add a model page only one  to display any model selected from the menu or the page combo box.
340            when this page is closed than the user will be able to open a new one
341           
342            @param model: the model for which paramters will be changed
343            @param page_title: the name of the page
344            @param page_info: contains info about the state of the page
345            @param qmin: mimimum Q
346            @param qmax: maximum Q
347            @param npts: number of Q points
348        """
349        if topmenu==True:
350            ##first time to open model page
351            if self.count==0 :
352                #if not page_title in self.list_fitpage_name :
353                self._help_add_model_page(model=model, page_title=page_title,
354                                qmin=qmin, qmax=qmax, npts=npts, reset=reset)
355                self.count +=1
356            else:
357                self.model_page.select_model(model)
358                self.fit_page_name[name]=ListOfState()
359                #self.fit_page_name[page_title].insert(0,self.model_page.createMemento())
360     
361     
362     
363    def _close_fitpage(self,data):
364        """
365            close a fit page when its data is completely remove from the graph
366        """
367        name = data.name
368        for index in range(self.GetPageCount()):
369            if self.GetPageText(index)== name:
370                selected_page = self.GetPage(index) 
371   
372                if index ==self.fit_page1D_number:
373                    self.fit_page1D_number=None
374                if index ==self.fit_page2D_number:
375                    self.fit_page2D_number=None
376                if selected_page in self.manager.page_finder:
377                    del self.manager.page_finder[selected_page]
378                ##remove the check box link to the model name of this page (selected_page)
379                try:
380                    self.sim_page.draw_page()
381                except:
382                    ## that page is already deleted no need to remove check box on
383                    ##non existing page
384                    pass
385               
386                #Delete the name of the page into the list of open page
387                if selected_page.window_name in self.list_fitpage_name:
388                    self.list_fitpage_name.remove(selected_page.window_name)
389                self.DeletePage(index)
390                break
391       
392       
393    def  _onGetstate(self, event):
394        """
395            copy the state of a page
396        """
397        page= event.page
398        if page.window_name in self.fit_page_name:
399            self.fit_page_name[page.window_name].appendItem(page.createMemento()) 
400           
401            print " current added state: ",len(self.fit_page_name[page.window_name])
402           
403    def _onUndo(self, event ):
404        """
405            return the previous state of a given page is available
406        """
407        page = event.page
408        if page.window_name in self.fit_page_name:
409            if self.fit_page_name[page.window_name].getCurrentPosition()==0:
410                state = None
411            else:
412                state = self.fit_page_name[page.window_name].getPreviousItem()
413                page._redo.Enable(True)
414            page.reset_page(state)
415       
416    def _onRedo(self, event ): 
417        """
418            return the next state available
419        """       
420        page = event.page
421        if page.window_name in self.fit_page_name:
422            length= len(self.fit_page_name[page.window_name])
423            if self.fit_page_name[page.window_name].getCurrentPosition()== length -1:
424                state = None
425                page._redo.Enable(False)
426            else:
427                state = self.fit_page_name[page.window_name].getNextItem()
428            page.reset_page(state) 
429               
430    def _help_add_model_page(self,model,page_title="Model", qmin=0.0001, 
431                             qmax=0.13, npts=50,reset= False):
432        """
433            #TODO: fill in description
434           
435            @param qmin: mimimum Q
436            @param qmax: maximum Q
437            @param npts: number of Q points
438        """
439        ## creating object that contaning info about model
440        myinfo = PageInfo(model= model ,name= page_title)
441        myinfo.model_list_box = self.model_list_box.get_list()
442        myinfo.event_owner = self.event_owner
443        myinfo.manager = self.manager
444        myinfo.window_name = page_title
445        myinfo.window_caption = page_title
446     
447        from modelpage import ModelPage
448        panel = ModelPage(self,myinfo)
449       
450        self.AddPage(page=panel, caption=page_title, select=True)
451
452        self.model_page_number=self.GetSelection()
453        self.model_page=self.GetPage(self.GetSelection())
454     
455        ##  resetting page
456        if reset:
457            if page_title in self.fit_page_name.keys():
458
459                memento= self.fit_page_name[page_title][0]
460                panel.reset_page(memento)
461        else:
462            self.fit_page_name[page_title]=ListOfState()
463            #self.fit_page_name[page_title]=[]
464            self.fit_page_name[page_title].insert(0,panel.createMemento())
465       
466 
Note: See TracBrowser for help on using the repository browser.