Skip to content

Move guide building to ggplot_build() #5483

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 10 commits into from
Oct 30, 2023
3 changes: 3 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# ggplot2 (development version)

* (internal) guide building is now part of `ggplot_build()` instead of
`ggplot_gtable()` to allow guides to observe unmapped data (#5483).

* `geom_violin()` gains a `bounds` argument analogous to `geom_density()`s (@eliocamp, #5493).

* Legend titles no longer take up space if they've been removed by setting
Expand Down
2 changes: 1 addition & 1 deletion R/coord-cartesian-.R
Original file line number Diff line number Diff line change
Expand Up @@ -151,5 +151,5 @@ panel_guides_grob <- function(guides, position, theme) {
return(zeroGrob())
}
pair <- guides$get_position(position)
pair$guide$draw(theme, pair$params)
pair$guide$draw(theme, params = pair$params)
}
20 changes: 15 additions & 5 deletions R/guide-.R
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,12 @@ new_guide <- function(..., available_aes = "any", super) {
#' `params$hash`. This ensures that e.g. `guide_legend()` can display both
#' `shape` and `colour` in the same guide.
#'
#' - `get_layer_key()` Extract information from layers. This can be used to
#' check that the guide's aesthetic is actually in use, or to gather
#' information about how legend keys should be displayed.
#' - `process_layers()` Extract information from layers. This acts mostly
#' as a filter for which layers to include and these are then (typically)
#' forwarded to `get_layer_key()`.
#'
#' - `get_layer_key()` This can be used to gather information about how legend
#' keys should be displayed.
#'
#' - `setup_params()` Set up parameters at the beginning of drawing stages.
#' It can be used to overrule user-supplied parameters or perform checks on
Expand Down Expand Up @@ -253,7 +256,11 @@ Guide <- ggproto(

# Function for extracting information from the layers.
# Mostly applies to `guide_legend()` and `guide_binned()`
get_layer_key = function(params, layers) {
process_layers = function(self, params, layers, data = NULL) {
self$get_layer_key(params, layers, data)
},

get_layer_key = function(params, layers, data = NULL) {
return(params)
},

Expand All @@ -280,11 +287,14 @@ Guide <- ggproto(

# Main drawing function that organises more specialised aspects of guide
# drawing.
draw = function(self, theme, params = self$params) {
draw = function(self, theme, position = NULL, direction = NULL,
params = self$params) {

key <- params$key

# Setup parameters and theme
params$position <- params$position %||% position
params$direction <- params$direction %||% direction
params <- self$setup_params(params)
elems <- self$setup_elements(params, self$elements, theme)
elems <- self$override_elements(params, elems, theme)
Expand Down
2 changes: 1 addition & 1 deletion R/guide-axis.R
Original file line number Diff line number Diff line change
Expand Up @@ -486,7 +486,7 @@ draw_axis <- function(break_positions, break_labels, axis_position, theme,
!!aes := c(0, 1),
!!opp := opp_value
)
guide$draw(theme, params)
guide$draw(theme, params = params)
}

draw_axis_labels <- function(break_positions, break_labels, label_element, is_vertical,
Expand Down
32 changes: 18 additions & 14 deletions R/guide-bins.R
Original file line number Diff line number Diff line change
Expand Up @@ -298,15 +298,15 @@ GuideBins <- ggproto(
params$title <- scale$make_title(
params$title %|W|% scale$name %|W|% title
)
params$key <- key
params
},

setup_params = function(params) {
params$direction <- arg_match0(
params$direction %||% direction,
params$direction,
c("horizontal", "vertical"), arg_nm = "direction"
)
if (params$direction == "vertical") {
key$.value <- 1 - key$.value
}

params$key <- key
valid_label_pos <- switch(
params$direction,
"horizontal" = c("bottom", "top"),
Expand All @@ -320,10 +320,6 @@ GuideBins <- ggproto(
"not {.val {params$label.position}}."
))
}
params
},

setup_params = function(params) {
params <- GuideLegend$setup_params(params)
params$byrow <- FALSE
params$rejust_labels <- FALSE
Expand All @@ -345,10 +341,15 @@ GuideBins <- ggproto(
}
key$.label[c(1, n_labels)[!params$show.limits]] <- ""

just <- if (params$direction == "horizontal") {
elements$text$vjust
} else {
elements$text$hjust
just <- switch(
params$direction,
horizontal = elements$text$vjust,
vertical = elements$text$hjust,
0.5
)

if (params$direction == "vertical") {
key$.value <- 1 - key$.value
}

list(labels = flip_element_grob(
Expand All @@ -363,6 +364,9 @@ GuideBins <- ggproto(
},

build_ticks = function(key, elements, params, position = params$position) {
if (params$direction == "vertical") {
key$.value <- 1 - key$.value
}
key$.value[c(1, nrow(key))[!params$show.limits]] <- NA
Guide$build_ticks(key$.value, elements, params, params$label.position)
},
Expand Down
56 changes: 20 additions & 36 deletions R/guide-colorbar.R
Original file line number Diff line number Diff line change
Expand Up @@ -344,27 +344,10 @@ GuideColourbar <- ggproto(
},

extract_params = function(scale, params,
title = waiver(), direction = "vertical", ...) {
title = waiver(), ...) {
params$title <- scale$make_title(
params$title %|W|% scale$name %|W|% title
)
params$direction <- arg_match0(
params$direction %||% direction,
c("horizontal", "vertical"), arg_nm = "direction"
)
valid_label_pos <- switch(
params$direction,
"horizontal" = c("bottom", "top"),
"vertical" = c("right", "left")
)
params$label.position <- params$label.position %||% valid_label_pos[1]
if (!params$label.position %in% valid_label_pos) {
cli::cli_abort(paste0(
"When {.arg direction} is {.val {params$direction}}, ",
"{.arg label.position} must be one of {.or {.val {valid_label_pos}}}, ",
"not {.val {params$label.position}}."
))
}

limits <- c(params$decor$value[1], params$decor$value[nrow(params$decor)])
params$key$.value <- rescale(
Expand All @@ -381,27 +364,28 @@ GuideColourbar <- ggproto(
return(list(guide = self, params = params))
},

get_layer_key = function(params, layers) {

guide_layers <- lapply(layers, function(layer) {

matched_aes <- matched_aes(layer, params)

# Check if this layer should be included
if (include_layer_in_guide(layer, matched_aes)) {
layer
} else {
NULL
}
})

if (length(compact(guide_layers)) == 0) {
return(NULL)
}
return(params)
get_layer_key = function(params, layers, data = NULL) {
params
},

setup_params = function(params) {
params$direction <- arg_match0(
params$direction,
c("horizontal", "vertical"), arg_nm = "direction"
)
valid_label_pos <- switch(
params$direction,
"horizontal" = c("bottom", "top"),
"vertical" = c("right", "left")
)
params$label.position <- params$label.position %||% valid_label_pos[1]
if (!params$label.position %in% valid_label_pos) {
cli::cli_abort(paste0(
"When {.arg direction} is {.val {params$direction}}, ",
"{.arg label.position} must be one of {.or {.val {valid_label_pos}}}, ",
"not {.val {params$label.position}}."
))
}
params$title.position <- arg_match0(
params$title.position %||%
switch(params$direction, vertical = "top", horizontal = "left"),
Expand Down
38 changes: 22 additions & 16 deletions R/guide-legend.R
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ GuideLegend <- ggproto(

available_aes = "any",

hashables = exprs(title, key$.label, direction, name),
hashables = exprs(title, key$.label, name),

elements = list(
background = "legend.background",
Expand All @@ -260,14 +260,10 @@ GuideLegend <- ggproto(
),

extract_params = function(scale, params,
title = waiver(), direction = NULL, ...) {
title = waiver(), ...) {
params$title <- scale$make_title(
params$title %|W|% scale$name %|W|% title
)
params$direction <- arg_match0(
params$direction %||% direction,
c("horizontal", "vertical"), arg_nm = "direction"
)
if (isTRUE(params$reverse %||% FALSE)) {
params$key <- params$key[nrow(params$key):1, , drop = FALSE]
}
Expand All @@ -291,17 +287,26 @@ GuideLegend <- ggproto(
},

# Arrange common data for vertical and horizontal legends
get_layer_key = function(params, layers) {
process_layers = function(self, params, layers, data = NULL) {

include <- vapply(layers, function(layer) {
aes <- matched_aes(layer, params)
include_layer_in_guide(layer, aes)
}, logical(1))

if (!any(include)) {
return(NULL)
}

self$get_layer_key(params, layers[include], data[include])
},

get_layer_key = function(params, layers, data) {

decor <- lapply(layers, function(layer) {

matched_aes <- matched_aes(layer, params)

# Check if this layer should be included
if (!include_layer_in_guide(layer, matched_aes)) {
return(NULL)
}

if (length(matched_aes) > 0) {
# Filter out aesthetics that can't be applied to the legend
n <- lengths(layer$aes_params, use.names = FALSE)
Expand Down Expand Up @@ -338,14 +343,15 @@ GuideLegend <- ggproto(

# Remove NULL geoms
params$decor <- compact(decor)

if (length(params$decor) == 0) {
return(NULL)
}
return(params)
},

setup_params = function(params) {
params$direction <- arg_match0(
params$direction %||% direction,
c("horizontal", "vertical"), arg_nm = "direction"
)

if ("title.position" %in% names(params)) {
params$title.position <- arg_match0(
params$title.position %||%
Expand Down
2 changes: 1 addition & 1 deletion R/guide-none.R
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ GuideNone <- ggproto(
},

# Draw nothing
draw = function(self, params, theme) {
draw = function(self, ...) {
zeroGrob()
}
)
9 changes: 5 additions & 4 deletions R/guide-old.R
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ GuideOld <- ggproto(
train = function(self, params, scale, aesthetic = NULL,
title = waiver(), direction = NULL) {
params$title <- scale$make_title(params$title %|W|% scale$name %|W|% title)
params$direction <- params$direction %||% direction
params$direction <- params$direction %||% direction %||% "vertical"
params <- guide_train(params, scale, aesthetic)
params
},
Expand All @@ -103,13 +103,14 @@ GuideOld <- ggproto(
guide_transform(params, coord, panel_params)
},

get_layer_key = function(params, layers) {
process_layers = function(self, params, layers, data = NULL) {
guide_geom(params, layers, default_mapping = NULL)
},

draw = function(self, theme, params) {
draw = function(self, theme, position = NULL, direction = NULL, params) {
params$direction <- params$direction %||% direction %||% "placeholder"
params$title.position <- params$title.position %||% switch(
params$direction %||% "placeholder",
params$direction,
vertical = "top", horizontal = "left",
NULL
)
Expand Down
Loading