diff --git a/src/Plots.jl b/src/Plots.jl index 152f0f24..3eaab2f6 100644 --- a/src/Plots.jl +++ b/src/Plots.jl @@ -18,6 +18,7 @@ using Base.Meta import Showoff import StatsBase import JSON +import RecipeUtils: _process_userrecipes, _process_plotrecipe, _process_seriesrecipe using Requires diff --git a/src/pipeline.jl b/src/pipeline.jl index 1e9cd991..2cd14550 100644 --- a/src/pipeline.jl +++ b/src/pipeline.jl @@ -59,39 +59,6 @@ end # user recipes -function _process_userrecipes(plt::Plot, plotattributes::AKW, args) - still_to_process = RecipeData[] - args = _preprocess_args(plotattributes, args, still_to_process) - - # for plotting recipes, swap out the args and update the parameter dictionary - # we are keeping a stack of series that still need to be processed. - # each pass through the loop, we pop one off and apply the recipe. - # the recipe will return a list a Series objects... the ones that are - # finished (no more args) get added to the kw_list, the ones that are not - # are placed on top of the stack and are then processed further. - kw_list = KW[] - while !isempty(still_to_process) - # grab the first in line to be processed and either add it to the kw_list or - # pass it through apply_recipe to generate a list of RecipeData objects (data + attributes) - # for further processing. - next_series = popfirst!(still_to_process) - # recipedata should be of type RecipeData. if it's not then the inputs must not have been fully processed by recipes - if !(typeof(next_series) <: RecipeData) - error("Inputs couldn't be processed... expected RecipeData but got: $next_series") - end - if isempty(next_series.args) - _process_userrecipe(plt, kw_list, next_series) - else - rd_list = RecipesBase.apply_recipe(next_series.plotattributes, next_series.args...) - prepend!(still_to_process,rd_list) - end - end - - # don't allow something else to handle it - plotattributes[:smooth] = false - kw_list -end - function _process_userrecipe(plt::Plot, kw_list::Vector{KW}, recipedata::RecipeData) # when the arg tuple is empty, that means there's nothing left to recursively # process... finish up and add to the kw_list @@ -168,39 +135,6 @@ function _add_smooth_kw(kw_list::Vector{KW}, kw::AKW) end # ------------------------------------------------------------------ -# plot recipes - -# Grab the first in line to be processed and pass it through apply_recipe -# to generate a list of RecipeData objects (data + attributes). -# If we applied a "plot recipe" without error, then add the returned datalist's KWs, -# otherwise we just add the original KW. -function _process_plotrecipe(plt::Plot, kw::AKW, kw_list::Vector{KW}, still_to_process::Vector{KW}) - if !isa(get(kw, :seriestype, nothing), Symbol) - # seriestype was never set, or it's not a Symbol, so it can't be a plot recipe - push!(kw_list, kw) - return - end - try - st = kw[:seriestype] - st = kw[:seriestype] = get(_typeAliases, st, st) - datalist = RecipesBase.apply_recipe(kw, Val{st}, plt) - for data in datalist - preprocessArgs!(data.plotattributes) - if data.plotattributes[:seriestype] == st - error("Plot recipe $st returned the same seriestype: $(data.plotattributes)") - end - push!(still_to_process, data.plotattributes) - end - catch err - if isa(err, MethodError) - push!(kw_list, kw) - else - rethrow() - end - end - return -end - # ------------------------------------------------------------------ # setup plot and subplot @@ -382,47 +316,3 @@ function _add_the_series(plt, sp, plotattributes) push!(sp.series_list, series) _series_added(plt, series) end - -# ------------------------------------------------------------------------------- - -# this method recursively applies series recipes when the seriestype is not supported -# natively by the backend -function _process_seriesrecipe(plt::Plot, plotattributes::AKW) - #println("process $(typeof(plotattributes))") - # replace seriestype aliases - st = Symbol(plotattributes[:seriestype]) - st = plotattributes[:seriestype] = get(_typeAliases, st, st) - - # shapes shouldn't have fillrange set - if plotattributes[:seriestype] == :shape - plotattributes[:fillrange] = nothing - end - - # if it's natively supported, finalize processing and pass along to the backend, otherwise recurse - if is_seriestype_supported(st) - sp = _prepare_subplot(plt, plotattributes) - _prepare_annotations(sp, plotattributes) - _expand_subplot_extrema(sp, plotattributes, st) - _update_series_attributes!(plotattributes, plt, sp) - _add_the_series(plt, sp, plotattributes) - - else - # get a sub list of series for this seriestype - datalist = RecipesBase.apply_recipe(plotattributes, Val{st}, plotattributes[:x], plotattributes[:y], plotattributes[:z]) - - # assuming there was no error, recursively apply the series recipes - for data in datalist - if isa(data, RecipeData) - preprocessArgs!(data.plotattributes) - if data.plotattributes[:seriestype] == st - error("The seriestype didn't change in series recipe $st. This will cause a StackOverflow.") - end - _process_seriesrecipe(plt, data.plotattributes) - else - @warn("Unhandled recipe: $(data)") - break - end - end - end - nothing -end