diff --git a/NEWS.md b/NEWS.md index 5497358548..74b049ace5 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,11 @@ # ggplot2 (development version) +* New parameters for `geom_label()` (@teunbrand and @steveharoz, #5365): + * The `linewidth` aesthetic is now applied and replaces the `label.size` + argument. + * The `linetype` aesthetic is now applied. + * New `border.colour` argument to set the colour of borders. + * New `text.colour` argument to set the colour of text. * New `element_point()` and `element_polygon()` that can be given to `theme(point, polygon)` as an extension point (@teunbrand, #6248). * Turned off fallback for `size` to `linewidth` translation in diff --git a/R/geom-label.R b/R/geom-label.R index 68f4549b6e..ae21a48df3 100644 --- a/R/geom-label.R +++ b/R/geom-label.R @@ -2,19 +2,36 @@ #' @rdname geom_text #' @param label.padding Amount of padding around label. Defaults to 0.25 lines. #' @param label.r Radius of rounded corners. Defaults to 0.15 lines. -#' @param label.size Size of label border, in mm. +#' @param label.size `r lifecycle::badge("deprecated")` Replaced by the +#' `linewidth` aesthetic. Size of label border, in mm. +#' @param border.colour,border.color Colour of label border. When `NULL` +#' (default), the `colour` aesthetic determines the colour of the label border. +#' `border.color` is an alias for `border.colour`. +#' @param text.colour,text.color Colour of the text. When `NULL` (default), the +#' `colour` aesthetic determines the colour of the text. `text.color` is an +#' alias for `text.colour`. geom_label <- function(mapping = NULL, data = NULL, stat = "identity", position = "nudge", ..., parse = FALSE, label.padding = unit(0.25, "lines"), label.r = unit(0.15, "lines"), - label.size = 0.25, + label.size = deprecated(), + border.colour = NULL, + border.color = NULL, + text.colour = NULL, + text.color = NULL, size.unit = "mm", na.rm = FALSE, show.legend = NA, inherit.aes = TRUE) { + extra_args <- list2(...) + if (lifecycle::is_present(label.size)) { + deprecate_warn0("3.5.0", "geom_label(label.size)", "geom_label(linewidth)") + extra_args$linewidth <- extra_args$linewidth %||% label.size + } + layer( data = data, mapping = mapping, @@ -27,10 +44,11 @@ geom_label <- function(mapping = NULL, data = NULL, parse = parse, label.padding = label.padding, label.r = label.r, - label.size = label.size, size.unit = size.unit, + border.colour = border.color %||% border.colour, + text.colour = text.color %||% text.colour, na.rm = na.rm, - ... + !!!extra_args ) ) } @@ -49,14 +67,17 @@ GeomLabel <- ggproto("GeomLabel", Geom, size = from_theme(fontsize), angle = 0, hjust = 0.5, vjust = 0.5, alpha = NA, fontface = 1, - lineheight = 1.2 + lineheight = 1.2, + linewidth = from_theme(borderwidth * 0.5), + linetype = from_theme(bordertype) ), draw_panel = function(self, data, panel_params, coord, parse = FALSE, na.rm = FALSE, label.padding = unit(0.25, "lines"), label.r = unit(0.15, "lines"), - label.size = 0.25, + border.colour = NULL, + text.colour = NULL, size.unit = "mm") { lab <- data$label if (parse) { @@ -71,6 +92,12 @@ GeomLabel <- ggproto("GeomLabel", Geom, } size.unit <- resolve_text_unit(size.unit) + data$text.colour <- text.colour %||% data$colour + data$border.colour <- border.colour %||% data$colour + data$border.colour[data$linewidth == 0] <- NA + data$fill <- fill_alpha(data$fill, data$alpha) + data$size <- data$size * size.unit + grobs <- lapply(seq_len(nrow(data)), function(i) { row <- data[i, , drop = FALSE] @@ -82,16 +109,17 @@ GeomLabel <- ggproto("GeomLabel", Geom, r = label.r, angle = row$angle, text.gp = gg_par( - col = row$colour, - fontsize = row$size * size.unit, + col = row$text.colour, + fontsize = row$size, fontfamily = row$family, fontface = row$fontface, lineheight = row$lineheight ), rect.gp = gg_par( - col = if (isTRUE(all.equal(label.size, 0))) NA else row$colour, - fill = fill_alpha(row$fill, row$alpha), - lwd = label.size + col = row$border.colour, + fill = row$fill, + lwd = row$linewidth, + lty = row$linetype ) ) }) diff --git a/R/geom-sf.R b/R/geom-sf.R index 78c543a50d..5ba2b3d846 100644 --- a/R/geom-sf.R +++ b/R/geom-sf.R @@ -317,12 +317,22 @@ geom_sf_label <- function(mapping = aes(), data = NULL, parse = FALSE, label.padding = unit(0.25, "lines"), label.r = unit(0.15, "lines"), - label.size = 0.25, + label.size = deprecated(), + border.colour = NULL, + border.color = NULL, + text.colour = NULL, + text.color = NULL, na.rm = FALSE, show.legend = NA, inherit.aes = TRUE, fun.geometry = NULL) { + extra_args <- list2(...) + if (lifecycle::is_present(label.size)) { + deprecate_warn0("3.5.0", "geom_label(label.size)", "geom_label(linewidth)") + extra_args$linewidth <- extra_args$linewidth %||% label.size + } + layer_sf( data = data, mapping = mapping, @@ -335,10 +345,11 @@ geom_sf_label <- function(mapping = aes(), data = NULL, parse = parse, label.padding = label.padding, label.r = label.r, - label.size = label.size, na.rm = na.rm, fun.geometry = fun.geometry, - ... + border.colour = border.color %||% border.colour, + text.colour = text.color %||% text.colour, + !!!extra_args ) ) } diff --git a/R/legend-draw.R b/R/legend-draw.R index 533e9e111f..9a1b607a2e 100644 --- a/R/legend-draw.R +++ b/R/legend-draw.R @@ -328,7 +328,6 @@ draw_key_text <- function(data, params, size) { #' @rdname draw_key draw_key_label <- function(data, params, size) { data <- replace_null(unclass(data), label = "a", angle = 0) - params$label.size <- params$label.size %||% 0.25 hjust <- compute_just(data$hjust %||% 0.5) vjust <- compute_just(data$vjust %||% 0.5) just <- rotate_just(data$angle, hjust, vjust) @@ -338,6 +337,7 @@ draw_key_label <- function(data, params, size) { face = data$fontface %||% 1, size = data$size %||% 3.88 ) + lwd <- data$linewidth %||% 0.25 grob <- labelGrob( data$label, x = unit(just$hjust, "npc"), @@ -347,15 +347,16 @@ draw_key_label <- function(data, params, size) { padding = padding, r = params$label.r %||% unit(0.15, "lines"), text.gp = gg_par( - col = data$colour %||% "black", + col = params$text.colour %||% data$colour %||% "black", fontfamily = data$family %||% "", fontface = data$fontface %||% 1, fontsize = (data$size %||% 3.88) * .pt ), rect.gp = gg_par( - col = if (isTRUE(all.equal(params$label.size, 0))) NA else data$colour, + col = if (isTRUE(all.equal(lwd, 0))) NA else params$border.colour %||% data$colour %||% "black", fill = alpha(data$fill %||% "white", data$alpha), - lwd = params$label.size + lwd = lwd, + lty = data$linetype %||% 1L ) ) angle <- deg2rad(data$angle %||% 0) diff --git a/ggplot2.Rproj b/ggplot2.Rproj index 30db3b4433..5215454023 100644 --- a/ggplot2.Rproj +++ b/ggplot2.Rproj @@ -1,4 +1,5 @@ Version: 1.0 +ProjectId: f500cb87-e0be-413f-b396-3eb022932f55 RestoreWorkspace: Default SaveWorkspace: Default diff --git a/man/geom_text.Rd b/man/geom_text.Rd index e92e3fe3d8..ea698af3c1 100644 --- a/man/geom_text.Rd +++ b/man/geom_text.Rd @@ -14,7 +14,11 @@ geom_label( parse = FALSE, label.padding = unit(0.25, "lines"), label.r = unit(0.15, "lines"), - label.size = 0.25, + label.size = deprecated(), + border.colour = NULL, + border.color = NULL, + text.colour = NULL, + text.color = NULL, size.unit = "mm", na.rm = FALSE, show.legend = NA, @@ -117,7 +121,16 @@ displayed as described in \code{?plotmath}.} \item{label.r}{Radius of rounded corners. Defaults to 0.15 lines.} -\item{label.size}{Size of label border, in mm.} +\item{label.size}{\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} Replaced by the +\code{linewidth} aesthetic. Size of label border, in mm.} + +\item{border.colour, border.color}{Colour of label border. When \code{NULL} +(default), the \code{colour} aesthetic determines the colour of the label border. +\code{border.color} is an alias for \code{border.colour}.} + +\item{text.colour, text.color}{Colour of the text. When \code{NULL} (default), the +\code{colour} aesthetic determines the colour of the text. \code{text.color} is an +alias for \code{text.colour}.} \item{size.unit}{How the \code{size} aesthetic is interpreted: as millimetres (\code{"mm"}, default), points (\code{"pt"}), centimetres (\code{"cm"}), inches (\code{"in"}), diff --git a/man/ggsf.Rd b/man/ggsf.Rd index 1ab15f232a..f7790f5abb 100644 --- a/man/ggsf.Rd +++ b/man/ggsf.Rd @@ -49,7 +49,11 @@ geom_sf_label( parse = FALSE, label.padding = unit(0.25, "lines"), label.r = unit(0.15, "lines"), - label.size = 0.25, + label.size = deprecated(), + border.colour = NULL, + border.color = NULL, + text.colour = NULL, + text.color = NULL, na.rm = FALSE, show.legend = NA, inherit.aes = TRUE, @@ -277,7 +281,16 @@ displayed as described in \code{?plotmath}.} \item{label.r}{Radius of rounded corners. Defaults to 0.15 lines.} -\item{label.size}{Size of label border, in mm.} +\item{label.size}{\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} Replaced by the +\code{linewidth} aesthetic. Size of label border, in mm.} + +\item{border.colour, border.color}{Colour of label border. When \code{NULL} +(default), the \code{colour} aesthetic determines the colour of the label border. +\code{border.color} is an alias for \code{border.colour}.} + +\item{text.colour, text.color}{Colour of the text. When \code{NULL} (default), the +\code{colour} aesthetic determines the colour of the text. \code{text.color} is an +alias for \code{text.colour}.} \item{fun.geometry}{A function that takes a \code{sfc} object and returns a \code{sfc_POINT} with the same length as the input. If \code{NULL}, \code{function(x) sf::st_point_on_surface(sf::st_zm(x))} diff --git a/tests/testthat/_snaps/geom-label/geom-label-with-line-parameters.svg b/tests/testthat/_snaps/geom-label/geom-label-with-line-parameters.svg new file mode 100644 index 0000000000..b7c5c9717f --- /dev/null +++ b/tests/testthat/_snaps/geom-label/geom-label-with-line-parameters.svg @@ -0,0 +1,121 @@ + + + + + + + + + + + + + + + + + + + + + + +foo + +bar + +baz + +foo + +bar + +baz + + + +1.00 +1.25 +1.50 +1.75 +2.00 + + + + + + + + + + +1.0 +1.5 +2.0 +2.5 +3.0 +x +y + +labels + + +a + +a + + +a + +a + + +a + +a +bar +baz +foo + +x + + +a + +a + + +a + +a + + +a + +a + + +a + +a + + +a + +a +1.0 +1.5 +2.0 +2.5 +3.0 +geom_label with line parameters + + diff --git a/tests/testthat/test-geom-label.R b/tests/testthat/test-geom-label.R index c80be5e38b..ec94fe7c4b 100644 --- a/tests/testthat/test-geom-label.R +++ b/tests/testthat/test-geom-label.R @@ -22,3 +22,14 @@ test_that("geom_label() rotates labels", { angle_out <- unname(vapply(vps, `[[`, numeric(1), "angle")) expect_equal(angle_in, angle_out) }) + +test_that("geom_label handles line parameters and colours", { + df <- data.frame(x = 1:3, labels = c("foo", "bar", "baz")) + + p <- ggplot(df, aes(x, label = labels, colour = labels, linewidth = x)) + + geom_label(aes(y = 1), border.colour = "black", linetype = 1) + + geom_label(aes(y = 2), text.colour = "black", linetype = 2) + + scale_linewidth(range = c(0.1, 1)) + + expect_doppelganger("geom_label with line parameters", p) +})