@@ -503,57 +503,8 @@ def val_or_rc(val, rc_name):
503
503
)
504
504
self .parent = parent
505
505
506
- loc0 = loc
507
- self ._loc_used_default = loc is None
508
- if loc is None :
509
- loc = mpl .rcParams ["legend.loc" ]
510
- if not self .isaxes and loc in [0 , 'best' ]:
511
- loc = 'upper right'
512
-
513
- type_err_message = ("loc must be string, coordinate tuple, or"
514
- f" an integer 0-10, not { loc !r} " )
515
-
516
- # handle outside legends:
517
- self ._outside_loc = None
518
- if isinstance (loc , str ):
519
- if loc .split ()[0 ] == 'outside' :
520
- # strip outside:
521
- loc = loc .split ('outside ' )[1 ]
522
- # strip "center" at the beginning
523
- self ._outside_loc = loc .replace ('center ' , '' )
524
- # strip first
525
- self ._outside_loc = self ._outside_loc .split ()[0 ]
526
- locs = loc .split ()
527
- if len (locs ) > 1 and locs [0 ] in ('right' , 'left' ):
528
- # locs doesn't accept "left upper", etc, so swap
529
- if locs [0 ] != 'center' :
530
- locs = locs [::- 1 ]
531
- loc = locs [0 ] + ' ' + locs [1 ]
532
- # check that loc is in acceptable strings
533
- loc = _api .check_getitem (self .codes , loc = loc )
534
- elif np .iterable (loc ):
535
- # coerce iterable into tuple
536
- loc = tuple (loc )
537
- # validate the tuple represents Real coordinates
538
- if len (loc ) != 2 or not all (isinstance (e , numbers .Real ) for e in loc ):
539
- raise ValueError (type_err_message )
540
- elif isinstance (loc , int ):
541
- # validate the integer represents a string numeric value
542
- if loc < 0 or loc > 10 :
543
- raise ValueError (type_err_message )
544
- else :
545
- # all other cases are invalid values of loc
546
- raise ValueError (type_err_message )
547
-
548
- if self .isaxes and self ._outside_loc :
549
- raise ValueError (
550
- f"'outside' option for loc='{ loc0 } ' keyword argument only "
551
- "works for figure legends" )
552
-
553
- if not self .isaxes and loc == 0 :
554
- raise ValueError (
555
- "Automatic legend placement (loc='best') not implemented for "
556
- "figure legend" )
506
+ # Set legend location
507
+ self .set_loc (loc )
557
508
558
509
self ._mode = mode
559
510
self .set_bbox_to_anchor (bbox_to_anchor , bbox_transform )
@@ -597,10 +548,7 @@ def val_or_rc(val, rc_name):
597
548
598
549
# init with null renderer
599
550
self ._init_legend_box (handles , labels , markerfirst )
600
-
601
- tmp = self ._loc_used_default
602
- self ._set_loc (loc )
603
- self ._loc_used_default = tmp # ignore changes done by _set_loc
551
+ self ._legend_box .set_offset (self ._findoffset )
604
552
605
553
# figure out title font properties:
606
554
if title_fontsize is not None and title_fontproperties is not None :
@@ -692,21 +640,78 @@ def set_loc(self, loc):
692
640
693
641
Parameters
694
642
----------
695
- alignment : {'upper left', 'upper right', 'lower left', 'lower right',
643
+ loc : {'upper left', 'upper right', 'lower left', 'lower right',
696
644
'upper center', 'lower center', 'center left', 'center right'
697
645
'center', 'right', 'best'}.
646
+ If a figure is using the constrained layout manager,
647
+ the string codes of the loc keyword argument can get better
648
+ layout behaviour using the prefix 'outside'.
698
649
"""
699
- _loc_code = self .codes .get (loc , 'best' )
700
- self ._set_loc (_loc_code )
650
+ loc0 = loc
651
+ self ._loc_used_default = loc is None
652
+ if loc is None :
653
+ loc = mpl .rcParams ["legend.loc" ]
654
+ if not self .isaxes and loc in [0 , 'best' ]:
655
+ loc = 'upper right'
656
+
657
+ type_err_message = ("loc must be string, coordinate tuple, or"
658
+ f" an integer 0-10, not { loc !r} " )
701
659
702
- def _set_loc (self , loc ):
660
+ # handle outside legends:
661
+ self ._outside_loc = None
662
+ if isinstance (loc , str ):
663
+ if loc .split ()[0 ] == 'outside' :
664
+ # strip outside:
665
+ loc = loc .split ('outside ' )[1 ]
666
+ # strip "center" at the beginning
667
+ self ._outside_loc = loc .replace ('center ' , '' )
668
+ # strip first
669
+ self ._outside_loc = self ._outside_loc .split ()[0 ]
670
+ locs = loc .split ()
671
+ if len (locs ) > 1 and locs [0 ] in ('right' , 'left' ):
672
+ # locs doesn't accept "left upper", etc, so swap
673
+ if locs [0 ] != 'center' :
674
+ locs = locs [::- 1 ]
675
+ loc = locs [0 ] + ' ' + locs [1 ]
676
+ # check that loc is in acceptable strings
677
+ loc = _api .check_getitem (self .codes , loc = loc )
678
+ elif np .iterable (loc ):
679
+ # coerce iterable into tuple
680
+ loc = tuple (loc )
681
+ # validate the tuple represents Real coordinates
682
+ if len (loc ) != 2 or not all (isinstance (e , numbers .Real ) for e in loc ):
683
+ raise ValueError (type_err_message )
684
+ elif isinstance (loc , int ):
685
+ # validate the integer represents a string numeric value
686
+ if loc < 0 or loc > 10 :
687
+ raise ValueError (type_err_message )
688
+ else :
689
+ # all other cases are invalid values of loc
690
+ raise ValueError (type_err_message )
691
+
692
+ if self .isaxes and self ._outside_loc :
693
+ raise ValueError (
694
+ f"'outside' option for loc='{ loc0 } ' keyword argument only "
695
+ "works for figure legends" )
696
+
697
+ if not self .isaxes and loc == 0 :
698
+ raise ValueError (
699
+ "Automatic legend placement (loc='best') not implemented for "
700
+ "figure legend" )
701
+
702
+ tmp = self ._loc_used_default
703
+ self ._set_loc (loc , set_offset = False )
704
+ self ._loc_used_default = tmp # ignore changes done by _set_loc
705
+
706
+ def _set_loc (self , loc , set_offset = True ):
703
707
# find_offset function will be provided to _legend_box and
704
708
# _legend_box will draw itself at the location of the return
705
709
# value of the find_offset.
706
710
self ._loc_used_default = False
707
711
self ._loc_real = loc
708
712
self .stale = True
709
- self ._legend_box .set_offset (self ._findoffset )
713
+ if set_offset :
714
+ self ._legend_box .set_offset (self ._findoffset )
710
715
711
716
def set_ncols (self , ncols ):
712
717
"""Set the number of columns."""
0 commit comments