source: sasview/calculatorview/perspectives/calculator/collimation_editor.py @ c5dca87

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

working on data editor

  • Property mode set to 100644
File size: 22.5 KB
Line 
1
2import wx
3import sys
4from copy import deepcopy
5from DataLoader.loader import Loader
6from DataLoader.data_info import Aperture, Collimation
7from aperture_editor import ApertureDialog
8
9from sans.guiframe.utils import check_float
10_BOX_WIDTH = 60
11
12if sys.platform.count("win32")>0:
13    _STATICBOX_WIDTH = 500
14    PANEL_WIDTH = 530
15    PANEL_HEIGHT = 430
16    FONT_VARIANT = 0
17else:
18    _STATICBOX_WIDTH = 550
19    PANEL_WIDTH = 600
20    PANEL_HEIGHT = 480
21    FONT_VARIANT = 1
22   
23class CollimationDialog(wx.Dialog):
24    def __init__(self, parent=None, manager=None,
25                 collimation=[], *args, **kwds):
26        """
27        """
28        kwds['size'] =(PANEL_WIDTH, PANEL_HEIGHT)
29        kwds['title'] = "Collimation Editor"
30        wx.Dialog.__init__(self, parent=parent, *args, **kwds)
31        self.parent = parent
32        self.manager = manager
33        self._collimation = collimation
34        self._reset_collimation = deepcopy(collimation)
35        self._notes = ""
36        self._description = "Edit collimation"
37        self._do_layout()
38        self.set_values()
39 
40    def _define_structure(self):
41        """
42            define initial sizer
43        """
44        self.main_sizer = wx.BoxSizer(wx.VERTICAL)
45        self.box_collimation = wx.StaticBox(self, -1,str("Edit Selected Collimation"))
46        self.boxsizer_collimation = wx.StaticBoxSizer(self.box_collimation, wx.VERTICAL)
47       
48        collimation_box = wx.StaticBox(self, -1, "Edit Number of Collimations")
49        self.collimation_sizer = wx.StaticBoxSizer(collimation_box, wx.VERTICAL)
50        self.collimation_sizer.SetMinSize((_STATICBOX_WIDTH, -1))
51        self.collimation_button_sizer = wx.BoxSizer(wx.HORIZONTAL)
52        self.collimation_hint_sizer = wx.BoxSizer(wx.HORIZONTAL)
53       
54        self.name_sizer = wx.BoxSizer(wx.HORIZONTAL)
55        self.length_sizer = wx.BoxSizer(wx.HORIZONTAL)
56        self.button_sizer = wx.BoxSizer(wx.HORIZONTAL)
57       
58        aperture_box = wx.StaticBox(self, -1, "Edit Aperture")
59        self.aperture_sizer = wx.StaticBoxSizer(aperture_box, wx.VERTICAL)
60        self.aperture_button_sizer = wx.BoxSizer(wx.HORIZONTAL)
61        self.aperture_hint_sizer = wx.BoxSizer(wx.HORIZONTAL)
62     
63    def _layout_collimation(self):
64        """
65            Do the layout for collimation related widgets
66        """
67        collimation_name_txt = wx.StaticText(self, -1, "Collimation:") 
68        hint_collimation_txt = 'Current available collimation.'
69        collimation_name_txt.SetToolTipString(hint_collimation_txt) 
70        self.collimation_cbox = wx.ComboBox(self, -1, style=wx.CB_READONLY)
71        wx.EVT_COMBOBOX(self.collimation_cbox, -1, self.on_select_collimation) 
72        hint_collimation_name_txt = 'Name of collimations.'
73        self.collimation_cbox.SetToolTipString(hint_collimation_name_txt) 
74   
75        self.bt_add_collimation = wx.Button(self, -1, "Add")
76        self.bt_add_collimation.SetToolTipString("Edit data's collimation.")
77        self.bt_add_collimation.Bind(wx.EVT_BUTTON, self.add_collimation)
78       
79        self.bt_remove_collimation = wx.Button(self, -1, "Remove")
80        self.bt_remove_collimation.SetToolTipString("Remove data's collimation.")
81        self.bt_remove_collimation.Bind(wx.EVT_BUTTON, self.remove_collimation)
82     
83        self.collimation_button_sizer.AddMany([(collimation_name_txt, 0, wx.LEFT, 15),
84                                     (self.collimation_cbox, 0, wx.LEFT, 5),
85                                     (self.bt_add_collimation, 0, wx.LEFT, 10),
86                                     (self.bt_remove_collimation, 0, wx.LEFT, 5)])
87        collimation_hint_txt = 'No collimation is available for this data.'
88        self.collimation_txt = wx.StaticText(self, -1, collimation_hint_txt) 
89        self.collimation_hint_sizer.Add(self.collimation_txt, 0, wx.LEFT, 10)
90        self.collimation_sizer.AddMany([(self.collimation_button_sizer, 0, wx.ALL, 10),
91                                     (self.collimation_hint_sizer, 0, wx.ALL, 10)])
92     
93        self.fill_collimation_combox()
94        self.enable_collimation()
95       
96
97    def _layout_name(self):
98        """
99            Do the layout for collimation name related widgets
100        """
101        #Collimation name [string]
102        name_txt = wx.StaticText(self, -1, 'Name : ') 
103        self.name_tcl = wx.TextCtrl(self, -1, size=(_BOX_WIDTH*5, 20), style=0) 
104        self.name_sizer.AddMany([(name_txt, 0, wx.LEFT|wx.RIGHT, 10),
105                                       (self.name_tcl, 0, wx.EXPAND)])
106       
107    def _layout_length(self):
108        """
109            Do the  layout for length related widgets
110        """
111        #Collimation length
112        length_txt = wx.StaticText(self, -1, 'Length:') 
113        self.length_tcl = wx.TextCtrl(self, -1, size=(_BOX_WIDTH, 20), style=0)   
114        length_unit_txt = wx.StaticText(self, -1, 'Unit: ') 
115        self.length_unit_tcl = wx.TextCtrl(self, -1, size=(_BOX_WIDTH, 20),style=0) 
116        self.length_sizer.AddMany([(length_txt, 0, wx.LEFT|wx.RIGHT, 10),
117                                     (self.length_tcl, 0, wx.LEFT, 12),
118                                     (length_unit_txt, 0, wx.LEFT|wx.RIGHT, 10),
119                                     (self.length_unit_tcl, 0, wx.EXPAND)]) 
120   
121    def _layout_button(self): 
122        """
123            Do the layout for the button widgets
124        """ 
125        self.bt_apply = wx.Button(self, -1,'Apply')
126        self.bt_apply.Bind(wx.EVT_BUTTON, self.on_click_apply)
127        self.bt_apply.SetToolTipString("Apply current changes to collimation.")
128        self.bt_cancel = wx.Button(self, -1,'Cancel')
129        self.bt_cancel.SetToolTipString("Cancel current changes.")
130        self.bt_cancel.Bind(wx.EVT_BUTTON, self.on_click_cancel)
131        self.bt_close = wx.Button(self, wx.ID_CANCEL,'Close')
132        self.bt_close.SetToolTipString("Close window.")
133        self.button_sizer.AddMany([(self.bt_apply, 0, wx.LEFT, 200),
134                                   (self.bt_cancel, 0, wx.LEFT, 10),
135                                   (self.bt_close, 0, wx.LEFT, 10)])
136    def _layout_aperture(self):
137        """
138            Do the layout for aperture related widgets
139        """
140        aperture_name_txt = wx.StaticText(self, -1, "Aperture:") 
141        hint_aperture_txt = 'Current available aperture.'
142        aperture_name_txt.SetToolTipString(hint_aperture_txt) 
143        self.aperture_cbox = wx.ComboBox(self, -1, style=wx.CB_READONLY)
144        hint_aperture_name_txt = 'Name of apertures.'
145        self.aperture_cbox.SetToolTipString(hint_aperture_name_txt) 
146   
147        self.bt_add_aperture = wx.Button(self, -1, "Add")
148        self.bt_add_aperture.SetToolTipString("Edit data's aperture.")
149        self.bt_add_aperture.Bind(wx.EVT_BUTTON, self.add_aperture)
150        self.bt_edit_aperture = wx.Button(self, -1, "Edit")
151        self.bt_edit_aperture.SetToolTipString("Edit data's aperture.")
152        self.bt_edit_aperture.Bind(wx.EVT_BUTTON, self.edit_aperture)
153        self.bt_remove_aperture = wx.Button(self, -1, "Remove")
154        self.bt_remove_aperture.SetToolTipString("Remove data's aperture.")
155        self.bt_remove_aperture.Bind(wx.EVT_BUTTON, self.remove_aperture)
156     
157        self.aperture_button_sizer.AddMany([(aperture_name_txt, 0, wx.LEFT, 15),
158                                     (self.aperture_cbox, 0, wx.LEFT, 5),
159                                     (self.bt_add_aperture, 0, wx.LEFT, 10),
160                                     (self.bt_edit_aperture, 0, wx.LEFT, 5),
161                                     (self.bt_remove_aperture, 0, wx.LEFT, 5)])
162        aperture_hint_txt = 'No aperture is available for this data.'
163        self.aperture_txt = wx.StaticText(self, -1, aperture_hint_txt) 
164        self.aperture_hint_sizer.Add(self.aperture_txt, 0, wx.LEFT, 10)
165        self.aperture_sizer.AddMany([(self.aperture_button_sizer, 0, wx.ALL, 10),
166                                     (self.aperture_hint_sizer, 0, wx.ALL, 10)])
167        self.fill_aperture_combox()
168        self.enable_aperture()
169   
170    def _do_layout(self, data=None):
171        """
172            Draw the current panel
173        """
174        self._define_structure()
175        self._layout_collimation()
176        self._layout_name()
177        self._layout_length()
178        self._layout_aperture()
179        self._layout_button()
180     
181        self.boxsizer_collimation.AddMany([(self.name_sizer, 0,
182                                          wx.EXPAND|wx.TOP|wx.BOTTOM, 5),
183                                          (self.length_sizer, 0,
184                                     wx.EXPAND|wx.TOP|wx.BOTTOM, 5),
185                                     (self.aperture_sizer, 0,
186                                     wx.EXPAND|wx.ALL, 10)])
187        self.main_sizer.AddMany([(self.collimation_sizer, 0, wx.ALL, 10),
188                                  (self.boxsizer_collimation, 0, wx.ALL, 10),
189                                  (self.button_sizer, 0,
190                                    wx.EXPAND|wx.TOP|wx.BOTTOM, 5)])
191        self.SetSizer(self.main_sizer)
192        self.SetAutoLayout(True)
193       
194    def get_current_collimation(self):
195        """
196        """
197        if not self.collimation_cbox.IsEnabled():
198            return None, None, None
199        position = self.collimation_cbox.GetSelection() 
200        if position == wx.NOT_FOUND:
201            return None, None, None
202        collimation_name = self.collimation_cbox.GetStringSelection() 
203        collimation = self.collimation_cbox.GetClientData(position)
204        return collimation, collimation_name, position
205   
206    def fill_collimation_combox(self):
207        """
208            fill the current combobox with the available collimation
209        """
210        if self._collimation is None or self._collimation == []:
211            return
212        for collimation in self._collimation:
213            pos = self.collimation_cbox.Append(str(collimation.name))
214            self.collimation_cbox.SetClientData(pos, collimation)
215            self.collimation_cbox.SetSelection(pos)
216            self.collimation_cbox.SetStringSelection(str(collimation.name)) 
217           
218    def add_collimation(self, event):
219        """
220            Append empty collimation to data's list of collimation
221        """
222       
223        if not self.collimation_cbox.IsEnabled():
224            self.collimation_cbox.Enable()
225        collimation = Collimation()
226        self._collimation.append(collimation)
227        position = self.collimation_cbox.Append(str(collimation.name))
228        self.collimation_cbox.SetClientData(position, collimation)
229        self.collimation_cbox.SetSelection(position) 
230        self.enable_collimation() 
231        self.bt_add_aperture.Enable()
232        self.fill_aperture_combox()
233        self.enable_aperture()
234        self.set_values()
235       
236    def remove_collimation(self, event):
237        """
238            Remove collimation to data's list of collimation
239        """
240        if self.collimation_cbox.IsEnabled():
241            if self.collimation_cbox.GetCount() > 0:
242                position = self.collimation_cbox.GetCurrentSelection()
243                collimation = self.collimation_cbox.GetClientData(position)
244                if collimation in self._collimation:
245                    self._collimation.remove(collimation)
246                    self.collimation_cbox.Delete(position) 
247                    #set the combo box box the next available item
248                    position = self.collimation_cbox.GetCount()
249                    if position > 0:
250                        position -= 1 
251                    self.collimation_cbox.SetSelection(position)
252        if not self._collimation and self.collimation_cbox.GetCount() == 0:       
253            self.bt_add_aperture.Disable() 
254            self.name_tcl.Clear()
255            self.length_tcl.Clear()
256            self.length_unit_tcl.Clear()
257            self.aperture_cbox.Clear()
258            self.aperture_cbox.Disable()
259        #disable or enable the combo box when necessary
260        self.enable_collimation()
261        self.enable_aperture()
262       
263    def on_select_collimation(self, event):
264        """
265           fill the control on the panel according to the current  selected collimation
266        """
267        self.set_values()
268        self.fill_aperture_combox()
269        self.enable_aperture()
270   
271    def enable_collimation(self):
272        """
273            Enable /disable widgets related to collimation
274        """
275        if self._collimation is not None and self.collimation_cbox.GetCount() > 0:
276            self.collimation_cbox.Enable()
277            self.bt_remove_collimation.Enable()
278            n_collimation = self.collimation_cbox.GetCount()
279            collimation_hint_txt = 'collimations available: %s '%str(n_collimation)
280            if len(self._collimation) > 0:
281                self.bt_remove_collimation.Enable()
282            else:
283                self.bt_remove_collimation.Disable()
284        else:
285            self.collimation_cbox.Disable()
286            self.bt_remove_collimation.Disable()
287            collimation_hint_txt = 'No collimation is available for this data.'
288        self.collimation_txt.SetLabel(collimation_hint_txt)
289           
290   
291    def reset_collimation_combobox(self, edited_collimation):
292        """
293            take all edited editor and reset clientdata of collimation combo box
294        """
295        for position in range(self.collimation_cbox.GetCount()):
296            collimation = self.collimation_cbox.GetClientData(position)
297            if collimation == edited_collimation:
298                collimation = edited_collimation
299                self.collimation_cbox.SetString(position, str(collimation.name)) 
300                self.collimation_cbox.SetClientData(position, collimation)
301                self.collimation_cbox.SetStringSelection(str(collimation.name)) 
302         
303    def add_aperture(self, event):
304        """
305            Append empty aperture to data's list of aperture
306        """
307        collimation, _, _ = self.get_current_collimation()
308        if not self.aperture_cbox.IsEnabled():
309            self.aperture_cbox.Enable()
310        aperture = Aperture()
311        collimation.aperture.append(aperture)
312        position = self.aperture_cbox.Append(str(aperture.name))
313        self.aperture_cbox.SetClientData(position, aperture)
314        self.aperture_cbox.SetSelection(position) 
315        self.enable_aperture()
316       
317    def edit_aperture(self, event):
318        """
319            Edit the selected aperture
320        """
321        if self._collimation is None or not self.aperture_cbox.IsEnabled():
322            return 
323        position = self.aperture_cbox.GetSelection() 
324        if position != wx.NOT_FOUND:
325            name = self.aperture_cbox.GetStringSelection() 
326            aperture = self.aperture_cbox.GetClientData(position)
327            dlg = ApertureDialog(parent=self, aperture=aperture)
328            dlg.set_manager(self)
329            dlg.ShowModal()
330           
331    def remove_aperture(self, event):
332        """
333            Remove aperture to data's list of aperture
334        """
335        if self._collimation is None or not self._collimation:
336            return
337        collimation, _, _ = self.get_current_collimation()
338        if self.aperture_cbox.IsEnabled():
339            if self.aperture_cbox.GetCount() > 1:
340                position = self.aperture_cbox.GetCurrentSelection()
341                aperture = self.aperture_cbox.GetClientData(position)
342                if aperture in collimation.aperture:
343                    collimation.aperture.remove(aperture)
344                    self.aperture_cbox.Delete(position) 
345                    #set the combo box box the next available item
346                    position = self.aperture_cbox.GetCount()
347                    if position > 0:
348                        position -= 1 
349                    self.aperture_cbox.SetSelection(position)
350                   
351        #disable or enable the combo box when necessary
352        self.enable_aperture()
353       
354    def set_aperture(self, aperture):
355        """
356            set aperture for data
357        """
358        if self._collimation is None or not self._collimation:
359            return
360        collimation, _, _ = self.get_current_collimation()
361        if collimation.aperture:
362            for item in collimation.aperture:
363                if item == aperture:
364                    item = aperture
365                    self.reset_aperture_combobox(edited_aperture=aperture)
366                    return
367               
368    def enable_aperture(self):
369        """
370            Enable /disable widgets crelated to aperture
371        """
372        collimation, _, _ = self.get_current_collimation()
373        if  self.aperture_cbox.GetCount() > 0:
374            self.aperture_cbox.Enable()
375            self.bt_edit_aperture.Enable()
376            self.bt_remove_aperture.Enable()
377            n_aperture = self.aperture_cbox.GetCount()
378            aperture_hint_txt = 'apertures available: %s '%str(n_aperture)
379            if len(collimation.aperture) > 0:
380                self.bt_remove_aperture.Enable()
381            else:
382                self.bt_remove_aperture.Disable()
383        else:
384            self.aperture_cbox.Disable()
385            self.bt_edit_aperture.Disable()
386            self.bt_remove_aperture.Disable()
387            aperture_hint_txt = 'No aperture is available for this data.'
388        self.aperture_txt.SetLabel(aperture_hint_txt)
389   
390    def reset_aperture_combobox(self, edited_aperture):
391        """
392            take all edited editor and reset clientdata of aperture combo box
393        """
394        for position in range(self.aperture_cbox.GetCount()):
395            aperture = self.aperture_cbox.GetClientData(position)
396            if aperture == edited_aperture:
397                aperture = edited_aperture
398                self.aperture_cbox.SetString(position, str(aperture.name)) 
399                self.aperture_cbox.SetClientData(position, aperture)
400                self.aperture_cbox.SetStringSelection(str(aperture.name)) 
401               
402    def fill_aperture_combox(self):
403        """
404            fill the current combobox with the available aperture
405        """
406        self.aperture_cbox.Clear()
407        collimation, _, _ = self.get_current_collimation()
408        if collimation is None or not collimation.aperture:
409            return
410        for aperture in collimation.aperture:
411            pos = self.aperture_cbox.Append(str(aperture.name))
412            self.aperture_cbox.SetClientData(pos, aperture)
413            self.aperture_cbox.SetSelection(pos)
414            self.aperture_cbox.SetStringSelection(str(aperture.name)) 
415         
416    def set_manager(self, manager):
417        """   
418            Set manager of this window
419        """
420        self.manager = manager
421       
422    def set_values(self):
423        """
424            take the collimation values of the current data and display them
425            through the panel
426        """
427        collimation, _, _ = self.get_current_collimation()
428        if collimation is None:
429            self.bt_add_aperture.Disable()
430            self.length_tcl.SetValue("")
431            self.name_tcl.SetValue("")
432            self.length_unit_tcl.SetValue("")
433            return
434        #Name
435        self.name_tcl.SetValue(str(collimation.name))
436        #length
437        self.length_tcl.SetValue(str(collimation.length))
438        #Length unit
439        self.length_unit_tcl.SetValue(str(collimation.length_unit))
440       
441    def get_collimation(self):
442        """
443            return the current collimation
444        """
445        return self._collimation
446   
447    def get_notes(self):
448        """
449            return notes
450        """
451        return self._notes
452   
453    def on_change_name(self):
454        """
455            Change name
456        """
457        collimation, collimation_name, position = self.get_current_collimation()
458        if collimation is None: 
459            return
460        #Change the name of the collimation
461        name = self.name_tcl.GetValue().lstrip().rstrip()
462        if name == "" or name == str(None):
463            name = None
464        if collimation.name != name:
465            self._notes += "Change collimation 's "
466            self._notes += "name from %s to %s \n"%(collimation.name, name)
467            collimation.name = name
468            self.collimation_cbox.SetString(position, str(collimation.name)) 
469            self.collimation_cbox.SetClientData(position, collimation)
470            self.collimation_cbox.SetStringSelection(str(collimation.name)) 
471   
472    def on_change_length(self):
473        """
474            Change the length
475        """
476        collimation, collimation_name, position = self.get_current_collimation()
477        if collimation is None: 
478            return
479        #Change length 
480        length = self.length_tcl.GetValue().lstrip().rstrip()
481        if length == "" or length == str(None):
482            length = None
483            collimation.length = length
484        else:
485            if check_float(self.length_tcl):
486                if collimation.length != float(length):
487                    self._notes += "Change Collimation length from "
488                    self._notes += "%s to %s \n"%(collimation.length, length)
489                    collimation.length  = float(length)
490            else:
491                self._notes += "Error: Expected a float for collimation length "
492                self._notes += "won't changes length from "
493                self._notes += "%s to %s"%(collimation.length, length)
494        #change length  unit
495        unit = self.length_unit_tcl.GetValue().lstrip().rstrip()
496        if collimation.length_unit != unit:
497            self._notes += " Change length's unit from "
498            self._notes += "%s to %s"%(collimation.length_unit, unit)
499            collimation.length_unit = unit
500   
501    def on_click_apply(self, event):
502        """
503            Apply user values to the collimation
504        """
505        self.on_change_name()
506        self.on_change_length()
507        self.set_values()
508        if self.manager is not None:
509            self.manager.set_collimation(self._collimation, self._notes)
510       
511    def on_click_cancel(self, event):
512        """
513            leave the collimation as it is and close
514        """
515        self._collimation = deepcopy(self._reset_collimation)
516        self.set_values()
517        if self.manager is not None:
518             self.manager.set_collimation(self._collimation)
519       
520 
521if __name__ =="__main__":
522
523    app  = wx.App()
524    dlg = CollimationDialog(collimation=[Collimation()])
525    dlg.ShowModal()
526    app.MainLoop()
527 
Note: See TracBrowser for help on using the repository browser.