Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit a3bfb09

Browse filesBrowse files
Add shadow coloring for legends and associated tests
Co-authored-by: Tranquilled <Tranquilled@users.noreply.github.com>
1 parent 5df9e3c commit a3bfb09
Copy full SHA for a3bfb09

File tree

Expand file treeCollapse file tree

6 files changed

+62
-3
lines changed
Filter options
Expand file treeCollapse file tree

6 files changed

+62
-3
lines changed
+6Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Colorful legend shadows
2+
-------------------------
3+
The *shadow* parameter of legends now accepts dicts in addition to booleans.
4+
If it is neither, a ValueError is thrown.
5+
Dictionaries can contain any keywords for `.patches.Patch`.
6+
Configuration is currently not supported via :rc:`legend.shadow`.
+5Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Configurable legend shadows
2+
-------------------------
3+
The *shadow* parameter of legends now accepts dicts in addition to booleans.
4+
Dictionaries can contain any keywords for `.patches.Patch`.
5+
Configuration is currently not supported via :rc:`legend.shadow`.

‎lib/matplotlib/legend.py

Copy file name to clipboardExpand all lines: lib/matplotlib/legend.py
+24-2Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
from matplotlib import _api, _docstring, colors, offsetbox
3232
from matplotlib.artist import Artist, allow_rasterization
3333
from matplotlib.cbook import silent_list
34+
from matplotlib.colors import is_color_like
3435
from matplotlib.font_manager import FontProperties
3536
from matplotlib.lines import Line2D
3637
from matplotlib.patches import (Patch, Rectangle, Shadow, FancyBboxPatch,
@@ -216,8 +217,10 @@ def _update_bbox_to_anchor(self, loc_in_canvas):
216217
Whether round edges should be enabled around the `.FancyBboxPatch` which
217218
makes up the legend's background.
218219
219-
shadow : bool, default: :rc:`legend.shadow`
220+
shadow : None, bool or dict, default: :rc:`legend.shadow`
220221
Whether to draw a shadow behind the legend.
222+
The shadow can be configured using `.Patch` keywords.
223+
Currently customization in :rc:`legend.shadow` not supported.
221224
222225
framealpha : float, default: :rc:`legend.framealpha`
223226
The alpha transparency of the legend's background.
@@ -480,6 +483,22 @@ def val_or_rc(val, rc_name):
480483
self._mode = mode
481484
self.set_bbox_to_anchor(bbox_to_anchor, bbox_transform)
482485

486+
# Figure out if self.shadow is valid
487+
# If shadow was None, rcParams loads False
488+
# So it shouldn't be None here
489+
490+
if isinstance(self.shadow, dict):
491+
self._shadow_props = self.shadow
492+
self.shadow = True
493+
elif self.shadow in (0, 1, True, False):
494+
self._shadow_props = {}
495+
self.shadow = bool(self.shadow)
496+
else:
497+
raise ValueError(
498+
'Legend shadow must be a dict or bool, not '
499+
f'{self.shadow!r} of type {type(self.shadow)}.'
500+
)
501+
483502
# We use FancyBboxPatch to draw a legend frame. The location
484503
# and size of the box will be updated during the drawing time.
485504

@@ -662,8 +681,11 @@ def draw(self, renderer):
662681
self.legendPatch.set_bounds(bbox.bounds)
663682
self.legendPatch.set_mutation_scale(fontsize)
664683

684+
# self.shadow is validated in __init__
685+
# So by here it is a bool and self._shadow_props contains any configs
686+
665687
if self.shadow:
666-
Shadow(self.legendPatch, 2, -2).draw(renderer)
688+
Shadow(self.legendPatch, 2, -2, **self._shadow_props).draw(renderer)
667689

668690
self.legendPatch.draw(renderer)
669691
self._legend_box.draw(renderer)

‎lib/matplotlib/rcsetup.py

Copy file name to clipboardExpand all lines: lib/matplotlib/rcsetup.py
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1059,7 +1059,7 @@ def _convert_validator_spec(key, conv):
10591059
"legend.labelcolor": _validate_color_or_linecolor,
10601060
# the relative size of legend markers vs. original
10611061
"legend.markerscale": validate_float,
1062-
"legend.shadow": validate_bool,
1062+
"legend.shadow": validate_bool, # using dict in rcParams not yet implemented
10631063
# whether or not to draw a frame around legend
10641064
"legend.frameon": validate_bool,
10651065
# alpha value of the legend frame
Loading

‎lib/matplotlib/tests/test_legend.py

Copy file name to clipboardExpand all lines: lib/matplotlib/tests/test_legend.py
+26Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -532,6 +532,32 @@ def test_empty_bar_chart_with_legend():
532532
plt.legend()
533533

534534

535+
@image_comparison(['shadow_argument_types.png'])
536+
def test_shadow_argument_types():
537+
# Test that different arguments for shadow work as expected
538+
fig, ax = plt.subplots()
539+
ax.plot([1, 2, 3], label='test')
540+
541+
legs = (ax.legend(loc='upper left', shadow=True), # True
542+
ax.legend(loc='upper right', shadow=False), # False
543+
ax.legend(loc='center left', shadow={'color': 'red'}), # string
544+
ax.legend(loc='center right', shadow={'color': (0.1, 0.2, 0.5)}), # tuple
545+
ax.legend(loc='lower left', shadow={'color': 'tab:cyan'}) # tab
546+
)
547+
for l in legs:
548+
ax.add_artist(l)
549+
ax.legend(loc='lower right') # default
550+
551+
552+
def test_shadow_invalid_argument():
553+
# Test if invalid argument to legend shadow
554+
# (i.e. not [color|bool]) raises ValueError
555+
fig, ax = plt.subplots()
556+
ax.plot([1, 2, 3], label='test')
557+
with pytest.raises(ValueError, match="dict or bool"):
558+
ax.legend(loc="upper left", shadow="aardvark") # Bad argument
559+
560+
535561
def test_shadow_framealpha():
536562
# Test if framealpha is activated when shadow is True
537563
# and framealpha is not explicitly passed'''

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.