From: <pki...@us...> - 2007-07-20 16:00:46
|
Revision: 3595 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3595&view=rev Author: pkienzle Date: 2007-07-20 09:00:40 -0700 (Fri, 20 Jul 2007) Log Message: ----------- Allow application to remove artists from the axes Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/artist.py trunk/matplotlib/lib/matplotlib/axes.py trunk/matplotlib/lib/matplotlib/backend_bases.py Modified: trunk/matplotlib/lib/matplotlib/artist.py =================================================================== --- trunk/matplotlib/lib/matplotlib/artist.py 2007-07-20 15:47:53 UTC (rev 3594) +++ trunk/matplotlib/lib/matplotlib/artist.py 2007-07-20 16:00:40 UTC (rev 3595) @@ -48,7 +48,34 @@ self._oid = 0 # an observer id self._propobservers = {} # a dict from oids to funcs self.axes = None + self._remove_method = None + def remove(self): + ''' + Remove the artist from the figure if possible. The effect will not + be visible until the figure is redrawn, e.g., with ax.draw_idle(). + Call ax.relim() to update the axes limits if desired. + + Note: relim() will not see collections even if the collection + was added to axes with autolim=True. + + Note: there is no support for removing the artist's legend entry. + ''' + + # There is no method to set the callback. Instead the parent should set + # the _remove_method attribute directly. This would be a protected + # attribute if Python supported that sort of thing. The callback + # has one parameter, which is the child to be removed. + if self._remove_method != None: + self._remove_method(self) + else: + raise NotImplementedError('cannot remove artist') + # TODO: the fix for the collections relim problem is to move the + # limits calculation into the artist itself, including the property + # of whether or not the artist should affect the limits. Then there + # will be no distinction between axes.add_line, axes.add_patch, etc. + # TODO: add legend support + def have_units(self): 'return True if units are set on the x or y axes' ax = self.axes Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2007-07-20 15:47:53 UTC (rev 3594) +++ trunk/matplotlib/lib/matplotlib/axes.py 2007-07-20 16:00:40 UTC (rev 3595) @@ -1093,7 +1093,8 @@ a.set_axes(self) self.artists.append(a) self._set_artist_props(a) - + a._remove_method = lambda h: self.artists.remove(h) + def add_collection(self, collection, autolim=False): 'add a Collection instance to Axes' label = collection.get_label() @@ -1104,8 +1105,8 @@ collection.set_clip_box(self.bbox) if autolim: self.update_datalim(collection.get_verts(self.transData)) - - + collection._remove_method = lambda h: self.collections.remove(h) + def add_line(self, line): 'Add a line to the list of plot lines' self._set_artist_props(line) @@ -1115,7 +1116,8 @@ if not line.get_label(): line.set_label('_line%d'%len(self.lines)) self.lines.append(line) - + line._remove_method = lambda h: self.lines.remove(h) + def _update_line_limits(self, line): xdata = line.get_xdata(orig=False) ydata = line.get_ydata(orig=False) @@ -1140,7 +1142,8 @@ p.set_clip_box(self.bbox) self._update_patch_limits(p) self.patches.append(p) - + p._remove_method = lambda h: self.patches.remove(h) + def _update_patch_limits(self, p): 'update the datalimits for patch p' xys = self._get_verts_in_data_coords( @@ -1152,7 +1155,8 @@ 'Add a table instance to the list of axes tables' self._set_artist_props(tab) self.tables.append(tab) - + tab._remove_method = lambda h: self.tables.remove(h) + def relim(self): 'recompute the datalimits based on current artists' self.dataLim.ignore(True) @@ -1161,7 +1165,7 @@ for p in self.patches: self._update_patch_limits(p) - + def update_datalim(self, xys): 'Update the data lim bbox with seq of xy tups or equiv. 2-D array' # if no data is set currently, the bbox will ignore its @@ -2148,8 +2152,9 @@ if fontdict is not None: t.update(fontdict) t.update(kwargs) self.texts.append(t) + t._remove_method = lambda h: self.texts.remove(h) + - #if t.get_clip_on(): t.set_clip_box(self.bbox) if kwargs.has_key('clip_on'): t.set_clip_box(self.bbox) return t Modified: trunk/matplotlib/lib/matplotlib/backend_bases.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backend_bases.py 2007-07-20 15:47:53 UTC (rev 3594) +++ trunk/matplotlib/lib/matplotlib/backend_bases.py 2007-07-20 16:00:40 UTC (rev 3595) @@ -873,13 +873,49 @@ self.scroll_pick_id = self.mpl_connect('scroll_event',self.pick) if False: - # highlight the artists that are hit - self.mpl_connect('motion_notify_event',self.hilite) + ## highlight the artists that are hit + self.mpl_connect('motion_notify_event',self.onHilite) + ## delete the artists that are clicked on + #self.mpl_disconnect(self.button_pick_id) + #self.mpl_connect('button_press_event',self.onRemove) - def hilite(self, ev): - """Mouse event processor which highlights the artists + def onRemove(self, ev): + """ + Mouse event processor which removes the top artist + under the cursor. Connect this to the mouse_press_event + using canvas.mpl_connect('mouse_press_event',canvas.onRemove) + """ + def sort_artists(artists): + # This depends on stable sort and artists returned + # from get_children in z order. + L = [ (h.zorder, h) for h in artists ] + L.sort() + return [ h for zorder, h in L ] + + # Find the top artist under the cursor + under = sort_artists(self.figure.hitlist(ev)) + h = None + if under: h = under[-1] + + # Try deleting that artist, or its parent if you + # can't delete the artist + while h: + print "Removing",h + if h.remove(): + self.draw_idle() + break + parent = None + for p in under: + if hasattr(p,'getchildren') and h in p.get_children(): + parent = p + break + h = parent + + def onHilite(self, ev): + """ + Mouse event processor which highlights the artists under the cursor. Connect this to the motion_notify_event - using canvas.mpl_connect('motion_notify_event',canvas.hilite) + using canvas.mpl_connect('motion_notify_event',canvas.onHilite) """ if not hasattr(self,'_active'): self._active = dict() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |