Skip to content

Commit

Permalink
Refactor Layoutables (#1796)
Browse files Browse the repository at this point in the history
Rename Layoutable to Block and simplify the initialization process, so less boilerplate would be required for end users. Attributes become possibly typed Observable fields. Every block has its own scene so z shifting and deleting can be simplified.
  • Loading branch information
jkrumbiegel committed Apr 10, 2022
1 parent 84a026f commit d4f5ea8
Show file tree
Hide file tree
Showing 59 changed files with 2,838 additions and 2,838 deletions.
2 changes: 1 addition & 1 deletion CairoMakie/src/precompiles.jl
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ end
function get_obs(x::Axis, visited, obs=Set())
if x in visited; return; else; push!(visited, x); end

get_obs(x.attributes, visited, obs)
# get_obs(x.attributes, visited, obs)
get_obs(x.layoutobservables, visited, obs)
get_obs(x.scene, visited, obs)
get_obs(x.finallimits, visited, obs)
Expand Down
2 changes: 1 addition & 1 deletion GLMakie/test/glmakie_tests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ end
rotations=rot,
color=color,
markersize=size,
limits=Rect3f(Point3(0), Point3(1))
axis = (; scenekw = (;limits=Rect3f(Point3(0), Point3(1))))
)
Record(fig, [10, 5, 100, 60, 177]) do i
makenew[] = i
Expand Down
2 changes: 1 addition & 1 deletion ReferenceTests/src/tests/examples3d.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ using Makie: Record, volume

@cell "Image on Geometry (Moon)" begin
moon = loadasset("moon.png")
fig, ax, meshplot = mesh(Sphere(Point3f(0), 1f0), color=moon, shading=false, show_axis=false)
fig, ax, meshplot = mesh(Sphere(Point3f(0), 1f0), color=moon, shading=false, axis = (;show_axis=false))
update_cam!(ax.scene, Vec3f(-2, 2, 2), Vec3f(0))
fig
end
Expand Down
2 changes: 1 addition & 1 deletion ReferenceTests/src/tests/figures_and_makielayout.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
fig
end

@cell "Figure with Layoutables" begin
@cell "Figure with Blocks" begin
fig = Figure(resolution = (900, 900))
ax, sc = scatter(fig[1, 1][1, 1], randn(100, 2), axis = (;title = "Random Dots", xlabel = "Time"))
sc2 = scatter!(ax, randn(100, 2) .+ 2, color = :red)
Expand Down
2 changes: 1 addition & 1 deletion ReferenceTests/src/tests/short_tests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ end

@cell "volume translated" begin
r = range(-3pi, stop=3pi, length=100)
fig, ax, vplot = Makie.volume(r, r, r, (x, y, z) -> cos(x) + sin(y) + cos(z), algorithm=:iso, isorange=0.1f0, show_axis=false)
fig, ax, vplot = Makie.volume(r, r, r, (x, y, z) -> cos(x) + sin(y) + cos(z), algorithm=:iso, isorange=0.1f0, axis = (;show_axis=false))
v2 = volume!(ax, r, r, r, (x, y, z) -> cos(x) + sin(y) + cos(z), algorithm=:mip,
transformation=(translation=Vec3f(6pi, 0, 0),))
fig
Expand Down
6 changes: 3 additions & 3 deletions docs/documentation/backends/rprmakie.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ radiance = 500
lights = [EnvironmentLight(1.0, load(RPR.assetpath("studio026.exr"))),
PointLight(Vec3f(10), RGBf(radiance, radiance, radiance * 1.1))]
fig = Figure(; resolution=(1500, 700))
ax = LScene(fig[1, 1]; show_axis=false, scenekw=(lights=lights,))
ax = LScene(fig[1, 1]; show_axis=false, scenekw=(; lights=lights))
screen = RPRScreen(ax.scene; plugin=RPR.Northstar, iterations=400)

matsys = screen.matsys
Expand Down Expand Up @@ -229,7 +229,7 @@ lights = [EnvironmentLight(1.0, load(RPR.assetpath("studio026.exr"))),
PointLight(Vec3f(10), RGBf(radiance, radiance, radiance * 1.1))]

fig = Figure(; resolution=(1500, 1000))
ax = LScene(fig[1, 1]; show_axis=false, scenekw=(lights=lights,))
ax = LScene(fig[1, 1]; show_axis=false, scenekw=(; lights=lights))
screen = RPRMakie.RPRScreen(size(ax.scene); plugin=RPR.Tahoe)
material = RPR.UberMaterial(screen.matsys)

Expand Down Expand Up @@ -493,7 +493,7 @@ scene = with_theme(theme_dark()) do
radiance = 30
lights = [EnvironmentLight(0.5, load(RPR.assetpath("starmap_4k.tif"))),
PointLight(Vec3f(1, 1, 3), RGBf(radiance, radiance, radiance))]
ax = LScene(fig[1, 1]; show_axis=false, scenekw=(lights=lights,))
ax = LScene(fig[1, 1]; show_axis=false, scenekw=(;lights=lights))
n = 1024 ÷ 4 # 2048
θ = LinRange(0, pi, n)
φ = LinRange(-pi, pi, 2 * n)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
# Layoutables
# Blocks

`Layoutables` are objects which can be added to a `Figure` or `Scene` and have their location and size controlled by a `GridLayout`. In of itself, a `Layoutable` is an abstract type.
A `Figure` has its own internal `GridLayout` and therefore offers simplified syntax for adding layoutables to it.
`Blocks` are objects which can be added to a `Figure` or `Scene` and have their location and size controlled by a `GridLayout`. In of itself, a `Block` is an abstract type.
A `Figure` has its own internal `GridLayout` and therefore offers simplified syntax for adding blocks to it.
If you want to work with a bare `Scene`, you can attach a `GridLayout` to its pixel area.

!!! note
A layout only controls an object's position or bounding box.
A `Layoutable` can be controlled by the GridLayout of a Figure but not be added as a visual to the Figure.
A `Layoutable` can also be added to a Scene without being inside any GridLayout, if you specify the bounding box yourself.
A `Block` can be controlled by the GridLayout of a Figure but not be added as a visual to the Figure.
A `Block` can also be added to a Scene without being inside any GridLayout, if you specify the bounding box yourself.

## Adding to a `Figure`

Here's one way to add a `Layoutable`, in this case an `Axis`, to a Figure.
Here's one way to add a `Block`, in this case an `Axis`, to a Figure.

\begin{examplefigure}{}
```julia
Expand All @@ -27,7 +27,7 @@ f

## Specifying a boundingbox directly

Sometimes you just want to place a `Layoutable` in a specific location, without it being controlled by a dynamic layout.
Sometimes you just want to place a `Block` in a specific location, without it being controlled by a dynamic layout.
You can do this by setting the `bbox` parameter, which is usually controlled by the layout, manually.
The boundingbox should be a 2D `Rect`, and can also be an Observable if you plan to change it dynamically.
The function `BBox` creates an `Rect2f`, but instead of passing origin and widths, you pass left, right, bottom and top boundaries directly.
Expand All @@ -46,6 +46,6 @@ Axis(f, bbox = BBox(400, 700, 200, 400), title = "Axis 2")
f
```
\end{examplefigure}
## Deleting layoutables
## Deleting blocks

To remove layoutables from their layout and the figure or scene, use `delete!(layoutable)`.
To remove blocks from their layout and the figure or scene, use `delete!(block)`.
2 changes: 1 addition & 1 deletion docs/documentation/events.md
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ Furthermore you can wrap any of the above in `Exclusively` to discard matches wh

## Interactive Widgets

Makie has a couple of useful interactive widgets like sliders, buttons and menus, which you can read about in the \myreflink{Layoutables} section.
Makie has a couple of useful interactive widgets like sliders, buttons and menus, which you can read about in the \myreflink{Blocks} section.

## Recording Animations with Interactions

Expand Down
2 changes: 1 addition & 1 deletion docs/documentation/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ If `Makie` can't find your font, you can do two things:

### Elements are squashed into the lower left corner

Layoutable elements require a bounding box that they align themselves to. If you
Block elements require a bounding box that they align themselves to. If you
place such an element in a layout, the bounding box is controlled by that layout.
If you forget to put an element in a layout, it will have its default bounding box
of `BBox(0, 100, 0, 100)` which ends up being in the lower left corner. You can
Expand Down
6 changes: 3 additions & 3 deletions docs/documentation/figure.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Figures

The `Figure` object contains a top-level `Scene` and a `GridLayout`, as well as a list of layoutables that have been placed into it, like `Axis`, `Colorbar`, `Slider`, `Legend`, etc.
The `Figure` object contains a top-level `Scene` and a `GridLayout`, as well as a list of blocks that have been placed into it, like `Axis`, `Colorbar`, `Slider`, `Legend`, etc.


## Creating a `Figure`
Expand Down Expand Up @@ -34,9 +34,9 @@ You can pass arguments to the created figure in a dict-like object to the specia
scatter(rand(100, 2), figure = (resolution = (600, 400),))
```

## Placing layoutables into a `Figure`
## Placing blocks into a `Figure`

All layoutables take their parent figure as the first argument, then you can place them in the figure layout via indexing syntax.
All blocks take their parent figure as the first argument, then you can place them in the figure layout via indexing syntax.

```julia
f = Figure()
Expand Down
10 changes: 6 additions & 4 deletions docs/documentation/lighting.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,12 @@ fig, ax, pl = surface(xs, ys, zs, colormap = [:white, :white],

# Light comes from (0, 0, 15), i.e the sphere
axis = (
# Light comes from (0, 0, 15), i.e the sphere
lightposition = Vec3f(0, 0, 15),
# base light of the plot only illuminates red colors
ambient = RGBf(0.3, 0, 0),
scenekw = (
# Light comes from (0, 0, 15), i.e the sphere
lightposition = Vec3f(0, 0, 15),
# base light of the plot only illuminates red colors
ambient = RGBf(0.3, 0, 0)
),
),
# light from source (sphere) illuminates yellow colors
diffuse = Vec3f(0.4, 0.4, 0),
Expand Down
4 changes: 2 additions & 2 deletions docs/documentation/theming.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,9 @@ with_theme(example_plot, lines_theme)
```
\end{examplefigure}

## Theming layoutable objects
## Theming block objects

Every Layoutable such as `Axis`, `Legend`, `Colorbar`, etc. can be themed by using its type name as a key in your theme.
Every Block such as `Axis`, `Legend`, `Colorbar`, etc. can be themed by using its type name as a key in your theme.

Here is how you could define a simple ggplot-like style for your axes:

Expand Down
4 changes: 2 additions & 2 deletions docs/examples/layoutables.md → docs/examples/blocks.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# Layoutables & Widgets
# Blocks & Widgets

All examples in this section are presented as static CairoMakie vector graphics for clarity of visuals.
Keep in mind that CairoMakie is not interactive.
Use GLMakie for interactive widgets, as WGLMakie currently doesn't have picking implemented.

## Example gallery

{{list_folder_with_images layoutables}}
{{list_folder_with_images blocks}}
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# Box

A simple rectangle poly that is layoutable. This can be useful to make boxes for
A simple rectangle poly that is block. This can be useful to make boxes for
facet plots or when a rectangular placeholder is needed.

\begin{examplefigure}{}
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

If you need a normal Makie scene in a layout, for example for 3D plots, you have
to use `LScene` right now. It's just a wrapper around the normal `Scene` that
makes it layoutable. The underlying Scene is accessible via the `scene` field.
makes it block. The underlying Scene is accessible via the `scene` field.
You can plot into the `LScene` directly, though.

You can pass keyword arguments to the underlying `Scene` object to the `scenekw` keyword.
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
4 changes: 2 additions & 2 deletions docs/tutorials/basic-tutorial.md
Original file line number Diff line number Diff line change
Expand Up @@ -302,8 +302,8 @@ fig

## Legend and Colorbar

We have seen two `Layoutables` so far, the \myreflink{Axis} and the \myreflink{Legend} which was created by the function `axislegend`.
All `Layoutable`s can be placed into the layout of a figure at arbitrary positions, which makes it easy to assemble complex figures.
We have seen two `Blocks` so far, the \myreflink{Axis} and the \myreflink{Legend} which was created by the function `axislegend`.
All `Block`s can be placed into the layout of a figure at arbitrary positions, which makes it easy to assemble complex figures.

In the same way as with the \myreflink{Axis} before, you can also create a \myreflink{Legend} manually and then place it freely, wherever you want, in the figure.
There are multiple ways to create \myreflink{Legend}s, for one of them you pass one vector of plot objects and one vector of label strings.
Expand Down
7 changes: 4 additions & 3 deletions docs/tutorials/layout-tutorial.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,12 +153,12 @@ data2 = [sin(x^0.8) * cos(y^1.5) for x in xs, y in ys] .+ 0.1 .* randn.()
ax1, hm = contourf(gb[1, 1], xs, ys, data1,
levels = 6)
ax1.title = "Histological analysis"
contour!(xs, ys, data1, levels = 5, color = :black)
contour!(ax1, xs, ys, data1, levels = 5, color = :black)
hidexdecorations!(ax1)

_, hm2 = contourf(gb[2, 1], xs, ys, data2,
levels = 6)
contour!(xs, ys, data2, levels = 5, color = :black)
contour!(ax1, xs, ys, data2, levels = 5, color = :black)

f
```
Expand Down Expand Up @@ -215,8 +215,9 @@ Now, we move on to panel C. This is just an `Axis3` with a colorbar on the side.
```julia
brain = load(assetpath("brain.stl"))

Axis3(gc[1, 1], title = "Brain activation")
ax3d = Axis3(gc[1, 1], title = "Brain activation")
m = mesh!(
ax3d,
brain,
color = [tri[1][2] for tri in brain for i in 1:3],
colormap = Reverse(:magma),
Expand Down
6 changes: 4 additions & 2 deletions src/basic_recipes/axis.jl
Original file line number Diff line number Diff line change
Expand Up @@ -314,8 +314,10 @@ function plot!(scene::SceneLike, ::Type{<: Axis3D}, attributes::Attributes, args
axis = Axis3D(scene, attributes, args)
# Disable any non linear transform for the axis plot!
axis.transformation.transform_func[] = identity
textbuffer = TextBuffer(axis, Point3, transparency = true, markerspace = :data, inspectable = axis.inspectable)
linebuffer = LinesegmentBuffer(axis, Point3, transparency = true, inspectable = axis.inspectable)
textbuffer = TextBuffer(axis, Point3, transparency = true, markerspace = :data,
inspectable = axis.inspectable, visible = axis.visible)
linebuffer = LinesegmentBuffer(axis, Point3, transparency = true, inspectable = axis.inspectable,
visible = axis.visible)

tstyle, ticks, frame = to_value.(getindex.(axis, (:names, :ticks, :frame)))
titlevals = getindex.(tstyle, (:axisnames, :textcolor, :textsize, :rotation, :align, :font, :gap))
Expand Down
10 changes: 5 additions & 5 deletions src/figureplotting.jl
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ function plot(P::PlotFunc, args...; axis = NamedTuple(), figure = NamedTuple(),
if is2d(proxyscene)
ax = Axis(fig; axis...)
else
ax = LScene(fig; scenekw = (camera=cam3d!, axis...))
ax = LScene(fig; axis...)
end
end

Expand Down Expand Up @@ -58,7 +58,7 @@ function plot(P::PlotFunc, gp::GridPosition, args...; axis = NamedTuple(), kwarg
$(c)
If you meant to plot into an axis at this position, use the plotting function with `!` (e.g. `func!` instead of `func`).
If you really want to place an axis on top of other layoutables, make your intention clear and create it manually.
If you really want to place an axis on top of other blocks, make your intention clear and create it manually.
""")
end

Expand All @@ -74,7 +74,7 @@ function plot(P::PlotFunc, gp::GridPosition, args...; axis = NamedTuple(), kwarg
if is2d(proxyscene)
ax = Axis(f; axis...)
else
ax = LScene(f; scenekw = (camera = cam3d!, axis...))
ax = LScene(f; axis...)
end
end

Expand Down Expand Up @@ -104,7 +104,7 @@ function plot(P::PlotFunc, gsp::GridSubposition, args...; axis = NamedTuple(), k
$(c)
If you meant to plot into an axis at this position, use the plotting function with `!` (e.g. `func!` instead of `func`).
If you really want to place an axis on top of other layoutables, make your intention clear and create it manually.
If you really want to place an axis on top of other blocks, make your intention clear and create it manually.
""")
end

Expand All @@ -123,7 +123,7 @@ function plot(P::PlotFunc, gsp::GridSubposition, args...; axis = NamedTuple(), k
if is2d(proxyscene)
ax = Axis(fig; axis...)
else
ax = LScene(fig; scenekw = (camera = automatic, axis...))
ax = LScene(fig; axis..., scenekw = (camera = automatic,))
end
end

Expand Down
6 changes: 3 additions & 3 deletions src/figures.jl
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#=
Figures are supposed to fill the gap that Scenes in combination with Layoutables leave.
Figures are supposed to fill the gap that Scenes in combination with Blocks leave.
A scene is supposed to be a generic canvas on which plot objects can be placed and drawn.
Layoutables always require one specific type of scene, with a PixelCamera, in order to draw
Blocks always require one specific type of scene, with a PixelCamera, in order to draw
their visual components there.
Figures also have layouts, which scenes do not have.
This is because every figure needs a layout, while not every scene does.
Figures keep track of the Layoutables that are created inside them, which scenes don't.
Figures keep track of the Blocks that are created inside them, which scenes don't.
The idea is there are three types of plotting commands.
They can return either:
Expand Down
4 changes: 2 additions & 2 deletions src/interaction/inspector.jl
Original file line number Diff line number Diff line change
Expand Up @@ -431,8 +431,8 @@ Defaults to the current plot when called without arguments.
- `priority = 100`: The priority of creating a tooltip on a mouse movement or
scrolling event.
"""
function DataInspector(fig_or_layoutable; kwargs...)
DataInspector(fig_or_layoutable.scene; kwargs...)
function DataInspector(fig_or_block; kwargs...)
DataInspector(fig_or_block.scene; kwargs...)
end

function DataInspector(scene::Scene; priority = 100, kwargs...)
Expand Down
31 changes: 17 additions & 14 deletions src/makielayout/MakieLayout.jl
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ using GridLayoutBase
using GridLayoutBase: GridSubposition
import Showoff
using Colors
import Markdown

const FPS = Observable(30)
const COLOR_ACCENT = Ref(RGBf(((79, 122, 214) ./ 255)...))
Expand Down Expand Up @@ -49,7 +50,7 @@ function __init__()
end
end

include("layoutables.jl")
include("blocks.jl")
include("geometrybasics_extension.jl")
include("mousestatemachine.jl")
include("types.jl")
Expand All @@ -59,23 +60,25 @@ include("ticklocators/wilkinson.jl")
include("defaultattributes.jl")
include("lineaxis.jl")
include("interactions.jl")
include("layoutables/axis.jl")
include("layoutables/axis3d.jl")
include("layoutables/colorbar.jl")
include("layoutables/label.jl")
include("layoutables/slider.jl")
include("layoutables/intervalslider.jl")
include("layoutables/button.jl")
include("layoutables/box.jl")
include("layoutables/toggle.jl")
include("layoutables/legend.jl")
include("layoutables/scene.jl")
include("layoutables/menu.jl")
include("layoutables/textbox.jl")
include("blocks/axis.jl")
include("blocks/axis3d.jl")
include("blocks/colorbar.jl")
include("blocks/label.jl")
include("blocks/slider.jl")
include("blocks/slidergrid.jl")
include("blocks/intervalslider.jl")
include("blocks/button.jl")
include("blocks/box.jl")
include("blocks/toggle.jl")
include("blocks/legend.jl")
include("blocks/scene.jl")
include("blocks/menu.jl")
include("blocks/textbox.jl")

export Axis
export Axis3
export Slider
export SliderGrid
export IntervalSlider
export Button
export Colorbar
Expand Down
Loading

0 comments on commit d4f5ea8

Please sign in to comment.