diff --git a/MakieCore/src/attributes.jl b/MakieCore/src/attributes.jl index 68d25aa0dcb..e1cfbb93234 100644 --- a/MakieCore/src/attributes.jl +++ b/MakieCore/src/attributes.jl @@ -250,14 +250,15 @@ function get_attribute(dict, key, default=nothing) end function merge_attributes!(input::Attributes, theme::Attributes) - for (key, value) in theme + for (key, value) in attributes(theme) if !haskey(input, key) input[key] = value else current_value = input[key] - if value isa Attributes && current_value isa Attributes + tvalue = to_value(value) + if tvalue isa Attributes && current_value isa Attributes # if nested attribute, we merge recursively - merge_attributes!(current_value, value) + merge_attributes!(current_value, tvalue) end # we're good! input already has a value, can ignore theme end diff --git a/MakieCore/src/recipes.jl b/MakieCore/src/recipes.jl index db92b981e05..90151646618 100644 --- a/MakieCore/src/recipes.jl +++ b/MakieCore/src/recipes.jl @@ -26,23 +26,12 @@ plotkey(::Nothing) = :scatter argtypes(F, tuple::T) where {T <: Tuple} = (F, T) function create_plot(P::Type{<: Combined{F}}, args, kw) where F - if first(args) isa Attributes - merge!(kw, attributes(popfirst!(args))) - end - args_converted = convert_arguments(P, map(to_value, args)...) - f_argtypes = argtypes(F, args_converted) - return Combined{f_argtypes...}(kw, args) + return Combined{F}(kw, args) end function create_plot(P::Type{<:Any}, args, kw) - if first(args) isa Attributes - merge!(kw, attributes(popfirst!(args))) - end - args_conv = map(to_value, args) - P = plottype(args_conv...) - args_converted = convert_arguments(P, args_conv...) - ArgTypes = Tuple{typeof.(args_converted)...} - return Combined{plotfunc(P),ArgTypes}(kw, args) + P = plottype(args...) + return Combined{plotfunc(P)}(kw, args) end function create_figurelike end @@ -50,26 +39,23 @@ function create_figurelike! end function figurelike_return end function figurelike_return! end -function _create_plot(F, kw, args...) +function _create_plot(F, attributes, args...) P = Combined{F} - attributes = Dict{Symbol,Any}(kw) figlike, plot_kw, plot_args = create_figurelike(P, attributes, args...) - plot = create_plot(P, Any[plot_args...], plot_kw) + plot = Combined{F}(plot_args, plot_kw) plot!(figlike, plot) return figurelike_return(figlike, plot) end -function _create_plot!(F, kw, args...) - P = Combined{F} - attributes = Dict{Symbol,Any}(kw) - figlike, plot_kw, plot_args = create_figurelike!(P, attributes, args...) - plot = create_plot(P, Any[plot_args...], plot_kw) +function _create_plot!(F, attributes, args...) + figlike, plot_kw, plot_args = create_figurelike!(Combined{F}, attributes, args...) + plot = Combined{F}(plot_args, plot_kw) plot!(figlike, plot) return figurelike_return!(figlike, plot) end function _create_plot!(F, kw, scene::SceneLike, args...) - plot = create_plot(Combined{F}, Any[args...], Dict{Symbol,Any}(kw)) + plot = Combined{F}(args, kw) plot!(scene, plot) return plot end @@ -211,8 +197,8 @@ macro recipe(theme_func, Tsym::Symbol, args::Symbol...) $(funcname)() = not_implemented_for($funcname) const $(PlotType){$(esc(:ArgType))} = Combined{$funcname,$(esc(:ArgType))} $(MakieCore).plotsym(::Type{<:$(PlotType)}) = $(QuoteNode(Tsym)) - Core.@__doc__ ($funcname)(args...; kw...) = _create_plot($funcname, kw, args...) - ($funcname!)(args...; kw...) = _create_plot!($funcname, kw, args...) + Core.@__doc__ ($funcname)(args...; kw...) = _create_plot($funcname, Dict{Symbol, Any}(kw), args...) + ($funcname!)(args...; kw...) = _create_plot!($funcname, Dict{Symbol, Any}(kw), args...) $(MakieCore).default_theme(scene, ::Type{<:$PlotType}) = $(esc(theme_func))(scene) export $PlotType, $funcname, $funcname! end diff --git a/src/figureplotting.jl b/src/figureplotting.jl index 4d90c0d4699..852ad4150b8 100644 --- a/src/figureplotting.jl +++ b/src/figureplotting.jl @@ -103,7 +103,8 @@ function create_axis_from_kw(PlotType, figlike, attributes::Dict, args...) else preferred_axis_type(PlotType, args...) end - return AxType(figlike; axis_kw...) + bbox = pop!(axis_kw, :bbox, nothing) + return _block(AxType, figlike, [], axis_kw, bbox) end function create_figurelike(PlotType, attributes::Dict, args...) diff --git a/src/interfaces.jl b/src/interfaces.jl index ebdb636b7da..8de01f8347b 100644 --- a/src/interfaces.jl +++ b/src/interfaces.jl @@ -87,7 +87,30 @@ const atomic_function_symbols = ( const atomic_functions = getfield.(Ref(Makie), atomic_function_symbols) const Atomic{Arg} = Union{map(x-> Combined{x, Arg}, atomic_functions)...} -function Combined{Func, ArgTypes}(plot_attributes, args) where {Func, ArgTypes} + + +function convert_arguments!(plot::Combined{F}) where {F} + P = Combined{F,Any} + function on_update(args...) + nt = convert_arguments(P, args...) + P, converted = apply_convert!(P, plot.attributes, nt) + for (obs, new_val) in zip(plot.converted, converted) + obs[] = new_val + end + end + onany(on_update, plot, plot.args...) + return +end + + +function Combined{Func}(args::Tuple, plot_attributes::Dict) where {Func} + if first(args) isa Attributes + merge!(plot_attributes, attributes(first(args))) + return Combined{Func}(Base.tail(args), plot_attributes) + end + P = Combined{Func} + args_converted = convert_arguments(P, map(to_value, args)...) + P2, converted = apply_convert!(P, Attributes(), args_converted) trans = get!(plot_attributes, :transformation, automatic) transval = to_value(trans) transformation = if transval isa Automatic @@ -99,7 +122,12 @@ function Combined{Func, ArgTypes}(plot_attributes, args) where {Func, ArgTypes} transform!(t, transval) t end - plot = Combined{Func,ArgTypes}(transformation, plot_attributes, convert.(Observable, args)) + + obs_args = Any[convert(Observable, x) for x in args] + + f_argtypes = MakieCore.argtypes(plotfunc(P2), converted) + plot = Combined{f_argtypes...}(transformation, plot_attributes, obs_args) + plot.converted = map(Observable, converted) plot.model = transformationmatrix(transformation) return plot end @@ -230,7 +258,7 @@ end function apply_theme!(scene::Scene, plot::Combined{F}) where {F} theme = default_theme(scene, Combined{F, Any}) - raw_attr = getfield(plot.attributes, :attributes) + raw_attr = attributes(plot.attributes) for (k, v) in plot.kw if v isa NamedTuple raw_attr[k] = Attributes(v) @@ -261,22 +289,3 @@ function MakieCore.argtypes(F, plot::PlotSpec{P}) where {P} args_converted = convert_arguments(P, plot.args...) return MakieCore.argtypes(plotfunc(P), args_converted) end - - -function convert_arguments!(plot::Combined{F}) where F - P = Combined{F, Any} - function on_update(args...) - nt = convert_arguments(P, args...) - P, converted = apply_convert!(P, plot.attributes, nt) - if isempty(plot.converted) - # initialize the tuple first for when it was `()` - plot.converted = Observable.(converted) - end - for (obs, new_val) in zip(plot.converted, converted) - obs[] = new_val - end - end - on_update(map(to_value, plot.args)...) - onany(on_update, plot, plot.args...) - return -end diff --git a/src/makielayout/blocks.jl b/src/makielayout/blocks.jl index ef9aa74d6f5..544adfcbc7b 100644 --- a/src/makielayout/blocks.jl +++ b/src/makielayout/blocks.jl @@ -273,12 +273,14 @@ function _block(T::Type{<:Block}, b end -function _block(T::Type{<:Block}, fig_or_scene::Union{Figure, Scene}, - args...; bbox = nothing, kwargs...) - # first sort out all user kwargs that correspond to block attributes +function _block(T::Type{<:Block}, fig_or_scene::Union{Figure, Scene}, args...; bbox = nothing, kwargs...) + return _block(T, fig_or_scene, Any[args...], Dict{Symbol,Any}(kwargs), bbox) +end - kwdict = Dict(kwargs) +function _block(T::Type{<:Block}, fig_or_scene::Union{Figure,Scene}, args, kwdict::Dict, bbox) + + # first sort out all user kwargs that correspond to block attributes if haskey(kwdict, :textsize) throw(ArgumentError("The attribute `textsize` has been renamed to `fontsize` in Makie v0.19. Please change all occurrences of `textsize` to `fontsize` or revert back to an earlier version.")) diff --git a/src/makielayout/blocks/axis.jl b/src/makielayout/blocks/axis.jl index d35ab44eadc..86d1518392c 100644 --- a/src/makielayout/blocks/axis.jl +++ b/src/makielayout/blocks/axis.jl @@ -158,7 +158,6 @@ function compute_protrusions(title, titlesize, titlegap, titlevisible, spinewidt end function initialize_block!(ax::Axis; palette = nothing) - blockscene = ax.blockscene elements = Dict{Symbol, Any}()