diff --git a/Project.toml b/Project.toml index c4b75b7d..30e9b1bb 100644 --- a/Project.toml +++ b/Project.toml @@ -21,7 +21,7 @@ PlotUtils = "995b91a9-d308-5afd-9ec6-746e21dbc043" Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" -RecipeUtils = "01d81517-befc-4cb6-b9ec-a95719d0359c" +RecipePipeline = "01d81517-befc-4cb6-b9ec-a95719d0359c" RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" Reexport = "189a3867-3050-52da-a836-e630ba90ab69" Requires = "ae029012-a4dd-5104-9daa-d747884805df" diff --git a/src/Plots.jl b/src/Plots.jl index 85caf4b5..4293b811 100644 --- a/src/Plots.jl +++ b/src/Plots.jl @@ -18,10 +18,13 @@ using Base.Meta import Showoff import StatsBase import JSON -import RecipeUtils: _process_userrecipes, _process_plotrecipe, +import RecipePipeline: _process_userrecipes, _process_plotrecipe, _process_seriesrecipe, _preprocess_args, preprocessArgs!, is_st_supported, - finalize_subplot! + recipe_pipeline!, + _recipe_init!, _recipe_after_user!, + _recipe_after_plot!, _recipe_before_series!, + _recipe_finish! using Requires @@ -226,7 +229,7 @@ end const CURRENT_BACKEND = CurrentBackend(:none) -include("precompile.jl") -_precompile_() +# include("precompile.jl") +# _precompile_() end # module diff --git a/src/plot.jl b/src/plot.jl index 7bd16693..6dfc2a7c 100644 --- a/src/plot.jl +++ b/src/plot.jl @@ -54,7 +54,7 @@ function plot(args...; kw...) # create an empty Plot then process plt = Plot() # plt.user_attr = plotattributes - _plot!(plt, plotattributes, args) + recipe_pipeline!(plt, plotattributes, args, type_aliases=_typeAliases) end # build a new plot from existing plots @@ -155,7 +155,7 @@ function plot!(plt::Plot, args...; kw...) plotattributes = KW(kw) preprocessArgs!(plotattributes) # merge!(plt.user_attr, plotattributes) - _plot!(plt, plotattributes, args) + recipe_pipeline!(plt, plotattributes, args, type_aliases=_typeAliases) end # ------------------------------------------------------------------------------- @@ -163,78 +163,36 @@ end # this is the core plotting function. recursively apply recipes to build # a list of series KW dicts. # note: at entry, we only have those preprocessed args which were passed in... no default values yet -function _plot!(plt::Plot, plotattributes::AKW, args::Tuple) + +## here we implement the recipe interface +function _recipe_init!(plt::Plot, plotattributes::AKW, args::Tuple) plotattributes[:plot_object] = plt if !isempty(args) && !isdefined(Main, :StatsPlots) && first(split(string(typeof(args[1])), ".")) == "DataFrames" @warn("You're trying to plot a DataFrame, but this functionality is provided by StatsPlots") end +end - # -------------------------------- - # "USER RECIPES" - # -------------------------------- - - kw_list = _process_userrecipes(plt, plotattributes, args) - - # @info(1) - # map(DD, kw_list) - - - # -------------------------------- - # "PLOT RECIPES" - # -------------------------------- - - # "plot recipe", which acts like a series type, and is processed before - # the plot layout is created, which allows for setting layouts and other plot-wide attributes. - # we get inputs which have been fully processed by "user recipes" and "type recipes", - # so we can expect standard vectors, surfaces, etc. No defaults have been set yet. - still_to_process = kw_list - kw_list = KW[] - while !isempty(still_to_process) - next_kw = popfirst!(still_to_process) - _process_plotrecipe(plt, next_kw, kw_list, still_to_process) - end - - # @info(2) - # map(DD, kw_list) - +function _recipe_after_plot!(plt::Plot, plotattributes::AKW, kw_list::Vector{KW}) # -------------------------------- # Plot/Subplot/Layout setup # -------------------------------- _plot_setup(plt, plotattributes, kw_list) _subplot_setup(plt, plotattributes, kw_list) +end - # !!! note: At this point, kw_list is fully decomposed into individual series... one KW per series. !!! - # !!! The next step is to recursively apply series recipes until the backend supports that series type !!! +function _recipe_before_series!(plt::Plot, kw, kw_list) + sp::Subplot = kw[:subplot] - # -------------------------------- - # "SERIES RECIPES" - # -------------------------------- + # in series attributes given as vector with one element per series, + # select the value for current series + _slice_series_args!(kw, plt, sp, series_idx(kw_list,kw)) - # @info(3) - # map(DD, kw_list) - - for kw in kw_list - sp::Subplot = kw[:subplot] - - # in series attributes given as vector with one element per series, - # select the value for current series - _slice_series_args!(kw, plt, sp, series_idx(kw_list,kw)) - - - series_attr = Attr(kw, _series_defaults) - # now we have a fully specified series, with colors chosen. we must recursively handle - # series recipes, which dispatch on seriestype. If a backend does not natively support a seriestype, - # we check for a recipe that will convert that series type into one made up of lower-level components. - # For example, a histogram is just a bar plot with binned data, a bar plot is really a filled step plot, - # and a step plot is really just a path. So any backend that supports drawing a path will implicitly - # be able to support step, bar, and histogram plots (and any recipes that use those components). - _process_seriesrecipe(plt, series_attr) - end - - # -------------------------------- + series_attr = Attr(kw, _series_defaults) +end +function _recipe_finish!(plt::Plot, plotattributes::AKW, args::Tuple) current(plt) # do we want to force display? @@ -246,7 +204,6 @@ function _plot!(plt::Plot, plotattributes::AKW, args::Tuple) plt end - # we're getting ready to display/output. prep for layout calcs, then update # the plot object after function prepare_output(plt::Plot)