Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b6147e3

Browse files
committed
added drabbable state to legend -- thanks Adam Fraser
svn path=/trunk/matplotlib/; revision=8100
1 parent 75097f9 commit b6147e3

1 file changed

Lines changed: 64 additions & 5 deletions

File tree

lib/matplotlib/legend.py

Lines changed: 64 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,51 @@
3838
from matplotlib.offsetbox import HPacker, VPacker, TextArea, DrawingArea
3939

4040

41+
class DraggableLegend:
42+
"""helper code for a draggable legend -- see Legend.draggable"""
43+
44+
def __init__(self, legend):
45+
self.legend = legend
46+
self.gotLegend = False
47+
48+
c1 = legend.figure.canvas.mpl_connect('motion_notify_event', self.on_motion)
49+
c2 = legend.figure.canvas.mpl_connect('pick_event', self.on_pick)
50+
c3 = legend.figure.canvas.mpl_connect('button_release_event', self.on_release)
51+
legend.set_picker(self.my_legend_picker)
52+
self.cids = [c1, c2, c3]
53+
54+
def on_motion(self, evt):
55+
if self.gotLegend:
56+
dx = evt.x - self.mouse_x
57+
dy = evt.y - self.mouse_y
58+
loc_in_canvas = self.legend_x + dx, self.legend_y + dy
59+
loc_in_norm_axes = self.legend.parent.transAxes.inverted().transform_point(loc_in_canvas)
60+
self.legend._loc = tuple(loc_in_norm_axes)
61+
self.legend.figure.canvas.draw()
62+
63+
def my_legend_picker(self, legend, evt):
64+
return self.legend.legendPatch.contains(evt)
65+
66+
def on_pick(self, evt):
67+
legend = self.legend
68+
if evt.artist == legend:
69+
bbox = self.legend.get_window_extent()
70+
self.mouse_x = evt.mouseevent.x
71+
self.mouse_y = evt.mouseevent.y
72+
self.legend_x = bbox.xmin
73+
self.legend_y = bbox.ymin
74+
self.gotLegend = 1
75+
76+
def on_release(self, event):
77+
if self.gotLegend:
78+
self.gotLegend = False
79+
80+
def disconnect(self):
81+
'disconnect the callbacks'
82+
for cid in self.cids:
83+
self.legend.figure.canvas.mpl_disconnect(cid)
84+
85+
4186
class Legend(Artist):
4287
"""
4388
Place a legend on the axes at location loc. Labels are a
@@ -182,7 +227,7 @@ def __init__(self, parent, handles, labels,
182227
self.texts = []
183228
self.legendHandles = []
184229
self._legend_title_box = None
185-
230+
186231
localdict = locals()
187232

188233
for name in propnames:
@@ -284,7 +329,7 @@ def __init__(self, parent, handles, labels,
284329

285330
# We use FancyBboxPatch to draw a legend frame. The location
286331
# and size of the box will be updated during the drawing time.
287-
332+
288333
self.legendPatch = FancyBboxPatch(
289334
xy=(0.0, 0.0), width=1., height=1.,
290335
facecolor=rcParams["axes.facecolor"],
@@ -316,6 +361,7 @@ def __init__(self, parent, handles, labels,
316361

317362
self._last_fontsize_points = self._fontsize
318363

364+
self._draggable = None
319365

320366
def _set_artist_props(self, a):
321367
"""
@@ -584,7 +630,7 @@ def _init_legend_box(self, handles, labels):
584630
textbox = TextArea(lab, textprops=label_prop,
585631
multilinebaseline=True, minimumdescent=True)
586632
text_list.append(textbox._text)
587-
633+
588634
labelboxes.append(textbox)
589635

590636
handlebox = DrawingArea(width=self.handlelength*fontsize,
@@ -597,7 +643,7 @@ def _init_legend_box(self, handles, labels):
597643
handleboxes.append(handlebox)
598644

599645

600-
if len(handleboxes) > 0:
646+
if len(handleboxes) > 0:
601647

602648
# We calculate number of lows in each column. The first
603649
# (num_largecol) columns will have (nrows+1) rows, and remaing
@@ -613,7 +659,7 @@ def _init_legend_box(self, handles, labels):
613659
[nrows] * num_smallcol)
614660
else:
615661
largecol, smallcol = [], []
616-
662+
617663
handle_label = safezip(handleboxes, labelboxes)
618664
columnbox = []
619665
for i0, di in largecol+smallcol:
@@ -889,3 +935,16 @@ def _find_best_position(self, width, height, renderer, consider=None):
889935
return ox, oy
890936

891937

938+
def draggable(self):
939+
"""
940+
toggle the draggable state; if on, you can drag the legend on
941+
the canvas. The DraggableLegend helper class is returned
942+
"""
943+
if self._draggable is not None:
944+
self._draggable.disconnect()
945+
self._draggable = None
946+
else:
947+
948+
self._draggable = DraggableLegend(self)
949+
950+
return self._draggable

0 commit comments

Comments
 (0)