Nothing
#' Activate dark mode on a 'ggplot2' theme
#'
#' @param .theme ggplot2 theme object
#' @param verbose print messages (default: TRUE)
#' @param force_geom_invert Force the inversion of geom defaults for fill and color/colour (default: FALSE)
#'
#' @return dark version of theme
#'
#' @importFrom ggplot2 theme theme_get is.theme element_rect
#' @export
#'
#' @examples
#' library(ggplot2)
#'
#' p1 <- ggplot(iris, aes(Sepal.Width, Sepal.Length, color = Species)) +
#' geom_point()
#'
#' p1 # theme returned by theme_get()
#' p1 + dark_mode() # activate dark mode on theme returned by theme_get()
#'
#' p2 <- ggplot(iris, aes(Sepal.Width, Sepal.Length)) +
#' geom_point() +
#' facet_wrap(~ Species)
#'
#' p2 + dark_mode(theme_minimal()) # activate dark mode on another theme
#'
#' invert_geom_defaults() # restore geom defaults to their original values
#' @rdname dark_mode
dark_mode <- function(.theme = theme_get(), verbose = TRUE, force_geom_invert = FALSE) {
stopifnot(is.theme(.theme))
# Detect whether the default value of geom point colour is black. If so, invert all geom
# defaults, otherwise leave the geoms alone. Use force_geom_invert to invert the geom When the geom point color is not black but
# the geom defaults force_geom_invert.
geoms <- get_geoms()
geoms_are_dark <- geoms[["GeomPoint"]]$default_aes$colour %in% c("black", "#000000")
if (geoms_are_dark || force_geom_invert) {
invert_geom_defaults(geoms)
if (verbose) {
message("Inverted geom defaults of fill and color/colour.\n",
"To change them back, use invert_geom_defaults().")
}
}
.theme <- invert_theme_elements(.theme)
if (inherits(.theme$plot.background, "element_blank") | is.null(.theme$plot.background)) {
# For a few themes, like theme_minimal() and theme_void() from 'ggplot2', the background
# is blank or NULL and displays as white, so fill the plot background with black.
.theme <- .theme + theme(plot.background = element_rect(fill = "#000000"))
}
.theme
}
#' Invert theme elements
#'
#' @param .theme theme to invert
#'
#' @return Inverted theme
#'
#' @importFrom ggplot2 is.theme
#' @export
#'
#' @rdname invert_theme_elements
invert_theme_elements <- function(.theme) {
stopifnot(is.theme(.theme))
element_names <- names(.theme)
for (element_name in element_names) {
element <- .theme[[element_name]]
if (inherits(element, "element")) { # element_line, element_rect, element_text, element_blank
if (!is.null(element$colour)) {
.theme[[element_name]]$colour <- invert_color(element$colour)
}
if (!is.null(element$fill)) {
.theme[[element_name]]$fill <- invert_color(element$fill)
}
}
}
.theme
}
#' Invert geom defaults for fill and color/colour
#'
#' @param geoms List of geoms as ggproto objects
#'
#' @importFrom ggplot2 is.ggproto
#'
#' @examples
#' library(ggplot2)
#'
#' p <- ggplot(iris, aes(Sepal.Width, Sepal.Length)) +
#' geom_point() +
#' facet_wrap(~ Species)
#'
#' p + dark_theme_gray() # geom defaults changed
#'
#' p + theme_gray() # oh no! geoms are not visible on light background
#'
#' invert_geom_defaults() # geom defaults changed back
#'
#' p + theme_gray() # back to normal
#' @export
#' @rdname invert_geom_defaults
invert_geom_defaults <- function(geoms = get_geoms()) {
for (geom in geoms) {
stopifnot(is.ggproto(geom))
if (!is.null(geom$default_aes$fill)) {
geom$default_aes$fill <- invert_color(geom$default_aes$fill)
}
if (!is.null(geom$default_aes$colour)) {
geom$default_aes$colour <- invert_color(geom$default_aes$colour)
}
}
invisible(geoms)
}
#' Get all geoms from loaded namespaces
#'
#' @importFrom utils apropos
#'
#' @export
#' @rdname get_geoms
#' @keywords internal
get_geoms <- function() {
geom_names <- apropos("^Geom", ignore.case = FALSE)
geoms <- list()
namespaces <- loadedNamespaces()
for (namespace in namespaces) {
geoms_in_namespace <- mget(geom_names, envir = asNamespace(namespace), ifnotfound = list(NULL))
for (geom_name in geom_names) {
if (is.ggproto(geoms_in_namespace[[geom_name]])) {
geoms[[geom_name]] <- geoms_in_namespace[[geom_name]]
}
}
}
geoms
}
#' Invert color(s)
#'
#' Invert a vector of colors, provided the colors are valid hex codes
#' or have valid names (i.e., they belong to base::colors()), and
#' return a vector of inverted colors in hex code.
#'
#' @param color color(s) to invert
#' @param colour alias of color
#'
#' @return Inverted color(s) in hex code
#'
#' @importFrom grDevices col2rgb rgb
#'
#' @examples
#' invert_color("white") # "black"
#' invert_color("gray20") # "gray80"
#' invert_color("grey80") # "grey20"
#' invert_color(c("#000000", "#333333")) # "#FFFFFF","#CCCCCC"
#'
#' @export
#' @rdname invert_color
invert_color <- function(color, colour = color) {
inv_rgb <- abs(255 - col2rgb(colour))
inv_color <- rgb(inv_rgb[1, ], inv_rgb[2, ], inv_rgb[3, ], maxColorValue = 255)
inv_color[is.na(colour)] <- NA
inv_color[is.null(colour)] <- NULL
inv_color
}
#' @export
#' @rdname invert_color
invert_colour <- invert_color
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.