source: sasview/src/sas/sasgui/perspectives/simulation/ShapeParameters.py @ 84ac3f1

magnetic_scattrelease-4.2.2ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249unittest-saveload
Last change on this file since 84ac3f1 was a1b8fee, checked in by andyfaff, 7 years ago

MAINT: from future import print_function

  • Property mode set to 100644
File size: 20.9 KB
RevLine 
[eaeb13e]1"""
2This software was developed by the University of Tennessee as part of the
3Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
4project funded by the US National Science Foundation.
5
6See the license text in license.txt
7
8copyright 2009, University of Tennessee
9"""
[a1b8fee]10from __future__ import print_function
11
[eaeb13e]12import wx
13import sys
14import wx.lib.newevent
15from copy import deepcopy
16import SimCanvas
17
18(CreateShapeEvent, EVT_ADD_SHAPE) = wx.lib.newevent.NewEvent()
19(EditShapeEvent, EVT_EDIT_SHAPE)  = wx.lib.newevent.NewEvent()
[6ef7ac5a]20(DelShapeEvent, EVT_DEL_SHAPE)    = wx.lib.newevent.NewEvent()
21(QRangeEvent, EVT_Q_RANGE)        = wx.lib.newevent.NewEvent() 
22(PtDensityEvent, EVT_PT_DENSITY)  = wx.lib.newevent.NewEvent() 
[eaeb13e]23
24class ShapeParameterPanel(wx.Panel):
25    #TODO: show units
26    #TODO: order parameters properly
27    CENTER_PANE = True
28   
[6ef7ac5a]29    def __init__(self, parent, q_min=0.001, q_max=0.5, q_npts=10, pt_density=0.1, *args, **kwargs):
[eaeb13e]30        wx.Panel.__init__(self, parent, *args, **kwargs)
31       
32        self.window_name = "ShapeParams"
33        self.window_caption = "Shape parameter"
34       
35     
36        self.params = {}
37        self.parent = parent
38        self.type = None
39        self.listeners = []
40        self.parameters = []
41        self.bck = wx.GridBagSizer(5,5)
42        self.SetSizer(self.bck)
43       
44        # position and orientation ctrl
45        self.xctrl = None
46        self.yctrl = None
47        self.zctrl = None
48        self.actrl = None
49        self.bctrl = None
50        self.cctrl = None
51               
52        # Sizer to hold the shape parameters
53        self.shape_sizer = wx.GridBagSizer(5,5)
54       
[cb78690]55        ny = 0       
[eaeb13e]56        title = wx.StaticText(self, -1, "[Temporary form]", style=wx.ALIGN_LEFT)
[cb78690]57        self.bck.Add(title, (ny,0), (1,2), flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border=15)
58       
59        # Shape list
60        shape_text = wx.StaticText(self, -1, "Geometric shape", style=wx.ALIGN_LEFT)
61        self.shape_list = SimCanvas.getShapes()
62        value_list = []
63        for item in self.shape_list:
64            value_list.append(item['name'])
65           
66        self.model_combo = wx.ComboBox(self, -1, value=value_list[0], choices=value_list, style=wx.CB_READONLY)
[6ef7ac5a]67        self.model_combo.SetToolTip(wx.ToolTip("Select a geometric shape from the drop-down list"))
[eaeb13e]68       
[cb78690]69        ny+=1
70        self.bck.Add(shape_text, (ny,0), flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border=15)
71        self.bck.Add(self.model_combo, (ny,1), flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border=15)
72        wx.EVT_COMBOBOX(self.model_combo,-1, self._on_select_shape)
73   
74        # Placeholder for parameter form
75        ny+=1
76        self.bck.Add(self.shape_sizer, (ny,0), (1,2), flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border=0)   
[eaeb13e]77       
78        # Point density control
79        point_density_text = wx.StaticText(self, -1, "Point density", style=wx.ALIGN_LEFT)
[cb78690]80        ny+=1
81        self.bck.Add(point_density_text, (ny,0), flag = wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border = 15)
[eaeb13e]82        self.point_density_ctrl = wx.TextCtrl(self, -1, size=(40,20), style=wx.TE_PROCESS_ENTER)
[6ef7ac5a]83        self.point_density_ctrl.SetValue(str(pt_density))
84        self.point_density_ctrl.SetToolTip(wx.ToolTip("Enter the number of real-space points per Angstrom cube"))
85        self.point_density_ctrl.Bind(wx.EVT_TEXT_ENTER, self._on_density_changed)
86        self.point_density_ctrl.Bind(wx.EVT_KILL_FOCUS, self._on_density_changed)
[cb78690]87        self.bck.Add(self.point_density_ctrl, (ny,1), flag = wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border = 15)
[eaeb13e]88       
[cb78690]89        # Q range
90        q_min_text = wx.StaticText(self, -1, "Q min", style=wx.ALIGN_LEFT)
91        ny+=1
92        self.bck.Add(q_min_text, (ny,0), flag = wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border = 15)
93        self.q_min_ctrl = wx.TextCtrl(self, -1, size=(40,20), style=wx.TE_PROCESS_ENTER)
[6ef7ac5a]94        self.q_min_ctrl.SetValue(str(q_min))
95        self.q_min_ctrl.SetToolTip(wx.ToolTip("Enter the minimum Q value to be simulated"))
96        self.q_min_ctrl.Bind(wx.EVT_TEXT_ENTER, self._on_q_range_changed)
97        self.q_min_ctrl.Bind(wx.EVT_KILL_FOCUS, self._on_q_range_changed)
[cb78690]98        self.bck.Add(self.q_min_ctrl, (ny,1), flag = wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border = 15)
[eaeb13e]99       
[cb78690]100        q_max_text = wx.StaticText(self, -1, "Q max", style=wx.ALIGN_LEFT)
101        self.bck.Add(q_max_text, (ny,2), flag = wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border = 15)
102        self.q_max_ctrl = wx.TextCtrl(self, -1, size=(40,20), style=wx.TE_PROCESS_ENTER)
[6ef7ac5a]103        self.q_max_ctrl.SetValue(str(q_max))
104        self.q_min_ctrl.SetToolTip(wx.ToolTip("Enter the maximum Q value to be simulated"))
105        self.q_max_ctrl.Bind(wx.EVT_TEXT_ENTER, self._on_q_range_changed)
106        self.q_max_ctrl.Bind(wx.EVT_KILL_FOCUS, self._on_q_range_changed)
[cb78690]107        self.bck.Add(self.q_max_ctrl, (ny,3), flag = wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border = 15)
108       
[6ef7ac5a]109        q_npts_text = wx.StaticText(self, -1, "No. of Q pts", style=wx.ALIGN_LEFT)
110        self.bck.Add(q_npts_text, (ny,4), flag = wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border = 15)
111        self.q_npts_ctrl = wx.TextCtrl(self, -1, size=(40,20), style=wx.TE_PROCESS_ENTER)
112        self.q_npts_ctrl.SetValue(str(q_npts))
113        self.q_min_ctrl.SetToolTip(wx.ToolTip("Enter the number of Q points to be simulated"))
114        self.q_npts_ctrl.Bind(wx.EVT_TEXT_ENTER, self._on_q_range_changed)
115        self.q_npts_ctrl.Bind(wx.EVT_KILL_FOCUS, self._on_q_range_changed)
116        self.bck.Add(self.q_npts_ctrl, (ny,5), flag = wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border = 15)
117       
[cb78690]118        # Shape List
119        # Internal counter of shapes in the listbox
120        self.counter = 0
121        # Buffer filled flag
122        self.buffer_filled = False
123        # Save current flag
124        self.current_saved = False       
125         
126        id = wx.NewId()
127        shape_listbox_text = wx.StaticText(self, -1, "List of shapes on 3D canvas", style=wx.ALIGN_LEFT)
128        self.shape_listbox = wx.ListBox(self, id, wx.DefaultPosition, (295, 200), 
129                                   [], wx.LB_SINGLE | wx.LB_HSCROLL)
130       
131        # Listen to history events
132        self.parent.Bind(EVT_ADD_SHAPE, self._on_add_shape_to_listbox)
133        self.shape_listbox.Bind(wx.EVT_LISTBOX, self._on_select_from_listbox, id=id)
134        self.shape_listbox.Bind(wx.EVT_CONTEXT_MENU, self._on_listbox_context_menu, id=id)
135       
136        ny+=1
137        self.bck.Add(shape_listbox_text, (ny,0), (1,2), flag = wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border = 15)
138        ny+=1
139        self.bck.Add(self.shape_listbox, (ny,0), (1,5), flag = wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border = 15)
[eaeb13e]140       
141        self.current_shape = None
142       
[cb78690]143        # Default shape
144        if type(self.shape_list)==list and len(self.shape_list)>0:
145            shape = SimCanvas.getShapeClassByName(self.shape_list[0]['name'])()
146            self.editShape(shape)                       
147
148    def _on_select_shape(self, event):
149        shape = SimCanvas.getShapeClassByName(self.shape_list[event.GetEventObject().GetSelection()]['name'])()
150        self.editShape(shape)   
[eaeb13e]151
[6ef7ac5a]152    def _on_density_changed(self, event):
[eaeb13e]153        """
154            Process event that might mean a change of the simulation point density
155        """
[6ef7ac5a]156        npts  = self._readCtrlFloat(self.point_density_ctrl)
157        if npts is not None:
158            event = PtDensityEvent(npts=npts)
159            wx.PostEvent(self.parent, event)
[eaeb13e]160           
[6ef7ac5a]161    def _on_q_range_changed(self, event):
[eaeb13e]162        """
[6ef7ac5a]163            Process event that might mean a change in Q range
164            @param event: EVT_Q_RANGE event
[eaeb13e]165        """
[6ef7ac5a]166        q_min = self._readCtrlFloat(self.q_min_ctrl)
167        q_max = self._readCtrlFloat(self.q_max_ctrl)
168        npts  = self._readCtrlInt(self.q_npts_ctrl)
169        if q_min is not None or q_max is not None or npts is not None:
170            event = QRangeEvent(q_min=q_min, q_max=q_max, npts=npts)
171            wx.PostEvent(self.parent, event)
172           
[eaeb13e]173    def _onEditShape(self, evt):
174        """
175            Process an EVT_EDIT_SHAPE event
176            @param evt: EVT_EDIT_SHAPE object
177        """
178        evt.Skip()
179        self.editShape(evt.shape, False)
180       
181    def editShape(self, shape=None, new=True):
182        """
183            Rebuild the panel
184        """
185        self.current_shape = shape
186        self.shape_sizer.Clear(True) 
187        #self.type = type 
188       
189        if shape==None:
190            title = wx.StaticText(self, -1, "Use menu to add a shapes", style=wx.ALIGN_LEFT)
191            self.shape_sizer.Add(title, (0,0), (1,2), flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border=15)
192
193        else:
194            if new==False:
195                title = wx.StaticText(self, -1, "Edit shape parameters", style=wx.ALIGN_LEFT)
196            else:
197                title = wx.StaticText(self, -1, "Create shape from parameters", style=wx.ALIGN_LEFT)
198               
199            self.shape_sizer.Add(title, (0,0), (1,2), flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border=15)
200           
201            n = 1
202            self.parameters = []
203            keys = shape.params.keys()
204            keys.sort()
205           
206            for item in keys:
207                if item in ['contrast', 'order']:
208                    continue
209                n += 1
210                text = wx.StaticText(self, -1, item, style=wx.ALIGN_LEFT)
211                self.shape_sizer.Add(text, (n-1,0), flag = wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border = 15)
212                ctl = wx.TextCtrl(self, -1, size=(40,20), style=wx.TE_PROCESS_ENTER)
213               
214               
215                ctl.SetValue(str(shape.params[item]))
216                self.Bind(wx.EVT_TEXT_ENTER, self.onTextEnter)
217                ctl.Bind(wx.EVT_KILL_FOCUS, self.onTextEnter)
218                self.parameters.append([item, ctl])
219                self.shape_sizer.Add(ctl, (n-1,1), flag=wx.TOP|wx.BOTTOM, border = 0)
220               
221                # Units
222                units = wx.StaticText(self, -1, shape.details[item], style=wx.ALIGN_LEFT)
223                self.shape_sizer.Add(units, (n-1,2), flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border = 15)
224
225            for item in ['contrast', 'order']:
226                n += 1
227                text = wx.StaticText(self, -1, item, style=wx.ALIGN_LEFT)
228                self.shape_sizer.Add(text, (n-1,0), flag = wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border = 15)
229                ctl = wx.TextCtrl(self, -1, size=(40,20), style=wx.TE_PROCESS_ENTER)
230               
231               
232                ctl.SetValue(str(shape.params[item]))
233                self.Bind(wx.EVT_TEXT_ENTER, self.onTextEnter)
234                ctl.Bind(wx.EVT_KILL_FOCUS, self.onTextEnter)
235                self.parameters.append([item, ctl])
236                self.shape_sizer.Add(ctl, (n-1,1), flag=wx.TOP|wx.BOTTOM, border = 0)
237               
238                # Units
239                units = wx.StaticText(self, -1, shape.details[item], style=wx.ALIGN_LEFT)
240                self.shape_sizer.Add(units, (n-1,2), flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border = 15)
241               
242               
243            # Add position
244            n += 1
245           
246            pos_sizer = wx.GridBagSizer(0,0)
247           
248            text = wx.StaticText(self, -1, 'x', style=wx.ALIGN_LEFT)
249            pos_sizer.Add(text, (0,0), (1,1), flag = wx.LEFT|wx.ALIGN_CENTER, border = 15)
250            text = wx.StaticText(self, -1, 'y', style=wx.ALIGN_LEFT)
251            pos_sizer.Add(text, (0,1), (1,1), flag = wx.LEFT|wx.ALIGN_CENTER, border = 15)
252            text = wx.StaticText(self, -1, 'z', style=wx.ALIGN_LEFT)
253            pos_sizer.Add(text, (0,2), (1,1), flag = wx.LEFT|wx.ALIGN_CENTER, border = 15)
254           
255            self.xctrl = wx.TextCtrl(self, -1, size=(40,20), style=wx.TE_PROCESS_ENTER)
256            self.xctrl.SetValue(str(shape.x))
257            self.xctrl.Bind(wx.EVT_KILL_FOCUS, self.onTextEnter)
258            pos_sizer.Add(self.xctrl, (1,0), (1,1), flag = wx.LEFT|wx.ALIGN_CENTER, border = 15)
259            self.yctrl = wx.TextCtrl(self, -1, size=(40,20), style=wx.TE_PROCESS_ENTER)
260            self.yctrl.SetValue(str(shape.y))
261            self.yctrl.Bind(wx.EVT_KILL_FOCUS, self.onTextEnter)
262            pos_sizer.Add(self.yctrl, (1,1), (1,1), flag = wx.LEFT|wx.ALIGN_CENTER, border = 15)
263            self.zctrl = wx.TextCtrl(self, -1, size=(40,20), style=wx.TE_PROCESS_ENTER)
264            self.zctrl.SetValue(str(shape.z))
265            self.zctrl.Bind(wx.EVT_KILL_FOCUS, self.onTextEnter)
266            pos_sizer.Add(self.zctrl, (1,2), (1,1), flag = wx.LEFT|wx.ALIGN_CENTER, border = 15)
267           
268            self.shape_sizer.Add(pos_sizer, (n-1, 0), (1,3), flag=wx.LEFT|wx.ALIGN_CENTER)
269           
270            # Add orientation
271            n += 1
272           
273            pos_sizer = wx.GridBagSizer(0,0)
274           
275            text = wx.StaticText(self, -1, 'theta_x', style=wx.ALIGN_LEFT)
276            pos_sizer.Add(text, (0,0), (1,1), flag = wx.LEFT|wx.ALIGN_CENTER, border = 15)
277            text = wx.StaticText(self, -1, 'theta_y', style=wx.ALIGN_LEFT)
278            pos_sizer.Add(text, (0,1), (1,1), flag = wx.LEFT|wx.ALIGN_CENTER, border = 15)
279            text = wx.StaticText(self, -1, 'theta_z', style=wx.ALIGN_LEFT)
280            pos_sizer.Add(text, (0,2), (1,1), flag = wx.LEFT|wx.ALIGN_CENTER, border = 15)
281           
282            self.actrl = wx.TextCtrl(self, -1, size=(40,20), style=wx.TE_PROCESS_ENTER)
283            self.actrl.SetValue(str(shape.theta_x))
284            self.actrl.Bind(wx.EVT_KILL_FOCUS, self.onTextEnter)
285            pos_sizer.Add(self.actrl, (1,0), (1,1), flag = wx.LEFT|wx.ALIGN_CENTER, border = 15)
286            self.bctrl = wx.TextCtrl(self, -1, size=(40,20), style=wx.TE_PROCESS_ENTER)
287            self.bctrl.SetValue(str(shape.theta_y))
288            self.bctrl.Bind(wx.EVT_KILL_FOCUS, self.onTextEnter)
289            pos_sizer.Add(self.bctrl, (1,1), (1,1), flag = wx.LEFT|wx.ALIGN_CENTER, border = 15)
290            self.cctrl = wx.TextCtrl(self, -1, size=(40,20), style=wx.TE_PROCESS_ENTER)
291            self.cctrl.SetValue(str(shape.theta_z))
292            self.cctrl.Bind(wx.EVT_KILL_FOCUS, self.onTextEnter)
293            pos_sizer.Add(self.cctrl, (1,2), (1,1), flag = wx.LEFT|wx.ALIGN_CENTER, border = 15)
294           
295            self.shape_sizer.Add(pos_sizer, (n-1, 0), (1,3), flag=wx.LEFT|wx.ALIGN_CENTER)
296           
297           
298            # Add a button to create the new shape on the canvas
299            n += 1
300            if new==True:
301                create = wx.Button(self, 1,"Create")
302                self.shape_sizer.Add(create, (n-1,1), (1,2), flag=wx.ALIGN_RIGHT|wx.ALL, border = 15)
303                self.Bind(wx.EVT_BUTTON, self._onCreate, id = 1)       
304            else:
305                create = wx.Button(self, 1,"Apply")
306                self.shape_sizer.Add(create, (n-1,1), (1,2), flag=wx.ALIGN_RIGHT|wx.ALL, border = 15)
307                self.Bind(wx.EVT_BUTTON, self._onEdited, id = 1)       
308               
309
310
311        self.shape_sizer.Layout()
312        self.shape_sizer.Fit(self)
[cb78690]313        try:
314            self.parent.GetSizer().Layout()
315        except:
[9c3d784]316            print("TODO: move the Layout call of editShape up to the caller")
[eaeb13e]317
318    def _readCtrlFloat(self, ctrl):
[6ef7ac5a]319        """
320            Parses a TextCtrl for a float value.
321            Returns None is the value hasn't changed or the value is not a float.
322            The control background turns pink if the value is not a float.
323           
324            @param ctrl: TextCtrl object
325        """
[eaeb13e]326        if ctrl.IsModified():
[6ef7ac5a]327            ctrl.SetModified(False)
[eaeb13e]328            str_value = ctrl.GetValue().lstrip().rstrip()
329            try:
330                flt_value = float(str_value)
331                ctrl.SetBackgroundColour(
332                        wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
333                ctrl.Refresh()
334                return flt_value
335            except:
336                ctrl.SetBackgroundColour("pink")
337                ctrl.Refresh()
338        return None
339
[6ef7ac5a]340    def _readCtrlInt(self, ctrl):
341        """
342            Parses a TextCtrl for a float value.
343            Returns None is the value hasn't changed or the value is not a float.
344            The control background turns pink if the value is not a float.
345           
346            @param ctrl: TextCtrl object
347        """
348        if ctrl.IsModified():
349            ctrl.SetModified(False)
350            str_value = ctrl.GetValue().lstrip().rstrip()
351            try:
352                int_value = int(str_value)
353                ctrl.SetBackgroundColour(
354                        wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
355                ctrl.Refresh()
356                return int_value
357            except:
358                ctrl.SetBackgroundColour("pink")
359                ctrl.Refresh()
360        return None
361
[eaeb13e]362    def _parseCtrl(self):
363        try:
364            # Position
365            tmp = self._readCtrlFloat(self.xctrl)
366            if not tmp==None:
367                self.current_shape.x = tmp
368               
369            tmp = self._readCtrlFloat(self.yctrl)
370            if not tmp==None:
371                self.current_shape.y = tmp
372               
373            tmp = self._readCtrlFloat(self.zctrl)
374            if not tmp==None:
375                self.current_shape.z = tmp
376               
377            # Orientation
378            tmp = self._readCtrlFloat(self.actrl)
379            if not tmp==None:
380                self.current_shape.theta_x = tmp
381               
382            tmp = self._readCtrlFloat(self.bctrl)
383            if not tmp==None:
384                self.current_shape.theta_y = tmp
385               
386            tmp = self._readCtrlFloat(self.cctrl)
387            if not tmp==None:
388                self.current_shape.theta_z = tmp
389               
390            # Parameters
391            for item in self.parameters:
392                tmp = self._readCtrlFloat(item[1])
393                if not tmp==None:
394                    self.current_shape.params[item[0]] = tmp
395        except:
[9c3d784]396            print("Could not create")
397            print(sys.exc_value)
[eaeb13e]398               
399    def _onCreate(self, evt):
400        """
401            Create a new shape with the parameters given by the user
402        """
403        self._parseCtrl()
404        event = CreateShapeEvent(shape=self.current_shape, new=True)
405        wx.PostEvent(self.parent, event)
406        self.editShape(self.current_shape, False)
407           
408       
409    def _onEdited(self, evt):
410        self._parseCtrl()
411        event = CreateShapeEvent(shape=self.current_shape, new=False)
412        wx.PostEvent(self.parent, event)
413        self.editShape(self.current_shape, False)
414
415    def onTextEnter(self, evt): 
416        """
417            Read text field to check values
418        """ 
419        self._readCtrlFloat(self.xctrl)
420        self._readCtrlFloat(self.yctrl)
421        self._readCtrlFloat(self.zctrl)
422        self._readCtrlFloat(self.actrl)
423        self._readCtrlFloat(self.bctrl)
424        self._readCtrlFloat(self.cctrl)
425        for item in self.parameters:
426            self._readCtrlFloat(item[1])
427 
[cb78690]428    #-- Methods to support list of shapes --
429    def _on_add_shape_to_listbox(self, event):
[eaeb13e]430        """
[cb78690]431            Process a new shape           
432            @param event: EVT_ADD_SHAPE event
[eaeb13e]433        """
[cb78690]434        event.Skip()
435        if event.new:
436            self.counter += 1
437            self.shape_listbox.Insert("%d: %s" % (self.counter, event.shape.name), 
438                                 self.shape_listbox.GetCount(), event.shape)
[eaeb13e]439
[cb78690]440    def _on_select_from_listbox(self, event):
[eaeb13e]441        """
[cb78690]442            Process item selection events
[eaeb13e]443        """
[cb78690]444        index = event.GetSelection()
445        view_name = self.shape_listbox.GetString(index)
446        self.editShape(shape=event.GetClientData(), new=False)
447        # The following event is bound to the SimPanel to highlight the shape in blue
448        #TODO: how come it doesn't work?
449        wx.PostEvent(self.parent, EditShapeEvent(shape=event.GetClientData()))
450        #TODO: select the shape from the drop down
[eaeb13e]451       
[cb78690]452    def _on_listbox_context_menu(self, event):
[eaeb13e]453        """
454            Popup context menu event
455        """
[cb78690]456        # Create context menu
[eaeb13e]457        popupmenu = wx.Menu()
[cb78690]458       
459        # Create an item to delete the selected shape from the canvas
460        id = wx.NewId()
461        popupmenu.Append(id, "&Remove Selected")
462        wx.EVT_MENU(self, id, self._on_remove_shape_from_listbox)
463       
464        # Create an item to rename a shape to a more user friendly name
465        #id = wx.NewId()
[eaeb13e]466        #popupmenu.Append(102, "&Rename Selected")
467        #wx.EVT_MENU(self, 102, self.onRename)
468
469        pos = event.GetPosition()
470        pos = self.ScreenToClient(pos)
[cb78690]471        self.PopupMenu(popupmenu, pos)       
472       
473    def _on_remove_shape_from_listbox(self, ev):
[eaeb13e]474        """
[cb78690]475            Remove an item
[eaeb13e]476        """
[cb78690]477        indices = self.shape_listbox.GetSelections()
478        if len(indices)>0:
479            name =  self.shape_listbox.GetClientData(indices[0]).name
480            self.shape_listbox.Delete(indices[0])
481            wx.PostEvent(self.parent, DelShapeEvent(id = name))
482       
483    def _on_rename_shape_from_listbox(self, ev):
[eaeb13e]484        """
[cb78690]485            Rename an item
[eaeb13e]486        """
[cb78690]487        indices = self.shape_listbox.GetSelections()
488        if len(indices)>0:
[9c3d784]489            print("NOT YET IMPLMENTED")
490            print("renaming", self.shape_listbox.GetString(indices[0]))
[eaeb13e]491               
Note: See TracBrowser for help on using the repository browser.