|
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.
|