Skip to content

Commit e4ee185

Browse files
Wojciech-Langeoscargus
authored andcommitted
Add legend handler for Annotation
1 parent 4d7c309 commit e4ee185

File tree

3 files changed

+63
-5
lines changed

3 files changed

+63
-5
lines changed

examples/text_labels_and_annotations/legend.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,11 @@
2121
ax.plot(a, d, 'k:', label='Data length')
2222
ax.plot(a, c + d, 'k', label='Total message length')
2323

24-
legend = ax.legend(loc='upper center', shadow=True, fontsize='x-large')
24+
#Create an arrow with pre-defined label.
25+
ax.annotate("", xy=(1.5, 4.5), xytext=(1.5, 9.0),
26+
arrowprops={'arrowstyle':'<->', 'color':'C7'}, label='Distance')
27+
28+
legend = ax.legend(loc='upper center', shadow=True, fontsize='large')
2529

2630
# Put a nicer background color on the legend.
2731
legend.get_frame().set_facecolor('C0')

lib/matplotlib/legend.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@
3434
from matplotlib.font_manager import FontProperties
3535
from matplotlib.lines import Line2D
3636
from matplotlib.patches import (Patch, Rectangle, Shadow, FancyBboxPatch,
37-
StepPatch)
37+
StepPatch, FancyArrowPatch)
3838
from matplotlib.collections import (
3939
Collection, CircleCollection, LineCollection, PathCollection,
4040
PolyCollection, RegularPolyCollection)
41-
from matplotlib.text import Text
41+
from matplotlib.text import Annotation, Text
4242
from matplotlib.transforms import Bbox, BboxBase, TransformedBbox
4343
from matplotlib.transforms import BboxTransformTo, BboxTransformFrom
4444
from matplotlib.offsetbox import (
@@ -649,7 +649,9 @@ def draw(self, renderer):
649649
update_func=legend_handler.update_from_first_child),
650650
tuple: legend_handler.HandlerTuple(),
651651
PathCollection: legend_handler.HandlerPathCollection(),
652-
PolyCollection: legend_handler.HandlerPolyCollection()
652+
PolyCollection: legend_handler.HandlerPolyCollection(),
653+
FancyArrowPatch: legend_handler.HandlerFancyArrowPatch(),
654+
Annotation: legend_handler.HandlerAnnotation()
653655
}
654656

655657
# (get|set|update)_default_handler_maps are public interfaces to
@@ -799,6 +801,7 @@ def _init_legend_box(self, handles, labels, markerfirst=True):
799801
self._legend_handle_box])
800802
self._legend_box.set_figure(self.figure)
801803
self._legend_box.axes = self.axes
804+
self._legend_box.set_offset(self._findoffset)
802805
self.texts = text_list
803806
self.legendHandles = handle_list
804807

lib/matplotlib/legend_handler.py

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ def legend_artist(self, legend, orig_handle, fontsize, handlebox)
3434

3535
from matplotlib import _api, cbook
3636
from matplotlib.lines import Line2D
37-
from matplotlib.patches import Rectangle
37+
from matplotlib.patches import Rectangle, FancyArrowPatch
3838
import matplotlib.collections as mcoll
3939

4040

@@ -806,3 +806,54 @@ def create_artists(self, legend, orig_handle,
806806
self.update_prop(p, orig_handle, legend)
807807
p.set_transform(trans)
808808
return [p]
809+
810+
811+
class HandlerFancyArrowPatch(HandlerPatch):
812+
"""
813+
Handler for `~.FancyArrowPatch` instances.
814+
"""
815+
def _create_patch(self, legend, orig_handle, xdescent, ydescent, width, height, fontsize):
816+
arrow = FancyArrowPatch([-xdescent,
817+
-ydescent + height / 2],
818+
[-xdescent + width,
819+
-ydescent + height / 2],
820+
mutation_scale=width / 3)
821+
arrow.set_arrowstyle(orig_handle.get_arrowstyle())
822+
return arrow
823+
824+
825+
class HandlerAnnotation(HandlerBase):
826+
"""
827+
Handler for `.Annotation` instances.
828+
Defers to `HandlerFancyArrowPatch` to draw the annotation arrow (if any).
829+
830+
Parameters
831+
----------
832+
pad : float, optional
833+
If None, fall back to :rc:`legend.borderpad` as the default.
834+
In units of fraction of font size. Default is None
835+
.
836+
width_ratios : two-tuple, optional
837+
The relative width of the respective text/arrow legend annotation pair.
838+
Default is (1, 4).
839+
"""
840+
841+
def __init__(self, pad=None, width_ratios=(1, 4), **kwargs):
842+
843+
self._pad = pad
844+
self._width_ratios = width_ratios
845+
846+
HandlerBase.__init__(self, **kwargs)
847+
848+
def create_artists(self, legend, orig_handle, xdescent, ydescent, width,
849+
height, fontsize, trans):
850+
851+
if orig_handle.arrow_patch is not None:
852+
853+
# Arrow without text
854+
855+
handler = HandlerFancyArrowPatch()
856+
handle = orig_handle.arrow_patch
857+
858+
return handler.create_artists(legend, handle, xdescent, ydescent,
859+
width, height, fontsize, trans)

0 commit comments

Comments
 (0)