From 1fff986d1033b460f42d0df831813f784cb95e87 Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Tue, 20 May 2025 14:12:47 +0200 Subject: [PATCH 1/9] implement 'patches' as attribute rather than list-item --- NAMESPACE | 2 ++ R/plot_patchwork.R | 17 +++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/NAMESPACE b/NAMESPACE index 00434f0..2dc4a2d 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,5 +1,7 @@ # Generated by roxygen2: do not edit by hand +S3method("$",patchwork) +S3method("$<-",patchwork) S3method("&",gg) S3method("*",gg) S3method("-",ggplot) diff --git a/R/plot_patchwork.R b/R/plot_patchwork.R index 95a6856..10b74a9 100644 --- a/R/plot_patchwork.R +++ b/R/plot_patchwork.R @@ -115,6 +115,23 @@ names.patchwork <- function(x) NULL x } #' @export +`$.patchwork` <- function(x, i) { + if (i == "patches") { + attr(x, "patches") + } else { + NextMethod() + } +} +#' @export +`$<-.patchwork` <- function(x, i, value) { + if (i == "patches") { + attr(x, "patches") <- value + x + } else { + NextMethod() + } +} +#' @export as.list.patchwork <- function(x, ...) { get_patches(x)$plots } From fa9eeda9c5d42f82fcc98ec49dec93a58b430c92 Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Tue, 20 May 2025 14:15:30 +0200 Subject: [PATCH 2/9] make methods of `ggplot_add()` non-methods --- NAMESPACE | 13 +++++-------- R/add_plot.R | 15 +++------------ R/plot_annotation.R | 2 +- R/plot_layout.R | 2 +- 4 files changed, 10 insertions(+), 22 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index 2dc4a2d..d3c4b40 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -27,14 +27,6 @@ S3method(as_patchwork,patchwork) S3method(c,patch_area) S3method(get_dim,ggplot) S3method(get_dim,patchwork) -S3method(ggplot_add,formula) -S3method(ggplot_add,ggplot) -S3method(ggplot_add,grob) -S3method(ggplot_add,gt_tbl) -S3method(ggplot_add,nativeRaster) -S3method(ggplot_add,plot_annotation) -S3method(ggplot_add,plot_layout) -S3method(ggplot_add,raster) S3method(ggplot_build,fixed_dim_ggplot) S3method(ggplot_gtable,fixed_dim_build) S3method(has_tag,ggplot) @@ -75,6 +67,11 @@ S3method(simplify_gt,gtable_patchwork) S3method(simplify_gt,inset_table) S3method(simplify_gt,patchgrob) S3method(str,patchwork) +export(add_ggplot) +export(add_grob) +export(add_gt_tbl) +export(add_plot_annotation) +export(add_plot_layout) export(align_patches) export(align_plots) export(area) diff --git a/R/add_plot.R b/R/add_plot.R index c2eabd5..5198c6a 100644 --- a/R/add_plot.R +++ b/R/add_plot.R @@ -1,27 +1,18 @@ #' @importFrom ggplot2 ggplot_add #' @export -ggplot_add.ggplot <- function(object, plot, object_name) { +add_ggplot <- function(object, plot, object_name) { patches <- get_patches(plot) add_patches(object, patches) } #' @importFrom ggplot2 ggplot_add #' @export -ggplot_add.grob <- function(object, plot, object_name) { +add_grob <- function(object, plot, object_name) { table <- as_patch(object) plot + wrap_elements(full = object) } #' @importFrom ggplot2 ggplot_add #' @export -ggplot_add.formula <- ggplot_add.grob -#' @importFrom ggplot2 ggplot_add -#' @export -ggplot_add.raster <- ggplot_add.grob -#' @importFrom ggplot2 ggplot_add -#' @export -ggplot_add.nativeRaster <- ggplot_add.grob -#' @importFrom ggplot2 ggplot_add -#' @export -ggplot_add.gt_tbl <- function(object, plot, object_name) { +add_gt_tbl <- function(object, plot, object_name) { plot + wrap_table(object) } diff --git a/R/plot_annotation.R b/R/plot_annotation.R index 6f53f2f..426c8fa 100644 --- a/R/plot_annotation.R +++ b/R/plot_annotation.R @@ -98,7 +98,7 @@ default_annotation <- plot_annotation( ) #' @importFrom utils modifyList #' @export -ggplot_add.plot_annotation <- function(object, plot, object_name) { +add_plot_annotation <- function(object, plot, object_name) { plot <- as_patchwork(plot) if (is.null(object$theme)) { plot$patches$annotation$theme <- NULL diff --git a/R/plot_layout.R b/R/plot_layout.R index 26637a4..4d41ad0 100644 --- a/R/plot_layout.R +++ b/R/plot_layout.R @@ -315,7 +315,7 @@ default_layout <- plot_layout( ) #' @importFrom utils modifyList #' @export -ggplot_add.plot_layout <- function(object, plot, object_name) { +add_plot_layout <- function(object, plot, object_name) { plot <- as_patchwork(plot) do_change <- object[!vapply(object, is_waiver, logical(1))] plot$patches$layout[names(do_change)] <- do_change From b2ba69b628c029f2b4905149be6b55b6e04da244 Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Tue, 20 May 2025 14:16:53 +0200 Subject: [PATCH 3/9] conditionally register S7 methods --- R/zzz.R | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/R/zzz.R b/R/zzz.R index f6ea651..f8c35f7 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -56,4 +56,24 @@ on_load({ if ("unitType" %in% getNamespaceExports("grid")) { unitType <- grid::unitType } + if ("class_ggplot" %in% getNamespaceExports("ggplot2")) { + class_ggplot <- get("class_ggplot", envir = asNamespace("ggplot2")) + S7::method(ggplot_add, list(class_ggplot, class_ggplot)) <- add_ggplot + + grobbish <- S7::new_union( + S7::new_S3_class("grob"), + S7::new_S3_class("formula"), + S7::new_S3_class("nativeRaster") + ) + S7::method(ggplot_add, list(grobbish, class_ggplot)) <- add_grob + S7::method(ggplot_add, list(S7::new_S3_class("gt_tbl"), class_ggplot)) <- + add_gt_tbl + S7::method(ggplot_add, list(S7::new_S3_class("plot_layout"), class_ggplot)) <- + add_plot_layout + S7::method(ggplot_add, list(S7::new_S3_class("plot_annotation"), class_ggplot)) <- + add_plot_annotation + } else { + #TODO + } + }) From c980c9361108dba8e85131b0330cc7244ffac236 Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Tue, 20 May 2025 14:17:48 +0200 Subject: [PATCH 4/9] arithmetic for `ggplot2::gg` class --- NAMESPACE | 2 ++ R/arithmetic.R | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/NAMESPACE b/NAMESPACE index d3c4b40..a1cb41f 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -2,7 +2,9 @@ S3method("$",patchwork) S3method("$<-",patchwork) +S3method("&","ggplot2::gg") S3method("&",gg) +S3method("*","ggplot2::gg") S3method("*",gg) S3method("-",ggplot) S3method("/",ggplot) diff --git a/R/arithmetic.R b/R/arithmetic.R index b0434b5..593620d 100644 --- a/R/arithmetic.R +++ b/R/arithmetic.R @@ -141,3 +141,9 @@ NULL } e1 + e2 } + +#' @export +"&.ggplot2::gg" <- `&.gg` + +#' @export +"*.ggplot2::gg" <- `*.gg` From b701d6261e6614511dc07e74887997a75abcf045 Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Tue, 20 May 2025 14:25:58 +0200 Subject: [PATCH 5/9] unmethod build methods --- NAMESPACE | 4 ++-- R/plot_multipage.R | 4 ++-- R/zzz.R | 6 ++++++ 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index a1cb41f..fc6926b 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -29,8 +29,6 @@ S3method(as_patchwork,patchwork) S3method(c,patch_area) S3method(get_dim,ggplot) S3method(get_dim,patchwork) -S3method(ggplot_build,fixed_dim_ggplot) -S3method(ggplot_gtable,fixed_dim_build) S3method(has_tag,ggplot) S3method(has_tag,guide_area) S3method(has_tag,inset_patch) @@ -77,9 +75,11 @@ export(add_plot_layout) export(align_patches) export(align_plots) export(area) +export(build_fixed_dim_ggplot) export(free) export(get_dim) export(get_max_dim) +export(gtable_fixed_dim_build) export(guide_area) export(inset_element) export(patchGrob) diff --git a/R/plot_multipage.R b/R/plot_multipage.R index 3db835d..dc9f730 100644 --- a/R/plot_multipage.R +++ b/R/plot_multipage.R @@ -106,14 +106,14 @@ set_dim.patchwork <- function(plot, dim) { } #' @importFrom ggplot2 ggplot_build #' @export -ggplot_build.fixed_dim_ggplot <- function(plot) { +build_fixed_dim_ggplot <- function(plot) { plot <- NextMethod() class(plot) <- c('fixed_dim_build', class(plot)) plot } #' @importFrom ggplot2 ggplot_gtable #' @export -ggplot_gtable.fixed_dim_build <- function(data) { +gtable_fixed_dim_build <- function(data) { dim <- data$plot$fixed_dimensions table <- NextMethod() table <- add_strips(table) diff --git a/R/zzz.R b/R/zzz.R index f8c35f7..4e45cf4 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -72,6 +72,12 @@ on_load({ add_plot_layout S7::method(ggplot_add, list(S7::new_S3_class("plot_annotation"), class_ggplot)) <- add_plot_annotation + + # Build/gtable methods + S7::method(ggplot_build, S7::new_S3_class("fixed_dim_ggplot")) <- + build_fixed_dim_ggplot + S7::method(ggplot_gtable, S7::new_S3_class("fixed_dim_build")) <- + gtable_fixed_dim_build } else { #TODO } From c828a43ec2833e15472ef3143d470ab10756507d Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Tue, 20 May 2025 14:26:29 +0200 Subject: [PATCH 6/9] organise S7 method declarations --- R/zzz.R | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/R/zzz.R b/R/zzz.R index 4e45cf4..f6193a8 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -57,15 +57,18 @@ on_load({ unitType <- grid::unitType } if ("class_ggplot" %in% getNamespaceExports("ggplot2")) { - class_ggplot <- get("class_ggplot", envir = asNamespace("ggplot2")) - S7::method(ggplot_add, list(class_ggplot, class_ggplot)) <- add_ggplot - grobbish <- S7::new_union( + # Class declarations + class_ggplot <- get("class_ggplot", envir = asNamespace("ggplot2")) + grob_like <- S7::new_union( S7::new_S3_class("grob"), S7::new_S3_class("formula"), S7::new_S3_class("nativeRaster") ) - S7::method(ggplot_add, list(grobbish, class_ggplot)) <- add_grob + + # Add methods + S7::method(ggplot_add, list(class_ggplot, class_ggplot)) <- add_ggplot + S7::method(ggplot_add, list(grob_like, class_ggplot)) <- add_grob S7::method(ggplot_add, list(S7::new_S3_class("gt_tbl"), class_ggplot)) <- add_gt_tbl S7::method(ggplot_add, list(S7::new_S3_class("plot_layout"), class_ggplot)) <- From 51d388df9eb8220eab0f9a8cb3471037e0736944 Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Tue, 20 May 2025 14:33:12 +0200 Subject: [PATCH 7/9] register S3 bits and bobs --- R/zzz.R | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/R/zzz.R b/R/zzz.R index f6193a8..972e3c2 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -82,7 +82,18 @@ on_load({ S7::method(ggplot_gtable, S7::new_S3_class("fixed_dim_build")) <- gtable_fixed_dim_build } else { - #TODO + # Add methods + register_s3_method("ggplot2", "ggplot_add", "ggplot", add_ggplot) + register_s3_method("ggplot2", "ggplot_add", "grob", add_grob) + register_s3_method("ggplot2", "ggplot_add", "formula", add_grob) + register_s3_method("ggplot2", "ggplot_add", "nativeRaster", add_grob) + register_s3_method("ggplot2", "ggplot_add", "gt_tbl", add_gt_tbl) + register_s3_method("ggplot2", "ggplot_add", "plot_layout", add_plot_layout) + register_s3_method("ggplot2", "ggplot_add", "plot_annotation", add_plot_annotation) + + # Build/gtable methods + register_s3_method("ggplot2", "ggplot_build", "fixed_dim_ggplot", build_fixed_dim_ggplot) + register_s3_method("ggplot2", "ggplot_gtable", "fxied_dim_build", gtable_fixed_dim_build) } }) From b805263c8bb5a72537e31be94e866718792ff2ba Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Tue, 20 May 2025 14:42:30 +0200 Subject: [PATCH 8/9] avoid having to document unregistered methods by not exporting them --- NAMESPACE | 7 ------- R/add_plot.R | 3 --- R/plot_annotation.R | 1 - R/plot_layout.R | 1 - R/plot_multipage.R | 2 -- 5 files changed, 14 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index fc6926b..25c9096 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -67,19 +67,12 @@ S3method(simplify_gt,gtable_patchwork) S3method(simplify_gt,inset_table) S3method(simplify_gt,patchgrob) S3method(str,patchwork) -export(add_ggplot) -export(add_grob) -export(add_gt_tbl) -export(add_plot_annotation) -export(add_plot_layout) export(align_patches) export(align_plots) export(area) -export(build_fixed_dim_ggplot) export(free) export(get_dim) export(get_max_dim) -export(gtable_fixed_dim_build) export(guide_area) export(inset_element) export(patchGrob) diff --git a/R/add_plot.R b/R/add_plot.R index 5198c6a..ac03496 100644 --- a/R/add_plot.R +++ b/R/add_plot.R @@ -1,17 +1,14 @@ #' @importFrom ggplot2 ggplot_add -#' @export add_ggplot <- function(object, plot, object_name) { patches <- get_patches(plot) add_patches(object, patches) } #' @importFrom ggplot2 ggplot_add -#' @export add_grob <- function(object, plot, object_name) { table <- as_patch(object) plot + wrap_elements(full = object) } #' @importFrom ggplot2 ggplot_add -#' @export add_gt_tbl <- function(object, plot, object_name) { plot + wrap_table(object) } diff --git a/R/plot_annotation.R b/R/plot_annotation.R index 426c8fa..5ba7fe6 100644 --- a/R/plot_annotation.R +++ b/R/plot_annotation.R @@ -97,7 +97,6 @@ default_annotation <- plot_annotation( theme = NULL ) #' @importFrom utils modifyList -#' @export add_plot_annotation <- function(object, plot, object_name) { plot <- as_patchwork(plot) if (is.null(object$theme)) { diff --git a/R/plot_layout.R b/R/plot_layout.R index 4d41ad0..1e092b0 100644 --- a/R/plot_layout.R +++ b/R/plot_layout.R @@ -314,7 +314,6 @@ default_layout <- plot_layout( axes = 'keep', axis_titles = 'keep' ) #' @importFrom utils modifyList -#' @export add_plot_layout <- function(object, plot, object_name) { plot <- as_patchwork(plot) do_change <- object[!vapply(object, is_waiver, logical(1))] diff --git a/R/plot_multipage.R b/R/plot_multipage.R index dc9f730..cde1bd5 100644 --- a/R/plot_multipage.R +++ b/R/plot_multipage.R @@ -105,14 +105,12 @@ set_dim.patchwork <- function(plot, dim) { cli_abort('Setting dimensions on patchworks are currently unsupported') } #' @importFrom ggplot2 ggplot_build -#' @export build_fixed_dim_ggplot <- function(plot) { plot <- NextMethod() class(plot) <- c('fixed_dim_build', class(plot)) plot } #' @importFrom ggplot2 ggplot_gtable -#' @export gtable_fixed_dim_build <- function(data) { dim <- data$plot$fixed_dimensions table <- NextMethod() From 65ccfd102a03a35df0366144659717e899acaf08 Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Wed, 21 May 2025 18:19:04 +0200 Subject: [PATCH 9/9] Revert "implement 'patches' as attribute rather than list-item" This reverts commit 1fff986d1033b460f42d0df831813f784cb95e87. --- NAMESPACE | 2 -- R/plot_patchwork.R | 17 ----------------- 2 files changed, 19 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index 25c9096..d26a883 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,7 +1,5 @@ # Generated by roxygen2: do not edit by hand -S3method("$",patchwork) -S3method("$<-",patchwork) S3method("&","ggplot2::gg") S3method("&",gg) S3method("*","ggplot2::gg") diff --git a/R/plot_patchwork.R b/R/plot_patchwork.R index 10b74a9..95a6856 100644 --- a/R/plot_patchwork.R +++ b/R/plot_patchwork.R @@ -115,23 +115,6 @@ names.patchwork <- function(x) NULL x } #' @export -`$.patchwork` <- function(x, i) { - if (i == "patches") { - attr(x, "patches") - } else { - NextMethod() - } -} -#' @export -`$<-.patchwork` <- function(x, i, value) { - if (i == "patches") { - attr(x, "patches") <- value - x - } else { - NextMethod() - } -} -#' @export as.list.patchwork <- function(x, ...) { get_patches(x)$plots }