8000 Added a support for bbox_to_anchor in offsetbox.AnchoredOffsetbox · matplotlib/matplotlib@fe29f74 · GitHub
[go: up one dir, main page]

Skip to content

Commit fe29f74

Browse files
committed
Added a support for bbox_to_anchor in offsetbox.AnchoredOffsetbox
svn path=/trunk/matplotlib/; revision=7047
1 parent 0baf075 commit fe29f74

File tree

2 files changed

+137
-15
lines changed

2 files changed

+137
-15
lines changed

CHANGELOG

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
======================================================================
22

3+
2009-04-17 Added a support for bbox_to_anchor in
4+
offsetbox.AnchoredOffsetbox. Improved a documentation.
5+
- JJL
6+
37
2009-04-16 Fixed a offsetbox bug that multiline texts are not
48
correctly aligned. - JJL
59

lib/matplotlib/offsetbox.py

Lines changed: 133 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@
1919
impo 10000 rt matplotlib.artist as martist
2020
import matplotlib.text as mtext
2121
import numpy as np
22+
from matplotlib.transforms import Bbox, TransformedBbox, BboxTransformTo
23+
24+
from matplotlib.font_manager import FontProperties
25+
from matplotlib.patches import FancyBboxPatch
26+
from matplotlib import rcParams
2227

2328
from matplotlib.patches import bbox_artist as mbbox_artist
2429
DEBUG=False
@@ -291,7 +296,7 @@ def get_extent_offsets(self, renderer):
291296
for c in self.get_visible_children():
292297
if isinstance(c, PackerBase) and c.mode == "expand":
293298
c.set_width(self.width)
294-
299+
295300
whd_list = [c.get_extent(renderer) for c in self.get_visible_children()]
296301
whd_list = [(w, h, xd, (h-yd)) for w, h, xd, yd in whd_list]
297302

@@ -752,7 +757,7 @@ def get_extent(self, renderer):
752757
self.ref_offset_transform.translate(-ub.x0, -ub.y0)
753758
# restor offset transform
754759
self.offset_transform.matrix_from_values(*_off)
755-
760+
756761
return ub.width, ub.height, 0., 0.
757762

758763

@@ -767,14 +772,50 @@ def draw(self, renderer):
767772
bbox_artist(self, renderer, fill=False, props=dict(pad=0.))
768773

769774

770-
from matplotlib.font_manager import FontProperties
771-
from matplotlib.patches import FancyBboxPatch
772-
from matplotlib import rcParams
773-
from matplotlib.transforms import Bbox
774775

775776
class AnchoredOffsetbox(OffsetBox):
777+
"""
778+
An offset box placed according to the legend location
779+
loc. AnchoredOffsetbox has a single child. When multiple children
780+
is needed, use other OffsetBox class to enlose them. By default,
781+
the offset box is anchored against its parent axes. You may
782+
explicitly specify the bbox_to_anchor.
783+
"""
784+
776785
def __init__(self, loc, pad=0.4, borderpad=0.5,
777-
child=None, prop=None, frameon=True):
786+
child=None, prop=None, frameon=True,
787+
bbox_to_anchor=None,
788+
bbox_transform=None):
789+
"""
790+
loc is a string or an integer specifying the legend location.
791+
The valid location codes are::
792+
793+
'upper right' : 1,
794+
'upper left' : 2,
795+
'lower left' : 3,
796+
'lower right' : 4,
797+
'right' : 5,
798+
'center left' : 6,
799+
'center right' : 7,
800+
'lower center' : 8,
801+
'upper center' : 9,
802+
'center' : 10,
803+
804+
805+
pad : pad around the child for drawing a frame. given in
806+
fraction of fontsize.
807+
808+
borderpad : pad between offsetbox frame and the bbox_to_anchor,
809+
810+
child : OffsetBox instance that will be anchored.
811+
812+
prop : font property. This is only used as a reference for paddings.
813+
814+
frameon : draw a frame box if True.
815+
816+
bbox_to_anchor : bbox to anchor. If None, use axes.bbox.
817+
818+
"""
778819

779820
super(AnchoredOffsetbox, self).__init__()
780821

@@ -788,7 +829,7 @@ def __init__(self, loc, pad=0.4, borderpad=0.5,
788829
self.prop=FontProperties(size=rcParams["legend.fontsize"])
789830
else:
790831
self.prop = prop
791-
832+
792833
self.patch = FancyBboxPatch(
793834
xy=(0.0, 0.0), width=1., height=1.,
794835
facecolor='w', edgecolor='k',
@@ -797,48 +838,121 @@ def __init__(self, loc, pad=0.4, borderpad=0.5,
797838
)
798839
self.patch.set_boxstyle("square",pad=0)
799840
self._drawFrame = frameon
841+
#self._parent_bbox = bbox_to_anchor
842+
self.set_bbox_to_anchor(bbox_to_anchor, bbox_transform)
843+
844+
845+
800846

801847
def set_child(self, child):
848+
"set the child to be anchored"
802849
self._child = child
803850

851+
def get_child(self):
852+
"return the child"
853+
return self._child
854+
804855
def get_children(self):
856+
"return the list of children"
805857
return [self._child]
806858

807-
def get_child(self):
808-
return self._child
809859

810860
def get_extent(self, renderer):
861+
"""
862+
return the extent of the artist. The extent of the child
863+
added with the pad is returned
864+
"""
811865
w, h, xd, yd = self.get_child().get_extent(renderer)
812866
fontsize = renderer.points_to_pixels(self.prop.get_size_in_points())
813867
pad = self.pad * fontsize
814868

815869
return w+2*pad, h+2*pad, xd+pad, yd+pad
816870

871+
872+
def get_bbox_to_anchor(self):
873+
"""
874+
return the bbox that the legend will be anchored
875+
"""
876+
if self._bbox_to_anchor is None:
877+
return self.axes.bbox
878+
else:
879+
transform = self._bbox_to_anchor_transform
880+
if transform is None:
881+
transform = BboxTransformTo(self.axes.bbox)
882+
883+
return TransformedBbox(self._bbox_to_anchor,
884+
transform)
885+
886+
887+
888+
def set_bbox_to_anchor(self, bbox, transform=None):
889+
"""
890+
set the bbox that the child will be anchored.
891+
892+
*bbox* can be a Bbox instance, a list of [left, bottom, width,
893+
height], or a list of [left, bottom] where the width and
894+
height will be assumed to be zero. The bbox will be
895+
transformed to display coordinate by the given transform. If
896+
transform is None, axes.transAxes will be use.
897+
"""
898+
if bbox is None:
899+
self._bbox_to_anchor = None
900+
elif isinstance(bbox, Bbox):
901+
self._bbox_to_anchor = bbox
902+
else:
903+
try:
904+
l = len(bbox)
905+
except TypeError:
906+
raise ValueError("Invalid argument for bbox : %s" % str(bbox))
907+
908+
if l == 2:
909+
bbox = [bbox[0], bbox[1], 0, 0]
910+
911+
self._bbox_to_anchor = Bbox.from_bounds(*bbox)
912+
913+
self._bbox_to_anchor_transform = transform
914+
915+
817916
def get_window_extent(self, renderer):
818917
'''
819918
get the bounding box in display space.
820919
'''
920+
self._update_offset_func(renderer)
821921
10000 w, h, xd, yd = self.get_extent(renderer)
822922
ox, oy = self.get_offset(w, h, xd, yd)
823923
return Bbox.from_bounds(ox-xd, oy-yd, w, h)
824924

825-
def draw(self, renderer):
826-
827-
if not self.get_visible(): return
828925

829-
fontsize = renderer.points_to_pixels(self.prop.get_size_in_points())
926+
def _update_offset_func(self, renderer, fontsize=None):
927+
"""
928+
Update the offset func which depends on the dpi of the
929+
renderer (because of the padding).
930+
"""
931+
if fontsize is None:
932+
fontsize = renderer.points_to_pixels(self.prop.get_size_in_points())
830933

831934
def _offset(w, h, xd, yd, fontsize=fontsize, self=self):
832935
bbox = Bbox.from_bounds(0, 0, w, h)
833936
borderpad = self.borderpad*fontsize
937+
bbox_to_anchor = self.get_bbox_to_anchor()
938+
834939
x0, y0 = self._get_anchored_bbox(self.loc,
835940
bbox,
836-
self.axes.bbox,
941+
bbox_to_anchor,
837942
borderpad)
838943
return x0+xd, y0+yd
839944

840945
self.set_offset(_offset)
841946

947+
948+
def draw(self, renderer):
949+
"draw the artist"
950+
951+
if not self.get_visible(): return
952+
953+
fontsize = renderer.points_to_pixels(self.prop.get_size_in_points())
954+
self._update_offset_func(renderer, fontsize)
955+
842956
if self._drawFrame:
843957
# update the location and size of the legend
844958
bbox = self.get_window_extent(renderer)
@@ -860,6 +974,10 @@ def _offset(w, h, xd, yd, fontsize=fontsize, self=self):
860974

861975

862976
def _get_anchored_bbox(self, loc, bbox, parentbbox, borderpad):
977+
"""
978+
return the position of the bbox anchored at the parentbbox
979+
with the loc code, with the borderpad.
980+
"""
863981
assert loc in range(1,11) # called only internally
864982

865983
BEST, UR, UL, LL, LR, R, CL, CR, LC, UC, C = range(11)

0 commit comments

Comments
 (0)
0