From 5fbde917345a256baa23aced1d15c6a1a0880f87 Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Thu, 25 Nov 2021 11:40:25 +0100 Subject: [PATCH] rework layout macro to use Base types (#3943) * @layout -> Base types except for `grid` call * add layout conversion of namedtuples, vectors and matrices * add missing method * rip it out * fix slicing * adjust compat * add Measure conversion --- Project.toml | 2 +- .../precompile/precompile_Plots.jl | 1 - src/Plots.jl | 5 +- src/args.jl | 2 +- src/layouts.jl | 149 ++---------------- 5 files changed, 22 insertions(+), 137 deletions(-) diff --git a/Project.toml b/Project.toml index af93d675..3981d0bb 100644 --- a/Project.toml +++ b/Project.toml @@ -46,7 +46,7 @@ Measures = "0.3" NaNMath = "0.3" PlotThemes = "2" PlotUtils = "1" -RecipesBase = "1" +RecipesBase = "1.2" RecipesPipeline = "0.3.5, 0.4" Reexport = "0.2, 1.0" Requires = "1" diff --git a/deps/SnoopCompile/precompile/precompile_Plots.jl b/deps/SnoopCompile/precompile/precompile_Plots.jl index e5fac265..75cfa8e2 100644 --- a/deps/SnoopCompile/precompile/precompile_Plots.jl +++ b/deps/SnoopCompile/precompile/precompile_Plots.jl @@ -268,7 +268,6 @@ function _precompile_() Base.precompile(Tuple{typeof(bbox),Float64,Float64,Float64,Float64}) Base.precompile(Tuple{typeof(build_layout),GridLayout,Int64,Vector{Plot}}) Base.precompile(Tuple{typeof(convert_to_polar),StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}},Vector{Float64},Tuple{Int64, Float64}}) - Base.precompile(Tuple{typeof(create_grid),Expr}) Base.precompile(Tuple{typeof(error_coords),Vector{Float64},Vector{Float64},Vector{Float64},Vararg{Vector{Float64}, N} where N}) Base.precompile(Tuple{typeof(error_coords),Vector{Float64},Vector{Float64},Vector{Float64}}) Base.precompile(Tuple{typeof(error_zipit),Tuple{Vector{Float64}, Vector{Float64}, Vector{Float64}}}) diff --git a/src/Plots.jl b/src/Plots.jl index d11ef67a..4aff05a2 100644 --- a/src/Plots.jl +++ b/src/Plots.jl @@ -25,7 +25,7 @@ using SparseArrays using FFMPEG @reexport using RecipesBase -import RecipesBase: plot, plot!, animate, is_explicit +import RecipesBase: plot, plot!, animate, is_explicit, grid using Base.Meta @reexport using PlotUtils @reexport using PlotThemes @@ -42,7 +42,6 @@ export grid, bbox, plotarea, - @layout, KW, wrap, @@ -167,6 +166,8 @@ const BBox = Measures.Absolute2DBox const px = AbsoluteLength(0.254) const pct = Length{:pct,Float64}(1.0) +Base.convert(::Type{<:Measure}, x::Float64) = x * pct + Base.:*(m1::AbsoluteLength, m2::Length{:pct}) = AbsoluteLength(m1.value * m2.value) Base.:*(m1::Length{:pct}, m2::AbsoluteLength) = AbsoluteLength(m2.value * m1.value) Base.:/(m1::AbsoluteLength, m2::Length{:pct}) = AbsoluteLength(m1.value / m2.value) diff --git a/src/args.jl b/src/args.jl index 1dbf185a..d5c3115a 100644 --- a/src/args.jl +++ b/src/args.jl @@ -1743,7 +1743,7 @@ function slice_arg!( ) v = get(plotattributes_in, k, plotattributes_out[k]) plotattributes_out[k] = - if haskey(plotattributes_in, k) && typeof(v) <: AMat && !isempty(v) + if haskey(plotattributes_in, k) && typeof(v) <: AMat && !isempty(v) && !(k in _plot_args) slice_arg(v, idx) else v diff --git a/src/layouts.jl b/src/layouts.jl index 3d620fd1..f9ec793d 100644 --- a/src/layouts.jl +++ b/src/layouts.jl @@ -269,6 +269,9 @@ Base.getindex(layout::GridLayout, r::Int, c::Int) = layout.grid[r, c] function Base.setindex!(layout::GridLayout, v, r::Int, c::Int) layout.grid[r, c] = v end +function Base.setindex!(layout::GridLayout, v, ci::CartesianIndex) + layout.grid[ci] = v +end leftpad(layout::GridLayout) = layout.minpad[1] toppad(layout::GridLayout) = layout.minpad[2] @@ -491,6 +494,19 @@ function layout_args(sztup::NTuple{3,Integer}) GridLayout(nr, nc), n end +layout_args(nt::NamedTuple) = EmptyLayout(;nt...), 1 + +function layout_args(m::AbstractVecOrMat) + sz = size(m) + nr = sz[1] + nc = get(sz, 2, 1) + gl = GridLayout(nr, nc) + for ci in CartesianIndices(m) + gl[ci] = layout_args(m[ci])[1] + end + layout_args(gl) +end + # compute number of subplots function layout_args(layout::GridLayout) # recursively get the size of the grid @@ -498,7 +514,7 @@ function layout_args(layout::GridLayout) layout, n end -layout_args(n_override::Integer, layout::GridLayout) = layout_args(layout) +layout_args(n_override::Integer, layout::Union{AbstractVecOrMat,GridLayout}) = layout_args(layout) layout_args(huh) = error("unhandled layout type $(typeof(huh)): $huh") @@ -562,137 +578,6 @@ function build_layout(layout::GridLayout, n::Integer, plts::AVec{Plot}) layout, subplots, spmap end -# ---------------------------------------------------------------------- -# @layout macro - -function add_layout_pct!(kw::AKW, v::Expr, idx::Integer, nidx::Integer) - # dump(v) - # something like {0.2w}? - if v.head == :call && v.args[1] == :* - num = v.args[2] - if length(v.args) == 3 && isa(num, Number) - units = v.args[3] - if units == :h - return kw[:h] = num * pct - elseif units == :w - return kw[:w] = num * pct - elseif units in (:pct, :px, :mm, :cm, :inch) - idx == 1 && (kw[:w] = v) - (idx == 2 || nidx == 1) && (kw[:h] = v) - # return kw[idx == 1 ? :w : :h] = v - end - end - end - error("Couldn't match layout curly (idx=$idx): $v") -end - -function add_layout_pct!(kw::AKW, v::Number, idx::Integer) - # kw[idx == 1 ? :w : :h] = v*pct - idx == 1 && (kw[:w] = v * pct) - (idx == 2 || nidx == 1) && (kw[:h] = v * pct) -end - -isrow(v) = isa(v, Expr) && v.head in (:hcat, :row) -iscol(v) = isa(v, Expr) && v.head == :vcat -rowsize(v) = isrow(v) ? length(v.args) : 1 - -function create_grid(expr::Expr) - if iscol(expr) - create_grid_vcat(expr) - elseif isrow(expr) - :( - let cell = GridLayout(1, $(length(expr.args))) - $( - [ - :(cell[1, $i] = $(create_grid(v))) for - (i, v) in enumerate(expr.args) - ]... - ) - cell - end - ) - - elseif expr.head == :curly - create_grid_curly(expr) - else - # if it's something else, just return that (might be an existing layout?) - esc(expr) - end -end - -function create_grid_vcat(expr::Expr) - rowsizes = map(rowsize, expr.args) - rmin, rmax = extrema(rowsizes) - if rmin > 0 && rmin == rmax - # we have a grid... build the whole thing - # note: rmin is the number of columns - nr = length(expr.args) - nc = rmin - body = Expr(:block) - for r in 1:nr - arg = expr.args[r] - if isrow(arg) - for (c, item) in enumerate(arg.args) - push!(body.args, :(cell[$r, $c] = $(create_grid(item)))) - end - else - push!(body.args, :(cell[$r, 1] = $(create_grid(arg)))) - end - end - :( - let cell = GridLayout($nr, $nc) - $body - cell - end - ) - else - # otherwise just build one row at a time - :( - let cell = GridLayout($(length(expr.args)), 1) - $( - [ - :(cell[$i, 1] = $(create_grid(v))) for - (i, v) in enumerate(expr.args) - ]... - ) - cell - end - ) - end -end - -function create_grid_curly(expr::Expr) - kw = KW() - for (i, arg) in enumerate(expr.args[2:end]) - add_layout_pct!(kw, arg, i, length(expr.args) - 1) - end - s = expr.args[1] - if isa(s, Expr) && s.head == :call && s.args[1] == :grid - create_grid( - :(grid( - $(s.args[2:end]...), - width = $(get(kw, :w, QuoteNode(:auto))), - height = $(get(kw, :h, QuoteNode(:auto))), - )), - ) - elseif isa(s, Symbol) - :(EmptyLayout( - label = $(QuoteNode(s)), - width = $(get(kw, :w, QuoteNode(:auto))), - height = $(get(kw, :h, QuoteNode(:auto))), - )) - else - error("Unknown use of curly brackets: $expr") - end -end - -function create_grid(s::Symbol) - :(EmptyLayout(label = $(QuoteNode(s)), blank = $(s == :_))) -end - -macro layout(mat::Expr) - create_grid(mat) -end # -------------------------------------------------------------------------