From 214be07369d085f6976d8e046e202be58a4ba645 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Tue, 11 Feb 2020 14:38:39 -0500 Subject: [PATCH 1/4] Add `add_gg` method --- NAMESPACE | 2 ++ R/plot-construction.r | 24 ++++++++++++++++++++++-- man/gg-add.Rd | 17 +++++++++++++++++ man/ggplot_add.Rd | 4 ++-- 4 files changed, 43 insertions(+), 4 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index f5f7149913..04b5fd9271 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -9,6 +9,7 @@ S3method("[<-",uneval) S3method("[[",ggproto) S3method("[[<-",uneval) S3method(.DollarNames,ggproto) +S3method(add_gg,default) S3method(as.list,ggproto) S3method(autolayer,default) S3method(autoplot,default) @@ -246,6 +247,7 @@ export(StatSummaryBin) export(StatSummaryHex) export(StatUnique) export(StatYdensity) +export(add_gg) export(aes) export(aes_) export(aes_all) diff --git a/R/plot-construction.r b/R/plot-construction.r index 7da90300b8..4b0161bac1 100644 --- a/R/plot-construction.r +++ b/R/plot-construction.r @@ -21,6 +21,15 @@ #' You can also supply a list, in which case each element of the list will #' be added in turn. #' +#' @section Package development: To add a custom left-hand-side object (which +#' inherits from `"gg"`) to a `gg` object, add a `add_gg` S3 method for your +#' particular class. +#' +#' For example, let's say you have an object `super_plot` with the class +#' `c("foo", "gg")` and want to `+` it to [theme_bw()]. Add the method +#' `add_gg.foo(e1, e2)` to gain control over how `e1` is added to `e2`. Now, +#' you'll be able to call `x + theme_bw() +#' #' @param e1 An object of class [ggplot()] or a [theme()]. #' @param e2 A plot component, as described below. #' @seealso [theme()] @@ -38,6 +47,17 @@ #' # This can be useful to return from a function. #' base + list(subset(mpg, fl == "p"), geom_smooth()) "+.gg" <- function(e1, e2) { + UseMethod("add_gg") +} + +#' @rdname gg-add +#' @export +add_gg <- function(e1, e2) { + UseMethod("add_gg") +} +#' @rdname gg-add +#' @export +add_gg.default <- function(e1, e2) { if (missing(e2)) { abort("Cannot use `+.gg()` with a single argument. Did you accidentally put + on a new line?") } @@ -68,8 +88,8 @@ add_ggplot <- function(p, object, objectname) { } #' Add custom objects to ggplot #' -#' This generic allows you to add your own methods for adding custom objects to -#' a ggplot with [+.gg]. +#' This generic allows you to add your own methods for adding custom +#' right-hand-side objects to a ggplot with [+.gg]. #' #' @param object An object to add to the plot #' @param plot The ggplot object to add `object` to diff --git a/man/gg-add.Rd b/man/gg-add.Rd index f689cb28bd..5298fde26f 100644 --- a/man/gg-add.Rd +++ b/man/gg-add.Rd @@ -2,11 +2,17 @@ % Please edit documentation in R/plot-construction.r \name{+.gg} \alias{+.gg} +\alias{add_gg} +\alias{add_gg.default} \alias{\%+\%} \title{Add components to a plot} \usage{ \method{+}{gg}(e1, e2) +add_gg(e1, e2) + +\method{add_gg}{default}(e1, e2) + e1 \%+\% e2 } \arguments{ @@ -39,6 +45,17 @@ You can also supply a list, in which case each element of the list will be added in turn. } +\section{Package development}{ + To add a custom left-hand-side object (which +inherits from \code{"gg"}) to a \code{gg} object, add a \code{add_gg} S3 method for your +particular class. + +For example, let's say you have an object \code{super_plot} with the class +\code{c("foo", "gg")} and want to \code{+} it to \code{\link[=theme_bw]{theme_bw()}}. Add the method +\code{add_gg.foo(e1, e2)} to gain control over how \code{e1} is added to \code{e2}. Now, +you'll be able to call `x + theme_bw() +} + \examples{ base <- ggplot(mpg, aes(displ, hwy)) + geom_point() base + geom_smooth() diff --git a/man/ggplot_add.Rd b/man/ggplot_add.Rd index 6921ebf228..e54fdaae31 100644 --- a/man/ggplot_add.Rd +++ b/man/ggplot_add.Rd @@ -17,7 +17,7 @@ ggplot_add(object, plot, object_name) A modified ggplot object } \description{ -This generic allows you to add your own methods for adding custom objects to -a ggplot with \link{+.gg}. +This generic allows you to add your own methods for adding custom +right-hand-side objects to a ggplot with \link{+.gg}. } \keyword{internal} From 8d122bbfac3c571aca1d1ef7cc49c410614e281d Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Wed, 23 Mar 2022 12:38:41 -0400 Subject: [PATCH 2/4] Apply suggestions from code review Co-authored-by: Hadley Wickham --- R/plot-construction.r | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/R/plot-construction.r b/R/plot-construction.r index 4b0161bac1..5a9c620306 100644 --- a/R/plot-construction.r +++ b/R/plot-construction.r @@ -21,9 +21,9 @@ #' You can also supply a list, in which case each element of the list will #' be added in turn. #' -#' @section Package development: To add a custom left-hand-side object (which -#' inherits from `"gg"`) to a `gg` object, add a `add_gg` S3 method for your -#' particular class. +#' @section Package development: +#' To add a custom left-hand-side object (which inherits from `"gg"`) to a `gg` object, +# implement a `add_gg` S3 method for your class. #' #' For example, let's say you have an object `super_plot` with the class #' `c("foo", "gg")` and want to `+` it to [theme_bw()]. Add the method @@ -47,7 +47,7 @@ #' # This can be useful to return from a function. #' base + list(subset(mpg, fl == "p"), geom_smooth()) "+.gg" <- function(e1, e2) { - UseMethod("add_gg") + add_gg(e1, e2) } #' @rdname gg-add From b035668f301deb00bf1799e68babd366e5a2d873 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Wed, 23 Mar 2022 12:52:19 -0400 Subject: [PATCH 3/4] Add news entry --- NEWS.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index 3e81319b84..eeff86a0db 100644 --- a/NEWS.md +++ b/NEWS.md @@ -2,7 +2,12 @@ * `annotation_raster()` adds support for native rasters. For large rasters, native rasters render significantly faster than arrays (@kent37, #3388) - + +* Developers can now add their own `add_ggplot()` S3 method to have control over + how a left-hand-side object is added to a right-hand-side object. `add_ggplot()` + will be called inside `+.gg`, so the left-hand-side still needs + to inherit from `"gg"`. (@schloerke, #3818) + # ggplot2 3.3.0 * Fix a bug in `geom_raster()` that squeezed the image when it went outside From f9c0fcadebf1757ac66d4ad6cc0d3646a8b32208 Mon Sep 17 00:00:00 2001 From: Barret Schloerke Date: Wed, 23 Mar 2022 12:58:40 -0400 Subject: [PATCH 4/4] `add_gg()` -> `add_ggplot()`; `add_ggplot()` -> `add_ggplot_internal()` --- NAMESPACE | 4 ++-- R/plot-construction.r | 27 ++++++++++++++------------- man/gg-add.Rd | 19 ++++++++++--------- 3 files changed, 26 insertions(+), 24 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index 04b5fd9271..f881c26b29 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -9,7 +9,7 @@ S3method("[<-",uneval) S3method("[[",ggproto) S3method("[[<-",uneval) S3method(.DollarNames,ggproto) -S3method(add_gg,default) +S3method(add_ggplot,default) S3method(as.list,ggproto) S3method(autolayer,default) S3method(autoplot,default) @@ -247,7 +247,7 @@ export(StatSummaryBin) export(StatSummaryHex) export(StatUnique) export(StatYdensity) -export(add_gg) +export(add_ggplot) export(aes) export(aes_) export(aes_all) diff --git a/R/plot-construction.r b/R/plot-construction.r index 5a9c620306..f925c6200d 100644 --- a/R/plot-construction.r +++ b/R/plot-construction.r @@ -21,14 +21,15 @@ #' You can also supply a list, in which case each element of the list will #' be added in turn. #' -#' @section Package development: -#' To add a custom left-hand-side object (which inherits from `"gg"`) to a `gg` object, -# implement a `add_gg` S3 method for your class. +#' @section Package development: #' -#' For example, let's say you have an object `super_plot` with the class -#' `c("foo", "gg")` and want to `+` it to [theme_bw()]. Add the method -#' `add_gg.foo(e1, e2)` to gain control over how `e1` is added to `e2`. Now, -#' you'll be able to call `x + theme_bw() +#' To add a custom left-hand-side object (which inherits from `"gg"`) to a +#' `gg` object, add a `add_ggplot` S3 method for your particular class. +#' +#' For example, let's say you have an object `super_plot` with the class +#' `c("foo", "gg")` and want to `+` it to [theme_bw()]. Add the method +#' `add_ggplot.foo(e1, e2)` to gain control over how `e1` is added to `e2`. +#' Now, you'll be able to call `super_plot + theme_bw()`. #' #' @param e1 An object of class [ggplot()] or a [theme()]. #' @param e2 A plot component, as described below. @@ -47,17 +48,17 @@ #' # This can be useful to return from a function. #' base + list(subset(mpg, fl == "p"), geom_smooth()) "+.gg" <- function(e1, e2) { - add_gg(e1, e2) + add_ggplot(e1, e2) } #' @rdname gg-add #' @export -add_gg <- function(e1, e2) { - UseMethod("add_gg") +add_ggplot <- function(e1, e2) { + UseMethod("add_ggplot") } #' @rdname gg-add #' @export -add_gg.default <- function(e1, e2) { +add_ggplot.default <- function(e1, e2) { if (missing(e2)) { abort("Cannot use `+.gg()` with a single argument. Did you accidentally put + on a new line?") } @@ -67,7 +68,7 @@ add_gg.default <- function(e1, e2) { e2name <- deparse(substitute(e2)) if (is.theme(e1)) add_theme(e1, e2, e2name) - else if (is.ggplot(e1)) add_ggplot(e1, e2, e2name) + else if (is.ggplot(e1)) add_ggplot_internal(e1, e2, e2name) else if (is.ggproto(e1)) { abort("Cannot add ggproto objects together. Did you forget to add this object to a ggplot object?") } @@ -78,7 +79,7 @@ add_gg.default <- function(e1, e2) { #' @export "%+%" <- `+.gg` -add_ggplot <- function(p, object, objectname) { +add_ggplot_internal <- function(p, object, objectname) { if (is.null(object)) return(p) p <- plot_clone(p) diff --git a/man/gg-add.Rd b/man/gg-add.Rd index 5298fde26f..a326c6e78e 100644 --- a/man/gg-add.Rd +++ b/man/gg-add.Rd @@ -2,16 +2,16 @@ % Please edit documentation in R/plot-construction.r \name{+.gg} \alias{+.gg} -\alias{add_gg} -\alias{add_gg.default} +\alias{add_ggplot} +\alias{add_ggplot.default} \alias{\%+\%} \title{Add components to a plot} \usage{ \method{+}{gg}(e1, e2) -add_gg(e1, e2) +add_ggplot(e1, e2) -\method{add_gg}{default}(e1, e2) +\method{add_ggplot}{default}(e1, e2) e1 \%+\% e2 } @@ -46,14 +46,15 @@ be added in turn. } \section{Package development}{ - To add a custom left-hand-side object (which -inherits from \code{"gg"}) to a \code{gg} object, add a \code{add_gg} S3 method for your -particular class. + + +To add a custom left-hand-side object (which inherits from \code{"gg"}) to a +\code{gg} object, add a \code{add_ggplot} S3 method for your particular class. For example, let's say you have an object \code{super_plot} with the class \code{c("foo", "gg")} and want to \code{+} it to \code{\link[=theme_bw]{theme_bw()}}. Add the method -\code{add_gg.foo(e1, e2)} to gain control over how \code{e1} is added to \code{e2}. Now, -you'll be able to call `x + theme_bw() +\code{add_ggplot.foo(e1, e2)} to gain control over how \code{e1} is added to \code{e2}. +Now, you'll be able to call \code{super_plot + theme_bw()}. } \examples{