Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
129ca43
add hide/show functionality to legend
fatteneder Sep 14, 2022
975c3c9
use the shade for interaction
fatteneder Sep 14, 2022
7dcb3a1
make plot as kwarg for <:LegendEntry
fatteneder Sep 14, 2022
479e3de
guard against missing visible field
fatteneder Sep 14, 2022
a741c31
add news entry
fatteneder Sep 14, 2022
f378669
don't put shades on entries which are not connected
fatteneder Sep 15, 2022
296bae4
rename kwarg plot to plots and allow to pass vectors of handles
fatteneder Sep 15, 2022
21d916f
add mouse event to toggle all entries of a legend
fatteneder Sep 15, 2022
617c1d2
use click instead of mouse down
fatteneder Sep 15, 2022
e4cc5d3
add middle click event to sync visibilty state
fatteneder Sep 15, 2022
8da0f80
revert to toggle method with a sync kwarg
fatteneder Sep 15, 2022
105dd2b
Rework shading for partly hidden elements
fatteneder Sep 18, 2022
99158dd
Merge remote-tracking branch 'origin/master' into fa/hideshow
fatteneder Sep 18, 2022
74d2137
Merge branch 'master' into fa/hideshow
SimonDanisch Oct 14, 2022
ef73bfe
Merge branch 'master' into fa/hideshow
SimonDanisch Jan 14, 2023
b5c62cf
Merge branch 'master' into fa/hideshow
SimonDanisch Feb 27, 2023
fb3c5d0
Merge branch 'master' into fa/hideshow
ffreyer Apr 9, 2025
bf4a935
fix some merge errors
ffreyer Apr 9, 2025
346e53b
fix sum errors
ffreyer Apr 9, 2025
136276c
rename e -> entry
ffreyer Apr 9, 2025
75137c9
fix right click
ffreyer Apr 9, 2025
887e5ec
don't print all attributes in short format
ffreyer Apr 9, 2025
e542bc0
refactor events to avoid creating multiple mouse state machines
ffreyer Apr 9, 2025
e3543f2
clean up visible observer handling
ffreyer Apr 9, 2025
d3c7443
Merge branch 'master' into fa/hideshow
ffreyer Apr 9, 2025
09711f2
cleanup deletion on relayout
ffreyer Apr 9, 2025
8c7d647
simplify right-click interaction
ffreyer Apr 9, 2025
2c78ac0
guard against entry.elements === nothing
ffreyer Apr 9, 2025
c4ce053
fix error and right click toggle
ffreyer Apr 9, 2025
71e66ce
Add middle mouse button interaction
ffreyer Apr 9, 2025
a774323
fix observer cleanup
ffreyer Apr 9, 2025
0c9f91a
fix event cleanup
ffreyer Apr 9, 2025
ed2b9d8
add warning & safeguard for LegendElement.plots
ffreyer Apr 9, 2025
bc2fafa
fix last element overwriting previous states
ffreyer Apr 10, 2025
f68f6a4
add test util for mouse and key event simulation
ffreyer Apr 10, 2025
e87e2e3
add refimg test for Legend interactions
ffreyer Apr 10, 2025
9a7eebb
add docs example
ffreyer Apr 10, 2025
69a1997
Update docs/src/reference/blocks/legend.md
ffreyer Apr 14, 2025
ccdd4b4
Merge branch 'master' into fa/hideshow
ffreyer Apr 16, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## [Unreleased]

- Added ability to hide and show individual plot elements by clicking their corresponding `Legend` entry [#2276](https://github.com/MakieOrg/Makie.jl/pull/2276).

## [0.22.4] - 2025-04-11

- Re-added the `apply_transform(f, data, space)` method that was removed in v0.22.3 with a deprecation warning. It will be removed in the next breaking version. [#4916](https://github.com/MakieOrg/Makie.jl/pull/4916)
Expand Down Expand Up @@ -74,7 +76,7 @@
- Changed the order of `Rect2` coordinates to be counter-clockwise.
- Updated `Cylinder` to avoid visually rounding off the top and bottom.
- Added `MetaMesh` to store non-vertex metadata in a GeometryBasics Mesh object. These are now produced by MeshIO for `.obj` files, containing information from `.mtl` files.
- Renamed `Tesselation/tesselation` to `Tessellation/tessellation` [GeometryBasics#227](https://github.com/JuliaGeometry/GeometryBasics.jl/pull/227) [#4564](https://github.com/MakieOrg/Makie.jl/pull/4564)

Check failure on line 79 in CHANGELOG.md

View workflow job for this annotation

GitHub Actions / check

tesselation ==> tessellation

Check failure on line 79 in CHANGELOG.md

View workflow job for this annotation

GitHub Actions / check

Tesselation ==> Tessellation
- Added `Makie.mesh` option for `MetaMesh` which applies some of the bundled information [#4368](https://github.com/MakieOrg/Makie.jl/pull/4368), [#4496](https://github.com/MakieOrg/Makie.jl/pull/4496)
- `Voronoiplot`s automatic colors are now defined based on the underlying point set instead of only those generators appearing in the tessellation. This makes the selected colors consistent between tessellations when generators might have been deleted or added. [#4357](https://github.com/MakieOrg/Makie.jl/pull/4357)
- `contour` now supports _curvilinear_ grids, where `x` and `y` are matrices [#4670](https://github.com/MakieOrg/Makie.jl/pull/4670).
Expand Down
4 changes: 2 additions & 2 deletions MakieCore/src/attributes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ end

_indent_attrs(s, n) = join(split(s, '\n'), "\n" * " "^n)

function Base.show(io::IO,::MIME"text/plain", attr::Attributes)
function Base.show(io::IO, ::MIME"text/plain", attr::Attributes)

io = IOContext(io, :compact => true)

Expand Down Expand Up @@ -152,7 +152,7 @@ function Base.show(io::IO,::MIME"text/plain", attr::Attributes)
end
end

Base.show(io::IO, attr::Attributes) = show(io, MIME"text/plain"(), attr)
Base.show(io::IO, attr::Attributes) = print(io, "Attributes()")
theme(x::AbstractPlot) = x.attributes
isvisible(x) = haskey(x, :visible) && to_value(x[:visible])

Expand Down
76 changes: 68 additions & 8 deletions ReferenceTests/src/tests/figures_and_makielayout.jl
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,67 @@ end
f
end

@reference_test "Legend visibility toggles" begin
f = Figure(size = (500, 500))

ax = Axis(f[1,1])
lb = lines!(ax, 0:4, 0:4, linewidth = 10, color=:blue, label="lines 1")
lo = lines!(ax, 0:4, -4:0, linewidth = 10, color=:orange, label="lines 2")
sb = scatter!(ax, range(0, 4, length=10), fill(3, 10), markersize = 10, color=:blue, label="scatter 1")
so = scatter!(ax, range(0, 4, length=10), fill(2, 10), markersize = 10, color=:orange, label="scatter 2")
x = LinRange(0, 4, 100)
slb = band!(ax, x, cos.(x) .- 1, cos.(x) .- 2, color=:blue, label="band 1")
slo = band!(ax, x, sin.(x) .- 1, sin.(x) .- 2, color=:orange, label="band 2")

ax2 = Axis(f[2,1])
x = 1:2:20
y = 5 * (0.5 .+ sin.(x).^2)
bb = barplot!(ax2, x, y; strokewidth = 1, color = :blue, label="barplot 1")
bo = barplot!(ax2, x, -y; strokewidth = 1, color = :orange, label="barplot 2")

l1 = Legend(f[1,2], ax)
l2 = Legend(f[2,2],
[ PolyElement(plots = [lb, sb, slb, bb], color = :blue),
PolyElement(plots = [lo, so, slo, bo], color = :orange) ],
[ "blue", "orange" ], "Colors" )

st = Makie.Stepper(f)
e = events(f)

click(e, 450, 440) # turn one off, single dashed
Makie.step!(st)

click(e, 450, 330) # turn another off, two dashed
Makie.step!(st)

click(e, 450, 400, Mouse.right) # invert
Makie.step!(st)

click(e, 450, 380)
click(e, 450, 420) # clear one dashed
Makie.step!(st)

click(e, 450, 120) # second legend off
Makie.step!(st)

click(e, 450, 120, Mouse.middle) # full reset
Makie.step!(st)

click(e, 450, 120, Mouse.middle) # swap
Makie.step!(st)

click(e, 450, 140) # turn on
Makie.step!(st)

click(e, 450, 110, Mouse.right)
Makie.step!(st)

click(e, 450, 120, Mouse.middle) # full reset (tests that last element doesn't overwrite privous states)
Makie.step!(st)

st
end

@reference_test "LaTeXStrings in Axis3 plots" begin
xs = LinRange(-10, 10, 100)
ys = LinRange(0, 15, 100)
Expand Down Expand Up @@ -554,29 +615,28 @@ end

@reference_test "Textbox" begin
f = Figure()
e = events(f)

tb1 = Makie.Textbox(f[1,1])
Makie.set!(tb1, "1234567890qwertyuiop")
Makie.focus!(tb1)
f.scene.events.mouseposition[] = (297, 221)
f.scene.events.mousebutton[] = Makie.MouseButtonEvent(Makie.Mouse.left, Makie.Mouse.press)
click(e, 297, 221)
Makie.defocus!(tb1)

tb2 = Makie.Textbox(f[2,1], width=100)
Makie.set!(tb2, "1234567890qwertyuiop")
tb2.cursorindex[] = 20
Makie.focus!(tb2)
f.scene.events.keyboardbutton[] = Makie.KeyEvent(Makie.Keyboard.backspace, Makie.Keyboard.press)
send(e, Keyboard.backspace)
Makie.defocus!(tb2)

tb3 = Makie.Textbox(f[3,1], width=100)
Makie.set!(tb3, "1234567890qwertyuiop")
tb3.cursorindex[] = 20
Makie.focus!(tb3)
f.scene.events.mouseposition[] = (259, 173) # between 7 and 8
f.scene.events.mousebutton[] = Makie.MouseButtonEvent(Makie.Mouse.left, Makie.Mouse.press)
f.scene.events.keyboardbutton[] = Makie.KeyEvent(Makie.Keyboard.left, Makie.Keyboard.press)
f.scene.events.keyboardbutton[] = Makie.KeyEvent(Makie.Keyboard.left, Makie.Keyboard.press)
click(e, 259, 173) # between 7 and 8
send(e, Keyboard.left)
send(e, Keyboard.left)
Makie.defocus!(tb3)

tb4 = Makie.Textbox(f[4,1], width=100)
Expand All @@ -585,7 +645,7 @@ end
tb4.cursorindex[] = 10
Makie.focus!(tb4)
for _ in 1:8
f.scene.events.keyboardbutton[] = Makie.KeyEvent(Makie.Keyboard.backspace, Makie.Keyboard.press)
send(e, Keyboard.backspace)
end
Makie.defocus!(tb4)

Expand Down
18 changes: 18 additions & 0 deletions ReferenceTests/src/tests/refimages.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,24 @@ using ReferenceTests.DelaunayTriangulation
using ReferenceTests.SparseArrays
using Makie: Record, volume

function click(events::Events, pos::VecTypes{2}, button::Mouse.Button = Mouse.left)
events.mouseposition[] = pos
events.mousebutton[] = Makie.MouseButtonEvent(button, Mouse.press)
events.mousebutton[] = Makie.MouseButtonEvent(button, Mouse.release)
end
click(events::Events, x, y, button::Mouse.Button = Mouse.left) = click(events, (x, y), button)

function send(events::Events, key::Keyboard.Button)
events.keyboardbutton[] = Makie.KeyEvent(key, Keyboard.press)
events.keyboardbutton[] = Makie.KeyEvent(key, Keyboard.release)
end
function send(events::Events, pos::VecTypes{2}, key::Keyboard.Button)
events.mouseposition[] = pos
send(events, key)
end
send(events::Events, x, y, key::Keyboard.Button) = click(events, (x, y), key)


@testset "categorical" begin
include("categorical.jl")
end
Expand Down
16 changes: 15 additions & 1 deletion docs/fake_interaction.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export MouseTo
export LeftClick
export LeftDown
export LeftUp
export RightClick, MiddleClick
export Lazy
export Wait
export relative_pos
Expand Down Expand Up @@ -48,7 +49,7 @@ function Makie.plot!(p::Cursor)

scatter!(p, p[1], marker = poly, markersize = p.multiplier, color = p.color, strokecolor = p.strokecolor, strokewidth = p.strokewidth,
glowcolor = (:black, 0.10), glowwidth = 2, transform_marker = true)

return p
end

Expand Down Expand Up @@ -106,6 +107,19 @@ struct LeftUp end
duration(::LeftUp, _) = 0.0
mouseevents_start(l::LeftUp) = [Makie.MouseButtonEvent(Mouse.left, Mouse.release)]

struct RightClick end

duration(::RightClick, _) = 0.15
mouseevents_start(l::RightClick) = [Makie.MouseButtonEvent(Mouse.right, Mouse.press)]
mouseevents_end(l::RightClick) = [Makie.MouseButtonEvent(Mouse.right, Mouse.release)]

struct MiddleClick end

duration(::MiddleClick, _) = 0.15
mouseevents_start(l::MiddleClick) = [Makie.MouseButtonEvent(Mouse.middle, Mouse.press)]
mouseevents_end(l::MiddleClick) = [Makie.MouseButtonEvent(Mouse.middle, Mouse.release)]


mouseevents_start(obj) = []
mouseevents_end(obj) = []
mouseevents_frame(obj, t) = []
Expand Down
54 changes: 54 additions & 0 deletions docs/src/reference/blocks/legend.md
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,60 @@ Label(f[3, 1:2, Top()], "titleposition = :left, orientation = :horizontal\nnbank
f
```

## Legend Interactivity

The Legend can be interacted with to show or hide connected plots.
A left click on a specific element will toggle the visibility of the connected plots.
A right click anywhere in the Legend will toggle the visibility of all plots associated with every element.
A middle click will toggle all plots if they have the same visibility state or make all visible if they do not.
Note that if you construct elements (MarkerElement, PolyElement, etc.) yourself, you need to also pass a plot or vector of plots as the first argument to enable these interactions.

```@example legend_interaction
using GLMakie
GLMakie.activate!() # hide

fig = Figure(size = (600, 450))
ax = Axis(fig[1, 1])
lines!(ax, Rect2f(-1,-1,2,2), linewidth = 5, color = RGBf(0.3, 0.5, 1), label = "blue line")
scatter!(ax, Rect2f(-1,-1,2,2), markersize = 30, color = :orange, label = "orange scatter")
lines!(ax, Circle(Point2f(0), 1), linewidth = 5, color = :darkgreen, label = "green circle")
leg = axislegend(ax, position = (:center, :center))
fig
nothing # hide
```

```@setup legend_interaction
using ..FakeInteraction

_events = [
Wait(0.5),
Lazy() do fig
MouseTo(relative_pos(leg, (0.6, 0.8)))
end,
Wait(0.2), LeftClick(),
Wait(1.5),
Lazy() do fig
MouseTo(relative_pos(leg, (0.6, 0.5)))
end,
Wait(0.2), LeftClick(),
Wait(1.5),
RightClick(),
Wait(1.5),
Lazy() do fig
MouseTo(relative_pos(leg, (0.6, 0.7)))
end,
Wait(0.2), LeftClick(),
Wait(1.5),
MiddleClick(),
Wait(1.5)
]

interaction_record(fig, "legend_interaction_example.mp4", _events)
```

```@raw html
<video autoplay loop muted playsinline src="./legend_interaction_example.mp4" width="600"/>
```

## Attributes

Expand Down
Loading
Loading