source: sasview/src/sas/sasgui/perspectives/simulation/ShapeParameters.py @ 3ec78a1

Last change on this file since 3ec78a1 was 5251ec6, checked in by Paul Kienzle <pkienzle@…>, 6 years ago

improved support for py37 in sasgui

  • 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 sys
13from copy import deepcopy
[5251ec6]14
15import wx
16import wx.lib.newevent
17
18from . import SimCanvas
[eaeb13e]19
20(CreateShapeEvent, EVT_ADD_SHAPE) = wx.lib.newevent.NewEvent()
21(EditShapeEvent, EVT_EDIT_SHAPE)  = wx.lib.newevent.NewEvent()
[6ef7ac5a]22(DelShapeEvent, EVT_DEL_SHAPE)    = wx.lib.newevent.NewEvent()
23(QRangeEvent, EVT_Q_RANGE)        = wx.lib.newevent.NewEvent() 
24(PtDensityEvent, EVT_PT_DENSITY)  = wx.lib.newevent.NewEvent() 
[eaeb13e]25
26class ShapeParameterPanel(wx.Panel):
27    #TODO: show units
28    #TODO: order parameters properly
29    CENTER_PANE = True
30   
[6ef7ac5a]31    def __init__(self, parent, q_min=0.001, q_max=0.5, q_npts=10, pt_density=0.1, *args, **kwargs):
[eaeb13e]32        wx.Panel.__init__(self, parent, *args, **kwargs)
33       
34        self.window_name = "ShapeParams"
35        self.window_caption = "Shape parameter"
36       
37     
38        self.params = {}
39        self.parent = parent
40        self.type = None
41        self.listeners = []
42        self.parameters = []
43        self.bck = wx.GridBagSizer(5,5)
44        self.SetSizer(self.bck)
45       
46        # position and orientation ctrl
47        self.xctrl = None
48        self.yctrl = None
49        self.zctrl = None
50        self.actrl = None
51        self.bctrl = None
52        self.cctrl = None
53               
54        # Sizer to hold the shape parameters
55        self.shape_sizer = wx.GridBagSizer(5,5)
56       
[cb78690]57        ny = 0       
[eaeb13e]58        title = wx.StaticText(self, -1, "[Temporary form]", style=wx.ALIGN_LEFT)
[cb78690]59        self.bck.Add(title, (ny,0), (1,2), flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border=15)
60       
61        # Shape list
62        shape_text = wx.StaticText(self, -1, "Geometric shape", style=wx.ALIGN_LEFT)
63        self.shape_list = SimCanvas.getShapes()
64        value_list = []
65        for item in self.shape_list:
66            value_list.append(item['name'])
67           
68        self.model_combo = wx.ComboBox(self, -1, value=value_list[0], choices=value_list, style=wx.CB_READONLY)
[6ef7ac5a]69        self.model_combo.SetToolTip(wx.ToolTip("Select a geometric shape from the drop-down list"))
[eaeb13e]70       
[cb78690]71        ny+=1
72        self.bck.Add(shape_text, (ny,0), flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border=15)
73        self.bck.Add(self.model_combo, (ny,1), flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border=15)
74        wx.EVT_COMBOBOX(self.model_combo,-1, self._on_select_shape)
75   
76        # Placeholder for parameter form
77        ny+=1
78        self.bck.Add(self.shape_sizer, (ny,0), (1,2), flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border=0)   
[eaeb13e]79       
80        # Point density control
81        point_density_text = wx.StaticText(self, -1, "Point density", style=wx.ALIGN_LEFT)
[cb78690]82        ny+=1
83        self.bck.Add(point_density_text, (ny,0), flag = wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border = 15)
[eaeb13e]84        self.point_density_ctrl = wx.TextCtrl(self, -1, size=(40,20), style=wx.TE_PROCESS_ENTER)
[6ef7ac5a]85        self.point_density_ctrl.SetValue(str(pt_density))
86        self.point_density_ctrl.SetToolTip(wx.ToolTip("Enter the number of real-space points per Angstrom cube"))
87        self.point_density_ctrl.Bind(wx.EVT_TEXT_ENTER, self._on_density_changed)
88        self.point_density_ctrl.Bind(wx.EVT_KILL_FOCUS, self._on_density_changed)
[cb78690]89        self.bck.Add(self.point_density_ctrl, (ny,1), flag = wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border = 15)
[eaeb13e]90       
[cb78690]91        # Q range
92        q_min_text = wx.StaticText(self, -1, "Q min", style=wx.ALIGN_LEFT)
93        ny+=1
94        self.bck.Add(q_min_text, (ny,0), flag = wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border = 15)
95        self.q_min_ctrl = wx.TextCtrl(self, -1, size=(40,20), style=wx.TE_PROCESS_ENTER)
[6ef7ac5a]96        self.q_min_ctrl.SetValue(str(q_min))
97        self.q_min_ctrl.SetToolTip(wx.ToolTip("Enter the minimum Q value to be simulated"))
98        self.q_min_ctrl.Bind(wx.EVT_TEXT_ENTER, self._on_q_range_changed)
99        self.q_min_ctrl.Bind(wx.EVT_KILL_FOCUS, self._on_q_range_changed)
[cb78690]100        self.bck.Add(self.q_min_ctrl, (ny,1), flag = wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border = 15)
[eaeb13e]101       
[cb78690]102        q_max_text = wx.StaticText(self, -1, "Q max", style=wx.ALIGN_LEFT)
103        self.bck.Add(q_max_text, (ny,2), flag = wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border = 15)
104        self.q_max_ctrl = wx.TextCtrl(self, -1, size=(40,20), style=wx.TE_PROCESS_ENTER)
[6ef7ac5a]105        self.q_max_ctrl.SetValue(str(q_max))
106        self.q_min_ctrl.SetToolTip(wx.ToolTip("Enter the maximum Q value to be simulated"))
107        self.q_max_ctrl.Bind(wx.EVT_TEXT_ENTER, self._on_q_range_changed)
108        self.q_max_ctrl.Bind(wx.EVT_KILL_FOCUS, self._on_q_range_changed)
[cb78690]109        self.bck.Add(self.q_max_ctrl, (ny,3), flag = wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border = 15)
110       
[6ef7ac5a]111        q_npts_text = wx.StaticText(self, -1, "No. of Q pts", style=wx.ALIGN_LEFT)
112        self.bck.Add(q_npts_text, (ny,4), flag = wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border = 15)
113        self.q_npts_ctrl = wx.TextCtrl(self, -1, size=(40,20), style=wx.TE_PROCESS_ENTER)
114        self.q_npts_ctrl.SetValue(str(q_npts))
115        self.q_min_ctrl.SetToolTip(wx.ToolTip("Enter the number of Q points to be simulated"))
116        self.q_npts_ctrl.Bind(wx.EVT_TEXT_ENTER, self._on_q_range_changed)
117        self.q_npts_ctrl.Bind(wx.EVT_KILL_FOCUS, self._on_q_range_changed)
118        self.bck.Add(self.q_npts_ctrl, (ny,5), flag = wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border = 15)
119       
[cb78690]120        # Shape List
121        # Internal counter of shapes in the listbox
122        self.counter = 0
123        # Buffer filled flag
124        self.buffer_filled = False
125        # Save current flag
126        self.current_saved = False       
127         
128        id = wx.NewId()
129        shape_listbox_text = wx.StaticText(self, -1, "List of shapes on 3D canvas", style=wx.ALIGN_LEFT)
130        self.shape_listbox = wx.ListBox(self, id, wx.DefaultPosition, (295, 200), 
131                                   [], wx.LB_SINGLE | wx.LB_HSCROLL)
132       
133        # Listen to history events
134        self.parent.Bind(EVT_ADD_SHAPE, self._on_add_shape_to_listbox)
135        self.shape_listbox.Bind(wx.EVT_LISTBOX, self._on_select_from_listbox, id=id)
136        self.shape_listbox.Bind(wx.EVT_CONTEXT_MENU, self._on_listbox_context_menu, id=id)
137       
138        ny+=1
139        self.bck.Add(shape_listbox_text, (ny,0), (1,2), flag = wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border = 15)
140        ny+=1
141        self.bck.Add(self.shape_listbox, (ny,0), (1,5), flag = wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border = 15)
[eaeb13e]142       
143        self.current_shape = None
144       
[cb78690]145        # Default shape
146        if type(self.shape_list)==list and len(self.shape_list)>0:
147            shape = SimCanvas.getShapeClassByName(self.shape_list[0]['name'])()
148            self.editShape(shape)                       
149
150    def _on_select_shape(self, event):
151        shape = SimCanvas.getShapeClassByName(self.shape_list[event.GetEventObject().GetSelection()]['name'])()
152        self.editShape(shape)   
[eaeb13e]153
[6ef7ac5a]154    def _on_density_changed(self, event):
[eaeb13e]155        """
156            Process event that might mean a change of the simulation point density
157        """
[6ef7ac5a]158        npts  = self._readCtrlFloat(self.point_density_ctrl)
159        if npts is not None:
160            event = PtDensityEvent(npts=npts)
161            wx.PostEvent(self.parent, event)
[eaeb13e]162           
[6ef7ac5a]163    def _on_q_range_changed(self, event):
[eaeb13e]164        """
[6ef7ac5a]165            Process event that might mean a change in Q range
166            @param event: EVT_Q_RANGE event
[eaeb13e]167        """
[6ef7ac5a]168        q_min = self._readCtrlFloat(self.q_min_ctrl)
169        q_max = self._readCtrlFloat(self.q_max_ctrl)
170        npts  = self._readCtrlInt(self.q_npts_ctrl)
171        if q_min is not None or q_max is not None or npts is not None:
172            event = QRangeEvent(q_min=q_min, q_max=q_max, npts=npts)
173            wx.PostEvent(self.parent, event)
174           
[eaeb13e]175    def _onEditShape(self, evt):
176        """
177            Process an EVT_EDIT_SHAPE event
178            @param evt: EVT_EDIT_SHAPE object
179        """
180        evt.Skip()
181        self.editShape(evt.shape, False)
182       
183    def editShape(self, shape=None, new=True):
184        """
185            Rebuild the panel
186        """
187        self.current_shape = shape
188        self.shape_sizer.Clear(True) 
189        #self.type = type 
190       
191        if shape==None:
192            title = wx.StaticText(self, -1, "Use menu to add a shapes", style=wx.ALIGN_LEFT)
193            self.shape_sizer.Add(title, (0,0), (1,2), flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border=15)
194
195        else:
196            if new==False:
197                title = wx.StaticText(self, -1, "Edit shape parameters", style=wx.ALIGN_LEFT)
198            else:
199                title = wx.StaticText(self, -1, "Create shape from parameters", style=wx.ALIGN_LEFT)
200               
201            self.shape_sizer.Add(title, (0,0), (1,2), flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border=15)
202           
203            n = 1
204            self.parameters = []
205           
[5251ec6]206            for item in sorted(shape.params.keys()):
[eaeb13e]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
[5251ec6]395        except Exception as exc:
[9c3d784]396            print("Could not create")
[5251ec6]397            print(exc)
[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]))
Note: See TracBrowser for help on using the repository browser.