Skip to content

Commit 4be2cde

Browse files
TomRottierjusacktomffreyer
authored
allow Legend to be created from multiple Axis (re-submit of #4984) (#5551)
* add option to collect legend entries from multiple axes * add change to changelog * fix formatting * make tests more specific * improve documentation * create Legend from multiple axes * fix * update docstring * format --------- Co-authored-by: Justin Ackers <justin.ackers@imte.fraunhofer.de> Co-authored-by: tom <tom.rottier@manchester.ac.uk> Co-authored-by: ffreyer <frederic481994@hotmail.de>
1 parent 9b947a4 commit 4be2cde

File tree

4 files changed

+51
-5
lines changed

4 files changed

+51
-5
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## Unreleased
44

5+
- Added possibility to gather legend entries from multiple axes [#5551](https://github.com/MakieOrg/Makie.jl/pull/5551)
56
- Added complete inverse transformation support to `register_projected_positions!` with `apply_inverse_transform`, `apply_inverse_transform_func`, `apply_inverse_float32convert`, and `apply_inverse_model` kwargs. These enable correct projection from non-data spaces back to data space. Includes early-exit optimization to skip redundant transform/inverse pairs when `input_space === output_space`. [#5485](https://github.com/MakieOrg/Makie.jl/pull/5485)
67
- Fixed `bracket` not supporting `LaTeXString` text, which would render with dollar signs instead of mathematical notation [#5536](https://github.com/MakieOrg/Makie.jl/pull/5536)
78
- Added text glow to CairoMakie [#5542](https://github.com/MakieOrg/Makie.jl/pull/5542)

Makie/src/makielayout/blocks/legend.jl

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -998,22 +998,29 @@ end
998998

999999

10001000
"""
1001-
Legend(fig_or_scene, axis::Union{Axis, Scene, LScene}, title = nothing; merge = false, unique = false, kwargs...)
1001+
Legend(fig_or_scene, axis, title = nothing; merge = false, unique = false, kwargs...)
10021002
1003-
Create a single-group legend with all plots from `axis` that have the
1004-
attribute `label` set.
1003+
Create a single-group legend with all plots from `axis` that have the attribute
1004+
`label` set. `axis` can be any `AbstractAxis`, `AbstractScene` or `Vector`
1005+
of the former.
10051006
10061007
If `merge` is `true`, all plot objects with the same label will be layered on top of each other into one legend entry.
10071008
If `unique` is `true`, all plot objects with the same plot type and label will be reduced to one occurrence.
1009+
1010+
To create a joint legend for multiple axes it is also possible to pass a `Vector` of axis objects.
10081011
"""
1009-
function Legend(fig_or_scene, axis::Union{Axis, Axis3, Scene, LScene}, title = nothing; merge = false, unique = false, kwargs...)
1012+
function Legend(
1013+
fig_or_scene,
1014+
axis::Union{AbstractAxis, AbstractScene, AbstractArray{<:Union{AbstractAxis, AbstractScene}}},
1015+
title = nothing; merge = false, unique = false, kwargs...
1016+
)
10101017
plots, labels = get_labeled_plots(axis, merge = merge, unique = unique)
10111018
isempty(plots) && error("There are no plots with labels in the given axis that can be put in the legend. Supply labels to plotting functions like `plot(args...; label = \"My label\")`")
10121019
return Legend(fig_or_scene, plots, labels, title; kwargs...)
10131020
end
10141021

10151022
function get_labeled_plots(ax; merge::Bool, unique::Bool)
1016-
lplots_init = filter(get_plots(ax)) do plot
1023+
lplots_init = filter(reduce(vcat, get_plots.(ax), init = AbstractPlot[])) do plot
10171024
haskey(plot.attributes, :label) ||
10181025
plot isa PlotList && any(x -> haskey(x.attributes, :label), plot.plots)
10191026
end

Makie/test/SceneLike/makielayout.jl

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,25 @@ end
534534
@test make_fig(linesegments!, rand(8)) isa Figure
535535
end
536536

537+
@testset "Joint legend data gathering" begin
538+
f = Figure()
539+
ax1 = Axis(f[1, 1])
540+
l1a = lines!(ax1, rand(10), label = "test a")
541+
l1b = lines!(ax1, rand(10), label = "test b")
542+
ax2 = Axis(f[1, 2])
543+
l2a = lines!(ax2, rand(10), label = "test a")
544+
leg = Legend(f[1, 3], [ax1, ax2], merge = true)
545+
546+
@test f isa Figure
547+
# The joint legend has two entries
548+
@test length(leg.entrygroups[][][2]) == 2
549+
# The first entry has two linked plots
550+
@test length(leg.entrygroups[][][2][1].elements) == 2
551+
# The two linked plots are the plots from two different axes
552+
@test leg.entrygroups[][][2][1].elements[1].plots[] == l1a
553+
@test leg.entrygroups[][][2][1].elements[2].plots[] == l2a
554+
end
555+
537556
@testset "ReversibleScale" begin
538557
@test ReversibleScale(identity).inverse === identity
539558
@test ReversibleScale(log).inverse === exp

docs/src/reference/blocks/legend.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,25 @@ end
8787
f
8888
```
8989

90+
To create a joint legend for multiple axes it is also possible to pass a `Vector` of axis objects. Together with the `merge` keyword this can be useful for legend interactivity spanning multiple axes.
91+
92+
```@figure
93+
94+
f = Figure()
95+
96+
ax1 = Axis(f[1, 1])
97+
ax2 = Axis(f[1, 2])
98+
99+
xs = range(0, 4pi, length = 31)
100+
lines!(ax1, xs, sin, label = "sin", color = :blue)
101+
lines!(ax2, xs, cos, label = "cos", color = :red)
102+
scatter!(ax1, xs, sin, label = "Points", color = :black)
103+
scatter!(ax2, xs, cos, label = "Points", color = :black)
104+
105+
f[0, 1:2] = Legend(f, [ax1, ax2], "Automatic Joint Legend", merge = true, orientation = :horizontal, tellheight = true)
106+
107+
f
108+
```
90109

91110
## Legend Inside An Axis
92111

0 commit comments

Comments
 (0)