Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# ggplot2 (development version)

* New `theme(legend.key.justification)` to control the alignment of legend keys
(@teunbrand, #3669).
* `geom_ribbon()` now appropriately warns about, and removes, missing values
(@teunbrand, #6243).
* `guide_*()` can now accept two inside legend theme elements:
Expand Down
54 changes: 39 additions & 15 deletions R/guide-legend.R
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ GuideLegend <- ggproto(
key = "legend.key",
key_height = "legend.key.height",
key_width = "legend.key.width",
key_just = "legend.key.justification",
text = "legend.text",
theme.title = "legend.title",
spacing_x = "legend.key.spacing.x",
Expand Down Expand Up @@ -271,7 +272,6 @@ GuideLegend <- ggproto(
c("horizontal", "vertical"), arg_nm = "direction"
)
params$n_breaks <- n_breaks <- nrow(params$key)
params$n_key_layers <- length(params$decor) + 1 # +1 is key background

# Resolve shape
if (!is.null(params$nrow) && !is.null(params$ncol) &&
Expand Down Expand Up @@ -374,6 +374,9 @@ GuideLegend <- ggproto(
elements$key <-
ggname("legend.key", element_grob(elements$key))
}
if (!is.null(elements$key_just)) {
elements$key_just <- valid.just(elements$key_just)
}

elements$text <-
label_angle_heuristic(elements$text, elements$text_position, params$angle)
Expand All @@ -387,22 +390,39 @@ GuideLegend <- ggproto(

build_decor = function(decor, grobs, elements, params) {

key_size <- c(elements$width_cm, elements$height_cm) * 10

draw <- function(i) {
bg <- elements$key
keys <- lapply(decor, function(g) {
data <- vec_slice(g$data, i)
if (data$.draw %||% TRUE) {
key <- g$draw_key(data, g$params, key_size)
set_key_size(key, data$linewidth, data$size, key_size / 10)
} else {
zeroGrob()
key_size <- c(elements$width_cm, elements$height_cm)
just <- elements$key_just
idx <- seq_len(params$n_breaks)

key_glyphs <- lapply(idx, function(i) {
glyph <- lapply(decor, function(dec) {
data <- vec_slice(dec$data, i)
if (!(data$.draw %||% TRUE)) {
return(zeroGrob())
}
key <- dec$draw_key(data, dec$params, key_size * 10)
set_key_size(key, data$linewidth, data$size, key_size)
})
c(list(bg), keys)
}
unlist(lapply(seq_len(params$n_breaks), draw), FALSE)

width <- vapply(glyph, get_attr, which = "width", default = 0, numeric(1))
width <- max(width, 0, key_size[1], na.rm = TRUE)
height <- vapply(glyph, get_attr, which = "height", default = 0, numeric(1))
height <- max(height, 0, key_size[2], na.rm = TRUE)

vp <- NULL
if (!is.null(just)) {
vp <- viewport(
x = just[1], y = just[2], just = just,
width = unit(width, "cm"), height = unit(height, "cm")
)
}

grob <- gTree(children = inject(gList(elements$key, !!!glyph)), vp = vp)
attr(grob, "width") <- width
attr(grob, "height") <- height
grob
})
key_glyphs
},

build_labels = function(key, elements, params) {
Expand Down Expand Up @@ -791,3 +811,7 @@ deprecated_guide_args <- function(
}
theme
}

get_attr <- function(x, which, exact = TRUE, default = NULL) {
attr(x, which = which, exact = exact) %||% default
}
1 change: 1 addition & 0 deletions R/theme-elements.R
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,7 @@ el_def <- function(class = NULL, inherit = NULL, description = NULL) {
legend.key.spacing = el_def(c("unit", "rel"), "spacing"),
legend.key.spacing.x = el_def(c("unit", "rel"), "legend.key.spacing"),
legend.key.spacing.y = el_def(c("unit", "rel"), "legend.key.spacing"),
legend.key.justification = el_def(c("character", "numeric", "integer")),
legend.frame = el_def("element_rect", "rect"),
legend.axis.line = el_def("element_line", "line"),
legend.ticks = el_def("element_line", "legend.axis.line"),
Expand Down
5 changes: 5 additions & 0 deletions R/theme.R
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@
#' between legend keys given as a `unit`. Spacing in the horizontal (x) and
#' vertical (y) direction inherit from `legend.key.spacing` or can be
#' specified separately. `legend.key.spacing` inherits from `spacing`.
#' @param legend.key.justification Justification for positioning legend keys
#' when more space is available than needed for display. The default, `NULL`,
#' stretches keys into the available space. Can be a location like `"center"`
#' or `"top"`, or a two-element numeric vector.
#' @param legend.frame frame drawn around the bar ([element_rect()]).
#' @param legend.ticks tick marks shown along bars or axes ([element_line()])
#' @param legend.ticks.length length of tick marks in legend
Expand Down Expand Up @@ -393,6 +397,7 @@ theme <- function(...,
legend.key.spacing,
legend.key.spacing.x,
legend.key.spacing.y,
legend.key.justification,
legend.frame,
legend.ticks,
legend.ticks.length,
Expand Down
6 changes: 6 additions & 0 deletions man/theme.Rd

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

136 changes: 136 additions & 0 deletions tests/testthat/_snaps/guide-legend/legend-key-justification.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading