@@ -332,6 +332,12 @@ def _update_bbox_to_anchor(self, loc_in_canvas):
332
332
_legend_kw_doc_base )
333
333
_docstring .interpd .update (_legend_kw_doc = _legend_kw_both_st )
334
334
335
+ _legend_kw_set_loc_st = (
336
+ _loc_doc_base .format (parent = 'axes/figure' ,
337
+ default = ":rc:`legend.loc` for Axes, 'upper right' for Figure" ,
338
+ best = _loc_doc_best , outside = _outside_doc ))
339
+ _docstring .interpd .update (_legend_kw_set_loc_doc = _legend_kw_set_loc_st )
340
+
335
341
336
342
class Legend (Artist ):
337
343
"""
@@ -505,58 +511,6 @@ def val_or_rc(val, rc_name):
505
511
)
506
512
self .parent = parent
507
513
508
- loc0 = loc
509
- self ._loc_used_default = loc is None
510
- if loc is None :
511
- loc = mpl .rcParams ["legend.loc" ]
512
- if not self .isaxes and loc in [0 , 'best' ]:
513
- loc = 'upper right'
514
-
515
- type_err_message = ("loc must be string, coordinate tuple, or"
516
- f" an integer 0-10, not { loc !r} " )
517
-
518
- # handle outside legends:
519
- self ._outside_loc = None
520
- if isinstance (loc , str ):
521
- if loc .split ()[0 ] == 'outside' :
522
- # strip outside:
523
- loc = loc .split ('outside ' )[1 ]
524
- # strip "center" at the beginning
525
- self ._outside_loc = loc .replace ('center ' , '' )
526
- # strip first
527
- self ._outside_loc = self ._outside_loc .split ()[0 ]
528
- locs = loc .split ()
529
- if len (locs ) > 1 and locs [0 ] in ('right' , 'left' ):
530
- # locs doesn't accept "left upper", etc, so swap
531
- if locs [0 ] != 'center' :
532
- locs = locs [::- 1 ]
533
- loc = locs [0 ] + ' ' + locs [1 ]
534
- # check that loc is in acceptable strings
535
- loc = _api .check_getitem (self .codes , loc = loc )
536
- elif np .iterable (loc ):
537
- # coerce iterable into tuple
538
- loc = tuple (loc )
539
- # validate the tuple represents Real coordinates
540
- if len (loc ) != 2 or not all (isinstance (e , numbers .Real ) for e in loc ):
541
- raise ValueError (type_err_message )
542
- elif isinstance (loc , int ):
543
- # validate the integer represents a string numeric value
544
- if loc < 0 or loc > 10 :
545
- raise ValueError (type_err_message )
546
- else :
547
- # all other cases are invalid values of loc
548
- raise ValueError (type_err_message )
549
-
550
- if self .isaxes and self ._outside_loc :
551
- raise ValueError (
552
- f"'outside' option for loc='{ loc0 } ' keyword argument only "
553
- "works for figure legends" )
554
-
555
- if not self .isaxes and loc == 0 :
556
- raise ValueError (
557
- "Automatic legend placement (loc='best') not implemented for "
558
- "figure legend" )
559
-
560
514
self ._mode = mode
561
515
self .set_bbox_to_anchor (bbox_to_anchor , bbox_transform )
562
516
@@ -616,9 +570,8 @@ def val_or_rc(val, rc_name):
616
570
# init with null renderer
617
571
self ._init_legend_box (handles , labels , markerfirst )
618
572
619
- tmp = self ._loc_used_default
620
- self ._set_loc (loc )
621
- self ._loc_used_default = tmp # ignore changes done by _set_loc
573
+ # Set legend location
574
+ self .set_loc (loc )
622
575
623
576
# figure out title font properties:
624
577
if title_fontsize is not None and title_fontproperties is not None :
@@ -704,6 +657,73 @@ def _set_artist_props(self, a):
704
657
705
658
a .set_transform (self .get_transform ())
706
659
660
+ @_docstring .dedent_interpd
661
+ def set_loc (self , loc = None ):
662
+ """
663
+ Set the location of the legend.
664
+
665
+ .. versionadded:: 3.8
666
+
667
+ Parameters
668
+ ----------
669
+ %(_legend_kw_set_loc_doc)s
670
+ """
671
+ loc0 = loc
672
+ self ._loc_used_default = loc is None
673
+ if loc is None :
674
+ loc = mpl .rcParams ["legend.loc" ]
675
+ if not self .isaxes and loc in [0 , 'best' ]:
676
+ loc = 'upper right'
677
+
678
+ type_err_message = ("loc must be string, coordinate tuple, or"
679
+ f" an integer 0-10, not { loc !r} " )
680
+
681
+ # handle outside legends:
682
+ self ._outside_loc = None
683
+ if isinstance (loc , str ):
684
+ if loc .split ()[0 ] == 'outside' :
685
+ # strip outside:
686
+ loc = loc .split ('outside ' )[1 ]
687
+ # strip "center" at the beginning
688
+ self ._outside_loc = loc .replace ('center ' , '' )
689
+ # strip first
690
+ self ._outside_loc = self ._outside_loc .split ()[0 ]
691
+ locs = loc .split ()
692
+ if len (locs ) > 1 and locs [0 ] in ('right' , 'left' ):
693
+ # locs doesn't accept "left upper", etc, so swap
694
+ if locs [0 ] != 'center' :
695
+ locs = locs [::- 1 ]
696
+ loc = locs [0 ] + ' ' + locs [1 ]
697
+ # check that loc is in acceptable strings
698
+ loc = _api .check_getitem (self .codes , loc = loc )
699
+ elif np .iterable (loc ):
700
+ # coerce iterable into tuple
701
+ loc = tuple (loc )
702
+ # validate the tuple represents Real coordinates
703
+ if len (loc ) != 2 or not all (isinstance (e , numbers .Real ) for e in loc ):
704
+ raise ValueError (type_err_message )
705
+ elif isinstance (loc , int ):
706
+ # validate the integer represents a string numeric value
707
+ if loc < 0 or loc > 10 :
708
+ raise ValueError (type_err_message )
709
+ else :
710
+ # all other cases are invalid values of loc
711
+ raise ValueError (type_err_message )
712
+
713
+ if self .isaxes and self ._outside_loc :
714
+ raise ValueError (
715
+ f"'outside' option for loc='{ loc0 } ' keyword argument only "
716
+ "works for figure legends" )
717
+
718
+ if not self .isaxes and loc == 0 :
719
+ raise ValueError (
720
+ "Automatic legend placement (loc='best') not implemented for "
721
+ "figure legend" )
722
+
723
+ tmp = self ._loc_used_default
724
+ self ._set_loc (loc )
725
+ self ._loc_used_default = tmp # ignore changes done by _set_loc
726
+
707
727
def _set_loc (self , loc ):
708
728
# find_offset function will be provided to _legend_box and
709
729
# _legend_box will draw itself at the location of the return
0 commit comments