Skip to content

Forward compatibility: cherry-pick accessors #6387

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Apr 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ Config/testthat/edition: 3
Encoding: UTF-8
LazyData: true
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.3.1
RoxygenNote: 7.3.2
Collate:
'ggproto.R'
'ggplot-global.R'
Expand Down
3 changes: 3 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ S3method(ggplot_add,list)
S3method(ggplot_add,theme)
S3method(ggplot_add,uneval)
S3method(ggplot_build,ggplot)
S3method(ggplot_build,ggplot_built)
S3method(ggplot_gtable,ggplot_built)
S3method(grid.draw,absoluteGrob)
S3method(grid.draw,ggplot)
Expand Down Expand Up @@ -420,7 +421,9 @@ export(geom_violin)
export(geom_vline)
export(get_alt_text)
export(get_element_tree)
export(get_geom_defaults)
export(get_guide_data)
export(get_labs)
export(gg_dep)
export(ggplot)
export(ggplotGrob)
Expand Down
8 changes: 8 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# ggplot2 (development version)

* New `get_labs()` function for retrieving completed plot labels
(@teunbrand, #6008).
* New `get_geom_defaults()` for retrieving resolved default aesthetics.
* A new `ggplot_build()` S3 method for <ggplot_built> classes was added, which
returns input unaltered (@teunbrand, #5800).

# ggplot2 3.5.1

This is a small release focusing on fixing regressions from 3.5.0 and
Expand Down
51 changes: 51 additions & 0 deletions R/geom-defaults.R
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,54 @@ update_stat_defaults <- function(stat, new) {
g$default_aes[names(new)] <- new
invisible()
}

#' Resolve and get geom defaults
#'
#' @param geom Some definition of a geom:
#' * A `function` that creates a layer, e.g. `geom_path()`.
#' * A layer created by such function
#' * A string naming a geom class in snake case without the `geom_`-prefix,
#' e.g. `"contour_filled"`.
#' * A geom class object.
#' @param theme A [`theme`] object. Defaults to the current global theme.
#'
#' @return A list of aesthetics
#' @export
#' @keywords internal
#'
#' @examples
#' # Using a function
#' get_geom_defaults(geom_raster)
#'
#' # Using a layer includes static aesthetics as default
#' get_geom_defaults(geom_tile(fill = "white"))
#'
#' # Using a class name
#' get_geom_defaults("density_2d")
#'
#' # Using a class
#' get_geom_defaults(GeomPoint)
#'
#' # Changed theme
#' get_geom_defaults("point", theme(geom = element_geom(ink = "purple")))
get_geom_defaults <- function(geom, theme = theme_get()) {
theme <- theme %||% list(geom = .default_geom_element)

if (is.function(geom)) {
geom <- geom()
}
if (is.layer(geom)) {
data <- data_frame0(.id = 1L)
data <- geom$compute_geom_2(data = data)
data$.id <- NULL
return(data)
}
if (is.character(geom)) {
geom <- check_subclass(geom, "Geom")
}
if (inherits(geom, "Geom")) {
out <- geom$use_defaults(data = NULL)
return(out)
}
stop_input_type(geom, as_cli("a layer function, string or {.cls Geom} object"))
}
1 change: 1 addition & 0 deletions R/guide-colorbar.R
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ GuideColourbar <- ggproto(
merge = function(self, params, new_guide, new_params) {
new_params$key$.label <- new_params$key$.value <- NULL
params$key <- vec_cbind(params$key, new_params$key)
params$aesthetic <- union(params$aesthetic, new_params$aesthetic)
return(list(guide = self, params = params))
},

Expand Down
1 change: 1 addition & 0 deletions R/guide-legend.R
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ GuideLegend <- ggproto(
cli::cli_warn("Duplicated {.arg override.aes} is ignored.")
}
params$override.aes <- params$override.aes[!duplicated(nms)]
params$aesthetic <- union(params$aesthetic, new_params$aesthetic)

list(guide = self, params = params)
},
Expand Down
4 changes: 1 addition & 3 deletions R/guides-.R
Original file line number Diff line number Diff line change
Expand Up @@ -792,9 +792,7 @@ get_guide_data <- function(plot = last_plot(), aesthetic, panel = 1L) {
check_string(aesthetic, allow_empty = FALSE)
aesthetic <- standardise_aes_names(aesthetic)

if (!inherits(plot, "ggplot_built")) {
plot <- ggplot_build(plot)
}
plot <- ggplot_build(plot)

if (!aesthetic %in% c("x", "y", "x.sec", "y.sec", "theta", "r")) {
# Non position guides: check if aesthetic in colnames of key
Expand Down
33 changes: 33 additions & 0 deletions R/labels.R
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,39 @@ ggtitle <- function(label, subtitle = waiver()) {
labs(title = label, subtitle = subtitle)
}

#' @rdname labs
#' @export
#' @param plot A ggplot object
#' @description
#' `get_labs()` retrieves completed labels from a plot.
get_labs <- function(plot = get_last_plot()) {
plot <- ggplot_build(plot)

labs <- plot$plot$labels

xy_labs <- rename(
c(x = plot$layout$resolve_label(plot$layout$panel_scales_x[[1]], labs),
y = plot$layout$resolve_label(plot$layout$panel_scales_y[[1]], labs)),
c(x.primary = "x", x.secondary = "x.sec",
y.primary = "y", y.secondary = "y.sec")
)

labs <- defaults(xy_labs, labs)

guides <- plot$plot$guides
if (length(guides$aesthetics) == 0) {
return(labs)
}

for (aes in guides$aesthetics) {
param <- guides$get_params(aes)
aes <- param$aesthetic # Can have length > 1 when guide was merged
title <- vec_set_names(rep(list(param$title), length(aes)), aes)
labs <- defaults(title, labs)
}
labs
}

#' Extract alt text from a plot
#'
#' This function returns a text that can be used as alt-text in webpages etc.
Expand Down
6 changes: 6 additions & 0 deletions R/plot-build.R
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ ggplot_build <- function(plot) {
UseMethod('ggplot_build')
}

#' @export
ggplot_build.ggplot_built <- function(plot) {
# This is a no-op
plot
}

#' @export
ggplot_build.ggplot <- function(plot) {
plot <- plot_clone(plot)
Expand Down
43 changes: 43 additions & 0 deletions man/get_geom_defaults.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions man/labs.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion tests/testthat/_snaps/coord-cartesian.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# cartesian coords throws error when limits are badly specified

`xlim` must be a vector of length 2, not a <ScaleContinuousPosition/ScaleContinuous/Scale/ggproto/gg> object.
`xlim` must be a vector of length 2, not a <ScaleContinuousPosition> object.

---

Expand Down
2 changes: 1 addition & 1 deletion tests/testthat/_snaps/coord-flip.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# flip coords throws error when limits are badly specified

`xlim` must be a vector of length 2, not a <ScaleContinuousPosition/ScaleContinuous/Scale/ggproto/gg> object.
`xlim` must be a vector of length 2, not a <ScaleContinuousPosition> object.

---

Expand Down
2 changes: 1 addition & 1 deletion tests/testthat/_snaps/coord-map.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# coord map throws error when limits are badly specified

`xlim` must be a vector of length 2, not a <ScaleContinuousPosition/ScaleContinuous/Scale/ggproto/gg> object.
`xlim` must be a vector of length 2, not a <ScaleContinuousPosition> object.

---

Expand Down
2 changes: 1 addition & 1 deletion tests/testthat/_snaps/coord-transform.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# coord_trans() throws error when limits are badly specified

`xlim` must be a vector of length 2, not a <ScaleContinuousPosition/ScaleContinuous/Scale/ggproto/gg> object.
`xlim` must be a vector of length 2, not a <ScaleContinuousPosition> object.

---

Expand Down
2 changes: 1 addition & 1 deletion tests/testthat/_snaps/coord_sf.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

# coord_sf() throws error when limits are badly specified

`xlim` must be a vector of length 2, not a <ScaleContinuousPosition/ScaleContinuous/Scale/ggproto/gg> object.
`xlim` must be a vector of length 2, not a <ScaleContinuousPosition> object.

---

Expand Down
41 changes: 0 additions & 41 deletions tests/testthat/_snaps/guides/axis-guides-basic.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
41 changes: 0 additions & 41 deletions tests/testthat/_snaps/guides/axis-guides-check-overlap.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading