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
This commit is contained in:
parent
4ef392b0b5
commit
5fbde91734
@ -46,7 +46,7 @@ Measures = "0.3"
|
|||||||
NaNMath = "0.3"
|
NaNMath = "0.3"
|
||||||
PlotThemes = "2"
|
PlotThemes = "2"
|
||||||
PlotUtils = "1"
|
PlotUtils = "1"
|
||||||
RecipesBase = "1"
|
RecipesBase = "1.2"
|
||||||
RecipesPipeline = "0.3.5, 0.4"
|
RecipesPipeline = "0.3.5, 0.4"
|
||||||
Reexport = "0.2, 1.0"
|
Reexport = "0.2, 1.0"
|
||||||
Requires = "1"
|
Requires = "1"
|
||||||
|
|||||||
@ -268,7 +268,6 @@ function _precompile_()
|
|||||||
Base.precompile(Tuple{typeof(bbox),Float64,Float64,Float64,Float64})
|
Base.precompile(Tuple{typeof(bbox),Float64,Float64,Float64,Float64})
|
||||||
Base.precompile(Tuple{typeof(build_layout),GridLayout,Int64,Vector{Plot}})
|
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(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},Vararg{Vector{Float64}, N} where N})
|
||||||
Base.precompile(Tuple{typeof(error_coords),Vector{Float64},Vector{Float64},Vector{Float64}})
|
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}}})
|
Base.precompile(Tuple{typeof(error_zipit),Tuple{Vector{Float64}, Vector{Float64}, Vector{Float64}}})
|
||||||
|
|||||||
@ -25,7 +25,7 @@ using SparseArrays
|
|||||||
using FFMPEG
|
using FFMPEG
|
||||||
|
|
||||||
@reexport using RecipesBase
|
@reexport using RecipesBase
|
||||||
import RecipesBase: plot, plot!, animate, is_explicit
|
import RecipesBase: plot, plot!, animate, is_explicit, grid
|
||||||
using Base.Meta
|
using Base.Meta
|
||||||
@reexport using PlotUtils
|
@reexport using PlotUtils
|
||||||
@reexport using PlotThemes
|
@reexport using PlotThemes
|
||||||
@ -42,7 +42,6 @@ export
|
|||||||
grid,
|
grid,
|
||||||
bbox,
|
bbox,
|
||||||
plotarea,
|
plotarea,
|
||||||
@layout,
|
|
||||||
KW,
|
KW,
|
||||||
|
|
||||||
wrap,
|
wrap,
|
||||||
@ -167,6 +166,8 @@ const BBox = Measures.Absolute2DBox
|
|||||||
const px = AbsoluteLength(0.254)
|
const px = AbsoluteLength(0.254)
|
||||||
const pct = Length{:pct,Float64}(1.0)
|
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::AbsoluteLength, m2::Length{:pct}) = AbsoluteLength(m1.value * m2.value)
|
||||||
Base.:*(m1::Length{:pct}, m2::AbsoluteLength) = AbsoluteLength(m2.value * m1.value)
|
Base.:*(m1::Length{:pct}, m2::AbsoluteLength) = AbsoluteLength(m2.value * m1.value)
|
||||||
Base.:/(m1::AbsoluteLength, m2::Length{:pct}) = AbsoluteLength(m1.value / m2.value)
|
Base.:/(m1::AbsoluteLength, m2::Length{:pct}) = AbsoluteLength(m1.value / m2.value)
|
||||||
|
|||||||
@ -1743,7 +1743,7 @@ function slice_arg!(
|
|||||||
)
|
)
|
||||||
v = get(plotattributes_in, k, plotattributes_out[k])
|
v = get(plotattributes_in, k, plotattributes_out[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)
|
slice_arg(v, idx)
|
||||||
else
|
else
|
||||||
v
|
v
|
||||||
|
|||||||
149
src/layouts.jl
149
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)
|
function Base.setindex!(layout::GridLayout, v, r::Int, c::Int)
|
||||||
layout.grid[r, c] = v
|
layout.grid[r, c] = v
|
||||||
end
|
end
|
||||||
|
function Base.setindex!(layout::GridLayout, v, ci::CartesianIndex)
|
||||||
|
layout.grid[ci] = v
|
||||||
|
end
|
||||||
|
|
||||||
leftpad(layout::GridLayout) = layout.minpad[1]
|
leftpad(layout::GridLayout) = layout.minpad[1]
|
||||||
toppad(layout::GridLayout) = layout.minpad[2]
|
toppad(layout::GridLayout) = layout.minpad[2]
|
||||||
@ -491,6 +494,19 @@ function layout_args(sztup::NTuple{3,Integer})
|
|||||||
GridLayout(nr, nc), n
|
GridLayout(nr, nc), n
|
||||||
end
|
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
|
# compute number of subplots
|
||||||
function layout_args(layout::GridLayout)
|
function layout_args(layout::GridLayout)
|
||||||
# recursively get the size of the grid
|
# recursively get the size of the grid
|
||||||
@ -498,7 +514,7 @@ function layout_args(layout::GridLayout)
|
|||||||
layout, n
|
layout, n
|
||||||
end
|
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")
|
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
|
layout, subplots, spmap
|
||||||
end
|
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
|
|
||||||
|
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user