draggable annotation bug and fix

There seems to be a problem with the draggable annotation code when
the annotation is just clicked, and not dragged. If you run the
following code:

import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
ann = ax.annotate('local max', xy=(2, 1), xytext=(3,
1.5),arrowprops=dict(facecolor='black', shrink=0.05))
ann.draggable()
ax.set_ylim(-2,2)
ax.set_xlim(0,5)
plt.show()

And click (just a single click) the annotation (the words "local
max"), then resize your window a little to force a redraw. The
annotation flips to the bottom left corner.

The fix is in offsetbox.py, DraggableAnnotation.save_offset. If you
add a call to update_offset() as the last call of that routine,
everything is OK again. I think that finalize_offset is assuming that
self.annotation.text is in pixels before it starts working with it,
but when update_offset fails to get called (as the case with a click),
self.annotation.xytext is still in axes fraction coordinates.

   def save_offset(self):
        ann = self.annotation
        x, y = ann.xytext
        if isinstance(ann.textcoords, tuple):
            xcoord, ycoord = ann.textcoords
            x1, y1 = ann._get_xy(self.canvas.renderer, x, y, xcoord)
            x2, y2 = ann._get_xy(self.canvas.renderer, x, y, ycoord)
            ox0, oy0 = x1, y2
        else:
            ox0, oy0 = ann._get_xy(self.canvas.renderer, x, y, ann.textcoords)

        self.ox, self.oy = ox0, oy0
        self.annotation.textcoords = "figure pixels"
        self.update_offset(0.0,0.0) # <----------- add this!

It might be sufficient to just set self.annotation.xytext to
self.ox,self.oy instead of calling update_offset like I did above.

···

--
Daniel Hyams
dhyams@...287...

Thanks for reporting this.
This is now fixed in the v1.0.x-maint branch and in the master branch.

Regards,

-JJ

···

On Fri, Sep 16, 2011 at 9:43 AM, Daniel Hyams <dhyams@...287...> wrote:

There seems to be a problem with the draggable annotation code when
the annotation is just clicked, and not dragged. If you run the
following code:

import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
ann = ax.annotate('local max', xy=(2, 1), xytext=(3,
1.5),arrowprops=dict(facecolor='black', shrink=0.05))
ann.draggable()
ax.set_ylim(-2,2)
ax.set_xlim(0,5)
plt.show()

And click (just a single click) the annotation (the words "local
max"), then resize your window a little to force a redraw. The
annotation flips to the bottom left corner.

The fix is in offsetbox.py, DraggableAnnotation.save_offset. If you
add a call to update_offset() as the last call of that routine,
everything is OK again. I think that finalize_offset is assuming that
self.annotation.text is in pixels before it starts working with it,
but when update_offset fails to get called (as the case with a click),
self.annotation.xytext is still in axes fraction coordinates.

def save_offset(self):
ann = self.annotation
x, y = ann.xytext
if isinstance(ann.textcoords, tuple):
xcoord, ycoord = ann.textcoords
x1, y1 = ann._get_xy(self.canvas.renderer, x, y, xcoord)
x2, y2 = ann._get_xy(self.canvas.renderer, x, y, ycoord)
ox0, oy0 = x1, y2
else:
ox0, oy0 = ann._get_xy(self.canvas.renderer, x, y, ann.textcoords)

   self\.ox, self\.oy = ox0, oy0
   self\.annotation\.textcoords = &quot;figure pixels&quot;
   self\.update\_offset\(0\.0,0\.0\)  \# &lt;\-\-\-\-\-\-\-\-\-\-\- add this\!

It might be sufficient to just set self.annotation.xytext to
self.ox,self.oy instead of calling update_offset like I did above.

--
Daniel Hyams
dhyams@...287...

------------------------------------------------------------------------------
BlackBerry&reg; DevCon Americas, Oct. 18-20, San Francisco, CA
http://p.sf.net/sfu/rim-devcon-copy2
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-users