Skip to content

Commit ecf5f40

Browse files
authored
Function for completing themes (#5804)
* exported wrapper for `plot_theme()` * document * add test * add news bullet * Allow for unclassed list themes * fix failing test
1 parent e8cb599 commit ecf5f40

File tree

5 files changed

+91
-0
lines changed

5 files changed

+91
-0
lines changed

NAMESPACE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,7 @@ export(borders)
305305
export(calc_element)
306306
export(check_device)
307307
export(combine_vars)
308+
export(complete_theme)
308309
export(continuous_scale)
309310
export(coord_cartesian)
310311
export(coord_equal)

NEWS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# ggplot2 (development version)
22

3+
* New function `complete_theme()` to replicate how themes are handled during
4+
plot building (#5801).
35
* Special getter and setter functions have been renamed for consistency, allowing
46
for better tab-completion with `get_*`- and `set_*`-prefixes. The old names
57
remain available for backward compatibility (@teunbrand, #5568).

R/theme.R

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,42 @@ validate_theme <- function(theme, tree = get_element_tree(), call = caller_env()
560560
)
561561
}
562562

563+
#' Complete a theme
564+
#'
565+
#' This function takes a theme and completes it so that it can be used
566+
#' downstream to render theme elements. Missing elements are filled in and
567+
#' every item is validated to the specifications of the element tree.
568+
#'
569+
#' @param theme An incomplete [theme][theme()] object to complete, or `NULL`
570+
#' to complete the default theme.
571+
#' @param default A complete [theme][theme()] to fill in missing pieces.
572+
#' Defaults to the global theme settings.
573+
#'
574+
#' @keywords internal
575+
#' @return A [theme][theme()] object.
576+
#' @export
577+
#'
578+
#' @examples
579+
#' my_theme <- theme(line = element_line(colour = "red"))
580+
#' complete_theme(my_theme)
581+
complete_theme <- function(theme = NULL, default = theme_get()) {
582+
if (!is_bare_list(theme)) {
583+
check_object(theme, is.theme, "a {.cls theme} object", allow_null = TRUE)
584+
}
585+
check_object(default, is.theme, "a {.cls theme} object")
586+
theme <- plot_theme(list(theme = theme), default = default)
587+
588+
# Using `theme(!!!theme)` drops `NULL` entries, so strip most attributes and
589+
# construct a new theme
590+
attributes(theme) <- list(names = attr(theme, "names"))
591+
structure(
592+
theme,
593+
class = c("theme", "gg"),
594+
complete = TRUE, # This theme is complete and has no missing elements
595+
validate = FALSE # Settings have already been validated
596+
)
597+
}
598+
563599
# Combine plot defaults with current theme to get complete theme for a plot
564600
plot_theme <- function(x, default = get_theme()) {
565601
theme <- x$theme

man/complete_theme.Rd

Lines changed: 28 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/test-theme.R

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,30 @@ test_that("Minor tick length supports biparental inheritance", {
583583
)
584584
})
585585

586+
test_that("complete_theme completes a theme", {
587+
# `NULL` should match default
588+
gray <- theme_gray()
589+
new <- complete_theme(NULL, default = gray)
590+
expect_equal(new, gray, ignore_attr = "validate")
591+
592+
# Elements are propagated
593+
new <- complete_theme(theme(axis.line = element_line("red")), gray)
594+
expect_equal(new$axis.line$colour, "red")
595+
596+
# Missing elements are filled in if default theme is incomplete
597+
new <- complete_theme(default = theme())
598+
expect_s3_class(new$axis.line, "element_blank")
599+
600+
# Registered elements are included
601+
register_theme_elements(
602+
test = element_text(),
603+
element_tree = list(test = el_def("element_text", "text"))
604+
)
605+
new <- complete_theme(default = gray)
606+
expect_s3_class(new$test, "element_text")
607+
reset_theme_settings()
608+
})
609+
586610
# Visual tests ------------------------------------------------------------
587611

588612
test_that("aspect ratio is honored", {

0 commit comments

Comments
 (0)