From 5fafc167e88393adad9d15ff3995d5be3041eb29 Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Fri, 10 Jun 2022 12:56:41 -0400 Subject: [PATCH] First pass at an auto-layout --- src/args.jl | 1 + src/layouts.jl | 42 +++++++++++++++++++++++++++++++++++++++++- src/plot.jl | 8 ++++++++ 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/args.jl b/src/args.jl index c5fc4724a..c2fce9338 100644 --- a/src/args.jl +++ b/src/args.jl @@ -434,6 +434,7 @@ const _plot_defaults = KW( :thickness_scaling => 1, :display_type => :auto, :warn_on_unsupported => true, + :plotarea => :auto, :extra_plot_kwargs => Dict(), :extra_kwargs => :series, # directs collection of extra_kwargs ) diff --git a/src/layouts.jl b/src/layouts.jl index 6f0548de5..8b30149ad 100644 --- a/src/layouts.jl +++ b/src/layouts.jl @@ -516,7 +516,9 @@ end layout_args(n_override::Integer, layout::Union{AbstractVecOrMat,GridLayout}) = layout_args(layout) - +layout_args(n_override::Integer, mode::Symbol) = + mode === :auto ? (mode, n_override) : error("unhandled layout mode $(typeof(mode)): $mode") # pass-through mode +layout_args(mode::Symbol) = mode === :auto ? (mode, 1) : error("unhandled layout mode $(typeof(mode)): $mode") # pass-through mode layout_args(huh) = error("unhandled layout type $(typeof(huh)): $huh") # ---------------------------------------------------------------------- @@ -579,6 +581,44 @@ function build_layout(layout::GridLayout, n::Integer, plts::AVec{Plot}) layout, subplots, spmap end +# handle :auto mode, which produces a series of subplots in a square as large as necessary to accomodate them. +function build_layout(layout::Symbol, n::Integer, plts::AVec{Plot}) + layout === :auto || error("Unrecognized layout mode: $layout") + + # step 1: collect minimum sizes for each subplot or apply a default if unspecified + minsizes = Vector{Union{Symbol, Tuple{Float64, Float64}}}(undef, length(plts)) + minsizes .= get.(plts, :plotarea, Ref((150.0, 150.0))) + minsizes[minsizes .== :auto] .= Ref((150.0, 150.0)) + + plotcountx = Int(round(sqrt(length(plts)))) + plotcounty = Int(ceil(length(plts) / plotcountx)) + + # compute the total size + plotwidth = 0.0 + plotrowwidth = 0.0 + plotrowheight = 0.0 + plotheight = 0.0 + xcount = 1 + for i ∈ eachindex(minsizes) + plotrowwidth += minsizes[i][1] + plotrowheight = max(plotrowheight, minsizes[i][2]) + if xcount == plotcountx + xcount = 1 + plotheight += plotrowheight + plotwidth = max(plotwidth, plotrowwidth) + plotrowheight = 0.0 + plotrowwidth = 0.0 + else + xcount += 1 + end + end + + layout = GridLayout(plotcounty, plotcountx) + layout.attr[:width] = plotwidth + layout.attr[:height] = plotheight + build_layout(layout, n, plts) +end + # ------------------------------------------------------------------------- # make all reference the same axis extrema/values. diff --git a/src/plot.jl b/src/plot.jl index da9aa8cf6..2e364cf31 100644 --- a/src/plot.jl +++ b/src/plot.jl @@ -141,6 +141,14 @@ function plot!(plt1::Plot, plt2::Plot, plts_tail::Plot...; kw...) # create the layout plt.layout, plt.subplots, plt.spmap = build_layout(layout, num_sp, copy(plts)) + if layout === :auto + if plt.attr[:size][1] < plt.layout.attr[:width] + plt.attr[:size] = (plt.layout.attr[:width], plt.attr[:size][2]) + end + if plt.attr[:size][2] < plt.layout.attr[:height] + plt.attr[:size] = (plt.attr[:size][1], plt.layout.attr[:height]) + end + end # do we need to link any axes together? link_axes!(plt.layout, plt[:link])