diff --git a/src/components.jl b/src/components.jl index d07bcce0..c2887516 100644 --- a/src/components.jl +++ b/src/components.jl @@ -573,64 +573,52 @@ function Base.iterate(ea::EachAnn, i = 1) ((_cycle(ea.x,i), _cycle(ea.y,i), str, fnt), i+1) end +# ----------------------------------------------------------------------- annotations(::Nothing) = [] annotations(anns::AVec) = anns annotations(anns::AMat) = map(annotations, anns) annotations(anns) = Any[anns] annotations(sa::SeriesAnnotations) = sa +_annotationfont(sp::Subplot) = Plots.font(; + family=sp[:annotationfontfamily], + pointsize=sp[:annotationfontsize], + halign=sp[:annotationhalign], + valign=sp[:annotationvalign], + rotation=sp[:annotationrotation], + color=sp[:annotationcolor], +) + +_annotation(sp, font, lab, pos...; alphabet="abcdefghijklmnopqrstuvwxyz") = ( + if lab == :auto + (pos..., text("($(alphabet[sp[:subplot_index]]))", font)) + else + (pos..., isa(lab, PlotText) ? lab : isa(lab, Tuple) ? text(lab[1], font, lab[2:end]...) : text(lab, font)) + end +) + # Expand arrays of coordinates, positions and labels into induvidual annotations # and make sure labels are of type PlotText -function process_annotation(sp::Subplot, xs, ys, labs, font = nothing) +function process_annotation(sp::Subplot, xs, ys, labs, font=_annotationfont(sp)) anns = [] labs = makevec(labs) xlength = length(methods(length, (typeof(xs),))) == 0 ? 1 : length(xs) ylength = length(methods(length, (typeof(ys),))) == 0 ? 1 : length(ys) - if isnothing(font) - font = Plots.font(; - family=sp[:annotationfontfamily], - pointsize=sp[:annotationfontsize], - halign=sp[:annotationhalign], - valign=sp[:annotationvalign], - rotation=sp[:annotationrotation], - color=sp[:annotationcolor], - ) - end for i in 1:max(xlength, ylength, length(labs)) x, y, lab = _cycle(xs, i), _cycle(ys, i), _cycle(labs, i) - x = typeof(x) <: TimeType ? Dates.value(x) : x - y = typeof(y) <: TimeType ? Dates.value(y) : y - if lab == :auto - alphabet = "abcdefghijklmnopqrstuvwxyz" - push!(anns, (x, y, text(string("(", alphabet[sp[:subplot_index]], ")"), font))) - else - push!(anns, (x, y, isa(lab, PlotText) ? lab : isa(lab, Tuple) ? text(lab[1], font, lab[2:end]...) : text(lab, font))) - end + x = typeof(x) <: TimeType ? Dates.value(x) : x + y = typeof(y) <: TimeType ? Dates.value(y) : y + push!(anns, _annotation(sp, font, lab, x, y)) end anns end -function process_annotation(sp::Subplot, positions::Union{AVec{Symbol},Symbol}, labs, font = nothing) + +function process_annotation(sp::Subplot, positions::Union{AVec{Symbol},Symbol,Tuple}, labs, font=_annotationfont(sp)) anns = [] positions, labs = makevec(positions), makevec(labs) - if isnothing(font) - font = Plots.font(; - family=sp[:annotationfontfamily], - pointsize=sp[:annotationfontsize], - halign=sp[:annotationhalign], - valign=sp[:annotationvalign], - rotation=sp[:annotationrotation], - color=sp[:annotationcolor], - ) - end for i in 1:max(length(positions), length(labs)) pos, lab = _cycle(positions, i), _cycle(labs, i) - pos = get(_positionAliases, pos, pos) - if lab == :auto - alphabet = "abcdefghijklmnopqrstuvwxyz" - push!(anns, (pos, text(string("(", alphabet[sp[:subplot_index]], ")"), font))) - else - push!(anns, (pos, isa(lab, PlotText) ? lab : isa(lab, Tuple) ? text(lab[1], font, lab[2:end]...) : text(lab, font))) - end + push!(anns, _annotation(sp, font, lab, get(_positionAliases, pos, pos))) end anns end @@ -640,7 +628,7 @@ process_any_label(lab, font=Font()) = lab isa Tuple ? text(lab...) : text(lab, f _relative_position(xmin, xmax, pos::Length{:pct}) = xmin + pos.value * (xmax - xmin) # Give each annotation coordinates based on specified position -locate_annotation( +function locate_annotation( sp::Subplot, pos::Symbol, label::PlotText; position_multiplier=Dict{Symbol, Tuple{Float64,Float64}}( :topleft => (0.1pct, 0.9pct), @@ -650,7 +638,7 @@ locate_annotation( :bottomcenter => (0.5pct, 0.1pct), :bottomright => (0.9pct, 0.1pct), ) -) = begin +) x, y = position_multiplier[pos] ( _relative_position(axis_limits(sp, :x)..., x), @@ -661,15 +649,15 @@ end locate_annotation(sp::Subplot, x, y, label::PlotText) = (x, y, label) locate_annotation(sp::Subplot, x, y, z, label::PlotText) = (x, y, z, label) -locate_annotation(sp::Subplot, x::Length{:pct}, y::Length{:pct}, label::PlotText) = ( - _relative_position(axis_limits(sp, :x)..., x), - _relative_position(axis_limits(sp, :y)..., y), +locate_annotation(sp::Subplot, rel::NTuple{2,<:Number}, label::PlotText) = ( + _relative_position(axis_limits(sp, :x)..., rel[1] * Plots.pct), + _relative_position(axis_limits(sp, :y)..., rel[2] * Plots.pct), label ) -locate_annotation(sp::Subplot, x::Length{:pct}, y::Length{:pct}, z::Length{:pct}, label::PlotText) = ( - _relative_position(axis_limits(sp, :x)..., x), - _relative_position(axis_limits(sp, :y)..., y), - _relative_position(axis_limits(sp, :z)..., z), +locate_annotation(sp::Subplot, rel::NTuple{3,<:Number}, label::PlotText) = ( + _relative_position(axis_limits(sp, :x)..., rel[1] * Plots.pct), + _relative_position(axis_limits(sp, :y)..., rel[2] * Plots.pct), + _relative_position(axis_limits(sp, :z)..., rel[3] * Plots.pct), label ) # -----------------------------------------------------------------------