diff --git a/NEWS.md b/NEWS.md
index 47e99f6589..0f242a2612 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -31,6 +31,8 @@
cannot be transformed (@teunbrand, #3171).
* `stat_density()` has the new computed variable: `wdensity`, which is
calculated as the density times the sum of weights (@teunbrand, #4176).
+* `theme()` gets new `spacing` and `margins` arguments that all other spacings
+ and (non-text) margins inherit from (@teunbrand, #5622).
# ggplot2 3.5.1
diff --git a/R/facet-grid-.R b/R/facet-grid-.R
index 54c4b8f971..0854b5299b 100644
--- a/R/facet-grid-.R
+++ b/R/facet-grid-.R
@@ -412,10 +412,10 @@ FacetGrid <- ggproto("FacetGrid", Facet,
panel_widths, panel_heights, respect = respect, clip = coord$clip, z = mtx(1))
panel_table$layout$name <- paste0('panel-', rep(seq_len(nrow), ncol), '-', rep(seq_len(ncol), each = nrow))
- panel_table <- gtable_add_col_space(panel_table,
- theme$panel.spacing.x %||% theme$panel.spacing)
- panel_table <- gtable_add_row_space(panel_table,
- theme$panel.spacing.y %||% theme$panel.spacing)
+ spacing_x <- calc_element("panel.spacing.x", theme)
+ spacing_y <- calc_element("panel.spacing.y", theme)
+ panel_table <- gtable_add_col_space(panel_table, spacing_x)
+ panel_table <- gtable_add_row_space(panel_table, spacing_y)
# Add axes
if (params$draw_axes$x) {
@@ -445,7 +445,7 @@ FacetGrid <- ggproto("FacetGrid", Facet,
switch_y <- !is.null(params$switch) && params$switch %in% c("both", "y")
inside_x <- (theme$strip.placement.x %||% theme$strip.placement %||% "inside") == "inside"
inside_y <- (theme$strip.placement.y %||% theme$strip.placement %||% "inside") == "inside"
- strip_padding <- convertUnit(theme$strip.switch.pad.grid, "cm")
+ strip_padding <- convertUnit(calc_element("strip.switch.pad.grid", theme), "cm")
panel_pos_col <- panel_cols(panel_table)
if (switch_x) {
if (!is.null(strips$x$bottom)) {
diff --git a/R/facet-wrap.R b/R/facet-wrap.R
index f69cdd8f95..720e2e8e37 100644
--- a/R/facet-wrap.R
+++ b/R/facet-wrap.R
@@ -325,10 +325,9 @@ FacetWrap <- ggproto("FacetWrap", Facet,
heights = unit(rep(abs(aspect_ratio), nrow), "null"), respect = respect, clip = coord$clip, z = matrix(1, ncol = ncol, nrow = nrow))
panel_table$layout$name <- paste0('panel-', rep(seq_len(ncol), nrow), '-', rep(seq_len(nrow), each = ncol))
- panel_table <- gtable_add_col_space(panel_table,
- theme$panel.spacing.x %||% theme$panel.spacing)
- panel_table <- gtable_add_row_space(panel_table,
- theme$panel.spacing.y %||% theme$panel.spacing)
+
+ panel_table <- gtable_add_col_space(panel_table, calc_element("panel.spacing.x", theme))
+ panel_table <- gtable_add_row_space(panel_table, calc_element("panel.spacing.y", theme))
# Add axes
axis_mat_x_top <- empty_table
@@ -442,7 +441,7 @@ FacetWrap <- ggproto("FacetWrap", Facet,
axis_size <- panel_table$sizes
panel_table <- panel_table$panels
- strip_padding <- convertUnit(theme$strip.switch.pad.wrap, "cm")
+ strip_padding <- convertUnit(calc_element("strip.switch.pad.wrap", theme), "cm")
strip_name <- paste0("strip-", substr(params$strip.position, 1, 1))
strip_mat <- empty_table
strip_mat[panel_pos] <- unlist(unname(strips), recursive = FALSE)[[params$strip.position]]
diff --git a/R/guide-legend.R b/R/guide-legend.R
index c685cdd8c7..157018dc48 100644
--- a/R/guide-legend.R
+++ b/R/guide-legend.R
@@ -313,8 +313,8 @@ GuideLegend <- ggproto(
arg_match0(title_position, .trbl, arg_nm = "legend.title.position")
# Set default spacing
- theme$legend.key.spacing <- theme$legend.key.spacing %||% unit(5.5, "pt")
- gap <- calc_element("legend.key.spacing", theme)
+ theme$legend.key.spacing <- calc_element("legend.key.spacing", theme)
+ gap <- theme$legend.key.spacing
# For backward compatibility, default vertical spacing is no spacing
if (params$direction == "vertical") {
diff --git a/R/guides-.R b/R/guides-.R
index 2280c40def..8a0117dc75 100644
--- a/R/guides-.R
+++ b/R/guides-.R
@@ -608,7 +608,7 @@ Guides <- ggproto(
box_xjust <- box_just[1]
box_yjust <- box_just[2]
- margin <- theme$legend.box.margin %||% margin()
+ margin <- calc_element("legend.box.margin", theme) %||% margin()
# setting that is different for vertical and horizontal guide-boxes.
if (identical(theme$legend.box, "horizontal")) {
diff --git a/R/plot-build.R b/R/plot-build.R
index d53f16ba85..55c419d1e9 100644
--- a/R/plot-build.R
+++ b/R/plot-build.R
@@ -261,10 +261,8 @@ ggplot_gtable.ggplot_built <- function(data) {
plot_table <- table_add_tag(plot_table, plot$labels$tag, theme)
# Margins
- plot_table <- gtable_add_rows(plot_table, theme$plot.margin[1], pos = 0)
- plot_table <- gtable_add_cols(plot_table, theme$plot.margin[2])
- plot_table <- gtable_add_rows(plot_table, theme$plot.margin[3])
- plot_table <- gtable_add_cols(plot_table, theme$plot.margin[4], pos = 0)
+ plot_margin <- calc_element("plot.margin", theme)
+ plot_table <- gtable_add_padding(plot_table, plot_margin)
if (inherits(theme$plot.background, "element")) {
plot_table <- gtable_add_grob(plot_table,
@@ -443,7 +441,7 @@ table_add_legends <- function(table, legends, theme) {
empty <- vapply(legends, is.zero, logical(1))
widths[!empty] <- lapply(legends[!empty], gtable_width)
heights[!empty] <- lapply(legends[!empty], gtable_height)
- spacing <- theme$legend.box.spacing %||% unit(0.2, "cm")
+ spacing <- calc_element("legend.box.spacing", theme) %||% unit(0.2, "cm")
# If legend is missing, set spacing to zero for that legend
zero <- unit(0, "pt")
diff --git a/R/theme-defaults.R b/R/theme-defaults.R
index 05260557e9..2066679533 100644
--- a/R/theme-defaults.R
+++ b/R/theme-defaults.R
@@ -133,6 +133,8 @@ theme_grey <- function(base_size = 11, base_family = "",
lineheight = 0.9, hjust = 0.5, vjust = 0.5, angle = 0,
margin = margin(), debug = FALSE
),
+ spacing = unit(half_line, "pt"),
+ margins = margin(half_line, half_line, half_line, half_line),
axis.line = element_blank(),
axis.line.x = NULL,
@@ -145,7 +147,7 @@ theme_grey <- function(base_size = 11, base_family = "",
axis.text.r = element_text(margin = margin(l = 0.8 * half_line / 2, r = 0.8 * half_line / 2),
hjust = 0.5),
axis.ticks = element_line(colour = "grey20"),
- axis.ticks.length = unit(half_line / 2, "pt"),
+ axis.ticks.length = rel(0.5),
axis.ticks.length.x = NULL,
axis.ticks.length.x.top = NULL,
axis.ticks.length.x.bottom = NULL,
@@ -173,15 +175,15 @@ theme_grey <- function(base_size = 11, base_family = "",
),
legend.background = element_rect(colour = NA),
- legend.spacing = unit(2 * half_line, "pt"),
+ legend.spacing = rel(2),
legend.spacing.x = NULL,
legend.spacing.y = NULL,
- legend.margin = margin(half_line, half_line, half_line, half_line),
+ legend.margin = NULL,
legend.key = NULL,
legend.key.size = unit(1.2, "lines"),
legend.key.height = NULL,
legend.key.width = NULL,
- legend.key.spacing = unit(half_line, "pt"),
+ legend.key.spacing = NULL,
legend.text = element_text(size = rel(0.8)),
legend.title = element_text(hjust = 0),
legend.ticks.length = rel(0.2),
@@ -189,15 +191,15 @@ theme_grey <- function(base_size = 11, base_family = "",
legend.direction = NULL,
legend.justification = "center",
legend.box = NULL,
- legend.box.margin = margin(0, 0, 0, 0, "cm"),
+ legend.box.margin = rel(0),
legend.box.background = element_blank(),
- legend.box.spacing = unit(2 * half_line, "pt"),
+ legend.box.spacing = rel(2),
panel.background = element_rect(fill = "grey92", colour = NA),
panel.border = element_blank(),
panel.grid = element_line(colour = "white"),
panel.grid.minor = element_line(linewidth = rel(0.5)),
- panel.spacing = unit(half_line, "pt"),
+ panel.spacing = NULL,
panel.spacing.x = NULL,
panel.spacing.y = NULL,
panel.ontop = FALSE,
@@ -240,7 +242,7 @@ theme_grey <- function(base_size = 11, base_family = "",
hjust = 0.5, vjust = 0.5
),
plot.tag.position = 'topleft',
- plot.margin = margin(half_line, half_line, half_line, half_line),
+ plot.margin = NULL,
complete = TRUE
)
@@ -466,30 +468,35 @@ theme_void <- function(base_size = 11, base_family = "",
lineheight = 0.9, hjust = 0.5, vjust = 0.5, angle = 0,
margin = margin(), debug = FALSE
),
+ spacing = unit(half_line, "pt"),
+ margins = margin(half_line, half_line, half_line, half_line),
axis.text = element_blank(),
axis.title = element_blank(),
- axis.ticks.length = unit(0, "pt"),
+ axis.ticks.length = rel(0),
axis.ticks.length.x = NULL,
axis.ticks.length.x.top = NULL,
axis.ticks.length.x.bottom = NULL,
axis.ticks.length.y = NULL,
axis.ticks.length.y.left = NULL,
axis.ticks.length.y.right = NULL,
- axis.minor.ticks.length = unit(0, "pt"),
+ axis.minor.ticks.length = NULL,
legend.box = NULL,
legend.key.size = unit(1.2, "lines"),
legend.position = "right",
legend.text = element_text(size = rel(0.8)),
legend.title = element_text(hjust = 0),
- legend.key.spacing = unit(half_line, "pt"),
+ legend.key.spacing = rel(1),
+ legend.margin = rel(0),
+ legend.box.margin = rel(0),
+ legend.box.spacing = unit(0.2, "cm"),
legend.ticks.length = rel(0.2),
strip.clip = "inherit",
strip.text = element_text(size = rel(0.8)),
- strip.switch.pad.grid = unit(half_line / 2, "pt"),
- strip.switch.pad.wrap = unit(half_line / 2, "pt"),
+ strip.switch.pad.grid = rel(0.5),
+ strip.switch.pad.wrap = rel(0.5),
panel.ontop = FALSE,
- panel.spacing = unit(half_line, "pt"),
- plot.margin = unit(c(0, 0, 0, 0), "lines"),
+ panel.spacing = NULL,
+ plot.margin = rel(0),
plot.title = element_text(
size = rel(1.2),
hjust = 0, vjust = 1,
@@ -542,6 +549,8 @@ theme_test <- function(base_size = 11, base_family = "",
lineheight = 0.9, hjust = 0.5, vjust = 0.5, angle = 0,
margin = margin(), debug = FALSE
),
+ spacing = unit(half_line, "pt"),
+ margins = margin(half_line, half_line, half_line, half_line),
axis.line = element_blank(),
axis.line.x = NULL,
@@ -552,7 +561,7 @@ theme_test <- function(base_size = 11, base_family = "",
axis.text.y = element_text(margin = margin(r = 0.8 * half_line / 2), hjust = 1),
axis.text.y.right = element_text(margin = margin(l = 0.8 * half_line / 2), hjust = 0),
axis.ticks = element_line(colour = "grey20"),
- axis.ticks.length = unit(half_line / 2, "pt"),
+ axis.ticks.length = rel(0.5),
axis.ticks.length.x = NULL,
axis.ticks.length.x.top = NULL,
axis.ticks.length.x.bottom = NULL,
@@ -580,7 +589,7 @@ theme_test <- function(base_size = 11, base_family = "",
),
legend.background = element_rect(colour = NA),
- legend.spacing = unit(2 * half_line, "pt"),
+ legend.spacing = rel(2),
legend.spacing.x = NULL,
legend.spacing.y = NULL,
legend.margin = margin(0, 0, 0, 0, "cm"),
@@ -588,7 +597,7 @@ theme_test <- function(base_size = 11, base_family = "",
legend.key.size = unit(1.2, "lines"),
legend.key.height = NULL,
legend.key.width = NULL,
- legend.key.spacing = unit(half_line, "pt"),
+ legend.key.spacing = NULL,
legend.key.spacing.x = NULL,
legend.key.spacing.y = NULL,
legend.text = element_text(size = rel(0.8)),
@@ -600,13 +609,13 @@ theme_test <- function(base_size = 11, base_family = "",
legend.box = NULL,
legend.box.margin = margin(0, 0, 0, 0, "cm"),
legend.box.background = element_blank(),
- legend.box.spacing = unit(2 * half_line, "pt"),
+ legend.box.spacing = rel(2),
panel.background = element_rect(fill = "white", colour = NA),
panel.border = element_rect(fill = NA, colour = "grey20"),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
- panel.spacing = unit(half_line, "pt"),
+ panel.spacing = NULL,
panel.spacing.x = NULL,
panel.spacing.y = NULL,
panel.ontop = FALSE,
@@ -624,8 +633,8 @@ theme_test <- function(base_size = 11, base_family = "",
strip.placement = "inside",
strip.placement.x = NULL,
strip.placement.y = NULL,
- strip.switch.pad.grid = unit(half_line / 2, "pt"),
- strip.switch.pad.wrap = unit(half_line / 2, "pt"),
+ strip.switch.pad.grid = rel(0.5),
+ strip.switch.pad.wrap = rel(0.5),
plot.background = element_rect(colour = "white"),
plot.title = element_text(
@@ -649,7 +658,7 @@ theme_test <- function(base_size = 11, base_family = "",
hjust = 0.5, vjust = 0.5
),
plot.tag.position = 'topleft',
- plot.margin = margin(half_line, half_line, half_line, half_line),
+ plot.margin = NULL,
complete = TRUE
)
diff --git a/R/theme-elements.R b/R/theme-elements.R
index 41b989df7e..23bf79bd6e 100644
--- a/R/theme-elements.R
+++ b/R/theme-elements.R
@@ -419,11 +419,14 @@ el_def <- function(class = NULL, inherit = NULL, description = NULL) {
rect = el_def("element_rect"),
text = el_def("element_text"),
title = el_def("element_text", "text"),
+ spacing = el_def("unit"),
+ margins = el_def("margin"),
+
axis.line = el_def("element_line", "line"),
axis.text = el_def("element_text", "text"),
axis.title = el_def("element_text", "title"),
axis.ticks = el_def("element_line", "line"),
- legend.key.size = el_def("unit"),
+ legend.key.size = el_def(c("unit", "rel"), "spacing"),
panel.grid = el_def("element_line", "line"),
panel.grid.major = el_def("element_line", "panel.grid"),
panel.grid.minor = el_def("element_line", "panel.grid"),
@@ -447,7 +450,7 @@ el_def <- function(class = NULL, inherit = NULL, description = NULL) {
axis.text.theta = el_def("element_text", "axis.text.x"),
axis.text.r = el_def("element_text", "axis.text.y"),
- axis.ticks.length = el_def("unit"),
+ axis.ticks.length = el_def(c("unit", "rel"), "spacing"),
axis.ticks.length.x = el_def(c("unit", "rel"), "axis.ticks.length"),
axis.ticks.length.x.top = el_def(c("unit", "rel"), "axis.ticks.length.x"),
axis.ticks.length.x.bottom = el_def(c("unit", "rel"), "axis.ticks.length.x"),
@@ -503,14 +506,14 @@ el_def <- function(class = NULL, inherit = NULL, description = NULL) {
),
legend.background = el_def("element_rect", "rect"),
- legend.margin = el_def("margin"),
- legend.spacing = el_def("unit"),
+ legend.margin = el_def(c("margin", "rel"), "margins"),
+ legend.spacing = el_def(c("unit", "rel"), "spacing"),
legend.spacing.x = el_def(c("unit", "rel"), "legend.spacing"),
legend.spacing.y = el_def(c("unit", "rel"), "legend.spacing"),
legend.key = el_def("element_rect", "panel.background"),
legend.key.height = el_def(c("unit", "rel"), "legend.key.size"),
legend.key.width = el_def(c("unit", "rel"), "legend.key.size"),
- legend.key.spacing = el_def("unit"),
+ 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.frame = el_def("element_rect", "rect"),
@@ -552,13 +555,13 @@ el_def <- function(class = NULL, inherit = NULL, description = NULL) {
legend.box = el_def("character"),
legend.box.just = el_def("character"),
- legend.box.margin = el_def("margin"),
+ legend.box.margin = el_def(c("margin", "rel"), "margins"),
legend.box.background = el_def("element_rect", "rect"),
- legend.box.spacing = el_def("unit"),
+ legend.box.spacing = el_def(c("unit", "rel"), "spacing"),
panel.background = el_def("element_rect", "rect"),
panel.border = el_def("element_rect", "rect"),
- panel.spacing = el_def("unit"),
+ panel.spacing = el_def(c("unit", "rel"), "spacing"),
panel.spacing.x = el_def(c("unit", "rel"), "panel.spacing"),
panel.spacing.y = el_def(c("unit", "rel"), "panel.spacing"),
panel.grid.major.x = el_def("element_line", "panel.grid.major"),
@@ -580,8 +583,8 @@ el_def <- function(class = NULL, inherit = NULL, description = NULL) {
strip.placement = el_def("character"),
strip.placement.x = el_def("character", "strip.placement"),
strip.placement.y = el_def("character", "strip.placement"),
- strip.switch.pad.grid = el_def("unit"),
- strip.switch.pad.wrap = el_def("unit"),
+ strip.switch.pad.grid = el_def(c("unit", "rel"), "spacing"),
+ strip.switch.pad.wrap = el_def(c("unit", "rel"), "spacing"),
plot.background = el_def("element_rect", "rect"),
plot.title = el_def("element_text", "title"),
@@ -592,7 +595,7 @@ el_def <- function(class = NULL, inherit = NULL, description = NULL) {
plot.tag = el_def("element_text", "title"),
plot.tag.position = el_def(c("character", "numeric", "integer")), # Need to also accept numbers
plot.tag.location = el_def("character"),
- plot.margin = el_def("margin"),
+ plot.margin = el_def(c("margin", "rel"), "margins"),
aspect.ratio = el_def(c("numeric", "integer"))
)
diff --git a/R/theme.R b/R/theme.R
index 3611af323e..f03d2a67ef 100644
--- a/R/theme.R
+++ b/R/theme.R
@@ -25,6 +25,8 @@
#' @param text all text elements ([element_text()])
#' @param title all title elements: plot, axes, legends ([element_text()];
#' inherits from `text`)
+#' @param spacing all spacings ([`unit()`][grid::unit])
+#' @param margins all margins ([margin()])
#' @param aspect.ratio aspect ratio of the panel
#'
#' @param axis.title,axis.title.x,axis.title.y,axis.title.x.top,axis.title.x.bottom,axis.title.y.left,axis.title.y.right
@@ -52,7 +54,7 @@
#' minor tick marks along axes ([element_line()]). `axis.minor.ticks.*.*`
#' inherit from the corresponding major ticks `axis.ticks.*.*`.
#' @param axis.ticks.length,axis.ticks.length.x,axis.ticks.length.x.top,axis.ticks.length.x.bottom,axis.ticks.length.y,axis.ticks.length.y.left,axis.ticks.length.y.right,axis.ticks.length.theta,axis.ticks.length.r
-#' length of tick marks (`unit`)
+#' length of tick marks (`unit`). `axis.ticks.length` inherits from `spacing`.
#' @param axis.minor.ticks.length,axis.minor.ticks.length.x,axis.minor.ticks.length.x.top,axis.minor.ticks.length.x.bottom,axis.minor.ticks.length.y,axis.minor.ticks.length.y.left,axis.minor.ticks.length.y.right,axis.minor.ticks.length.theta,axis.minor.ticks.length.r
#' length of minor tick marks (`unit`), or relative to `axis.ticks.length` when provided with `rel()`.
#' @param axis.line,axis.line.x,axis.line.x.top,axis.line.x.bottom,axis.line.y,axis.line.y.left,axis.line.y.right,axis.line.theta,axis.line.r
@@ -65,22 +67,26 @@
#'
#' @param legend.background background of legend ([element_rect()]; inherits
#' from `rect`)
-#' @param legend.margin the margin around each legend ([margin()])
+#' @param legend.margin the margin around each legend ([margin()]); inherits
+#' from `margins`.
#' @param legend.spacing,legend.spacing.x,legend.spacing.y
#' the spacing between legends (`unit`). `legend.spacing.x` & `legend.spacing.y`
-#' inherit from `legend.spacing` or can be specified separately
+#' inherit from `legend.spacing` or can be specified separately.
+#' `legend.spacing` inherits from `spacing`.
#' @param legend.key background underneath legend keys ([element_rect()];
#' inherits from `rect`)
#' @param legend.key.size,legend.key.height,legend.key.width
#' size of legend keys (`unit`); key background height & width inherit from
-#' `legend.key.size` or can be specified separately
+#' `legend.key.size` or can be specified separately. In turn `legend.key.size`
+#' inherits from `spacing`.
#' @param legend.key.spacing,legend.key.spacing.x,legend.key.spacing.y spacing
#' 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.
+#' specified separately. `legend.key.spacing` inherits from `spacing`.
#' @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 (`unit`)
+#' @param legend.ticks.length length of tick marks in legend
+#' ([`unit()`][grid::unit]); inherits from `legend.key.size`.
#' @param legend.axis.line lines along axes in legends ([element_line()])
#' @param legend.text legend item labels ([element_text()]; inherits from
#' `text`)
@@ -113,11 +119,11 @@
#' bounding box, when there are multiple legends ("top", "bottom", "left", or
#' "right")
#' @param legend.box.margin margins around the full legend area, as specified
-#' using [margin()]
+#' using [margin()]; inherits from `margins`.
#' @param legend.box.background background of legend area ([element_rect()];
#' inherits from `rect`)
#' @param legend.box.spacing The spacing between the plotting area and the
-#' legend box (`unit`)
+#' legend box (`unit`); inherits from `spacing`.
#'
#' @param panel.background background of plotting area, drawn underneath plot
#' ([element_rect()]; inherits from `rect`)
@@ -127,7 +133,7 @@
#' ([element_rect()]; inherits from `rect`)
#' @param panel.spacing,panel.spacing.x,panel.spacing.y spacing between facet
#' panels (`unit`). `panel.spacing.x` & `panel.spacing.y` inherit from `panel.spacing`
-#' or can be specified separately.
+#' or can be specified separately. `panel.spacing` inherits from `spacing`.
#' @param panel.grid,panel.grid.major,panel.grid.minor,panel.grid.major.x,panel.grid.major.y,panel.grid.minor.x,panel.grid.minor.y
#' grid lines ([element_line()]). Specify major grid lines,
#' or minor grid lines separately (using `panel.grid.major` or `panel.grid.minor`)
@@ -166,7 +172,7 @@
#' set the x,y-coordinate relative to the whole plot. The coordinate option
#' is unavailable for `plot.tag.location = "margin"`.
#' @param plot.margin margin around entire plot (`unit` with the sizes of
-#' the top, right, bottom, and left margins)
+#' the top, right, bottom, and left margins); inherits from `margin`.
#'
#' @param strip.background,strip.background.x,strip.background.y
#' background of facet labels ([element_rect()];
@@ -188,10 +194,8 @@
#' that inherit from `strip.text.x` and `strip.text.y`, respectively.
#' As a consequence, some theme stylings need to be applied to
#' the position-dependent elements rather than to the parent elements
-#' @param strip.switch.pad.grid space between strips and axes when strips are
-#' switched (`unit`)
-#' @param strip.switch.pad.wrap space between strips and axes when strips are
-#' switched (`unit`)
+#' @param strip.switch.pad.grid,strip.switch.pad.wrap space between strips and
+#' axes when strips are switched (`unit`); inherits from `spacing`.
#'
#' @param ... additional element specifications not part of base ggplot2. In general,
#' these should also be defined in the `element tree` argument. [Splicing][rlang::splice] a list is also supported.
@@ -311,6 +315,8 @@ theme <- function(...,
rect,
text,
title,
+ spacing,
+ margins,
aspect.ratio,
axis.title,
axis.title.x,
diff --git a/man/geom_density.Rd b/man/geom_density.Rd
index 26f2554e1c..86bf57d6e9 100644
--- a/man/geom_density.Rd
+++ b/man/geom_density.Rd
@@ -188,7 +188,7 @@ These are calculated by the 'stat' part of layers and can be accessed with \link
\itemize{
\item \code{after_stat(density)}\cr density estimate.
\item \code{after_stat(count)}\cr density * number of points - useful for stacked density plots.
-\item \code{after_stat(wdensity)}\cr density * sum of weights. In absence of weights, the same as \code{count}
+\item \code{after_stat(wdensity)}\cr density * sum of weights. In absence of weights, the same as \code{count}.
\item \code{after_stat(scaled)}\cr density estimate, scaled to maximum of 1.
\item \code{after_stat(n)}\cr number of points.
\item \code{after_stat(ndensity)}\cr alias for \code{scaled}, to mirror the syntax of \code{\link[=stat_bin]{stat_bin()}}.
diff --git a/man/theme.Rd b/man/theme.Rd
index 5d51fd8643..13a88a2e2a 100644
--- a/man/theme.Rd
+++ b/man/theme.Rd
@@ -10,6 +10,8 @@ theme(
rect,
text,
title,
+ spacing,
+ margins,
aspect.ratio,
axis.title,
axis.title.x,
@@ -159,6 +161,10 @@ these should also be defined in the \verb{element tree} argument. \link[rlang:sp
\item{title}{all title elements: plot, axes, legends (\code{\link[=element_text]{element_text()}};
inherits from \code{text})}
+\item{spacing}{all spacings (\code{\link[grid:unit]{unit()}})}
+
+\item{margins}{all margins (\code{\link[=margin]{margin()}})}
+
\item{aspect.ratio}{aspect ratio of the panel}
\item{axis.title, axis.title.x, axis.title.y, axis.title.x.top, axis.title.x.bottom, axis.title.y.left, axis.title.y.right}{labels of axes (\code{\link[=element_text]{element_text()}}). Specify all axes' labels (\code{axis.title}),
@@ -185,7 +191,7 @@ from \code{line}}
\item{axis.minor.ticks.x.top, axis.minor.ticks.x.bottom, axis.minor.ticks.y.left, axis.minor.ticks.y.right, axis.minor.ticks.theta, axis.minor.ticks.r, }{minor tick marks along axes (\code{\link[=element_line]{element_line()}}). \verb{axis.minor.ticks.*.*}
inherit from the corresponding major ticks \verb{axis.ticks.*.*}.}
-\item{axis.ticks.length, axis.ticks.length.x, axis.ticks.length.x.top, axis.ticks.length.x.bottom, axis.ticks.length.y, axis.ticks.length.y.left, axis.ticks.length.y.right, axis.ticks.length.theta, axis.ticks.length.r}{length of tick marks (\code{unit})}
+\item{axis.ticks.length, axis.ticks.length.x, axis.ticks.length.x.top, axis.ticks.length.x.bottom, axis.ticks.length.y, axis.ticks.length.y.left, axis.ticks.length.y.right, axis.ticks.length.theta, axis.ticks.length.r}{length of tick marks (\code{unit}). \code{axis.ticks.length} inherits from \code{spacing}.}
\item{axis.minor.ticks.length, axis.minor.ticks.length.x, axis.minor.ticks.length.x.top, axis.minor.ticks.length.x.bottom, axis.minor.ticks.length.y, axis.minor.ticks.length.y.left, axis.minor.ticks.length.y.right, axis.minor.ticks.length.theta, axis.minor.ticks.length.r}{length of minor tick marks (\code{unit}), or relative to \code{axis.ticks.length} when provided with \code{rel()}.}
@@ -199,27 +205,31 @@ from \code{line}}
\item{legend.background}{background of legend (\code{\link[=element_rect]{element_rect()}}; inherits
from \code{rect})}
-\item{legend.margin}{the margin around each legend (\code{\link[=margin]{margin()}})}
+\item{legend.margin}{the margin around each legend (\code{\link[=margin]{margin()}}); inherits
+from \code{margins}.}
\item{legend.spacing, legend.spacing.x, legend.spacing.y}{the spacing between legends (\code{unit}). \code{legend.spacing.x} & \code{legend.spacing.y}
-inherit from \code{legend.spacing} or can be specified separately}
+inherit from \code{legend.spacing} or can be specified separately.
+\code{legend.spacing} inherits from \code{spacing}.}
\item{legend.key}{background underneath legend keys (\code{\link[=element_rect]{element_rect()}};
inherits from \code{rect})}
\item{legend.key.size, legend.key.height, legend.key.width}{size of legend keys (\code{unit}); key background height & width inherit from
-\code{legend.key.size} or can be specified separately}
+\code{legend.key.size} or can be specified separately. In turn \code{legend.key.size}
+inherits from \code{spacing}.}
\item{legend.key.spacing, legend.key.spacing.x, legend.key.spacing.y}{spacing
between legend keys given as a \code{unit}. Spacing in the horizontal (x) and
vertical (y) direction inherit from \code{legend.key.spacing} or can be
-specified separately.}
+specified separately. \code{legend.key.spacing} inherits from \code{spacing}.}
\item{legend.frame}{frame drawn around the bar (\code{\link[=element_rect]{element_rect()}}).}
\item{legend.ticks}{tick marks shown along bars or axes (\code{\link[=element_line]{element_line()}})}
-\item{legend.ticks.length}{length of tick marks in legend (\code{unit})}
+\item{legend.ticks.length}{length of tick marks in legend
+(\code{\link[grid:unit]{unit()}}); inherits from \code{legend.key.size}.}
\item{legend.axis.line}{lines along axes in legends (\code{\link[=element_line]{element_line()}})}
@@ -266,13 +276,13 @@ bounding box, when there are multiple legends ("top", "bottom", "left", or
"right")}
\item{legend.box.margin}{margins around the full legend area, as specified
-using \code{\link[=margin]{margin()}}}
+using \code{\link[=margin]{margin()}}; inherits from \code{margins}.}
\item{legend.box.background}{background of legend area (\code{\link[=element_rect]{element_rect()}};
inherits from \code{rect})}
\item{legend.box.spacing}{The spacing between the plotting area and the
-legend box (\code{unit})}
+legend box (\code{unit}); inherits from \code{spacing}.}
\item{panel.background}{background of plotting area, drawn underneath plot
(\code{\link[=element_rect]{element_rect()}}; inherits from \code{rect})}
@@ -284,7 +294,7 @@ it covers tick marks and grid lines. This should be used with
\item{panel.spacing, panel.spacing.x, panel.spacing.y}{spacing between facet
panels (\code{unit}). \code{panel.spacing.x} & \code{panel.spacing.y} inherit from \code{panel.spacing}
-or can be specified separately.}
+or can be specified separately. \code{panel.spacing} inherits from \code{spacing}.}
\item{panel.grid, panel.grid.major, panel.grid.minor, panel.grid.major.x, panel.grid.major.y, panel.grid.minor.x, panel.grid.minor.y}{grid lines (\code{\link[=element_line]{element_line()}}). Specify major grid lines,
or minor grid lines separately (using \code{panel.grid.major} or \code{panel.grid.minor})
@@ -332,7 +342,7 @@ inside the panel space, anywhere in the plot as a whole, or in the margin
around the panel space.}
\item{plot.margin}{margin around entire plot (\code{unit} with the sizes of
-the top, right, bottom, and left margins)}
+the top, right, bottom, and left margins); inherits from \code{margin}.}
\item{strip.background, strip.background.x, strip.background.y}{background of facet labels (\code{\link[=element_rect]{element_rect()}};
inherits from \code{rect}). Horizontal facet background (\code{strip.background.x})
@@ -356,11 +366,8 @@ that inherit from \code{strip.text.x} and \code{strip.text.y}, respectively.
As a consequence, some theme stylings need to be applied to
the position-dependent elements rather than to the parent elements}
-\item{strip.switch.pad.grid}{space between strips and axes when strips are
-switched (\code{unit})}
-
-\item{strip.switch.pad.wrap}{space between strips and axes when strips are
-switched (\code{unit})}
+\item{strip.switch.pad.grid, strip.switch.pad.wrap}{space between strips and
+axes when strips are switched (\code{unit}); inherits from \code{spacing}.}
\item{complete}{set this to \code{TRUE} if this is a complete theme, such as
the one returned by \code{\link[=theme_grey]{theme_grey()}}. Complete themes behave
diff --git a/tests/testthat/_snaps/theme/large-margins.svg b/tests/testthat/_snaps/theme/large-margins.svg
new file mode 100644
index 0000000000..1e4bfb10db
--- /dev/null
+++ b/tests/testthat/_snaps/theme/large-margins.svg
@@ -0,0 +1,96 @@
+
+
diff --git a/tests/testthat/_snaps/theme/large-spacing.svg b/tests/testthat/_snaps/theme/large-spacing.svg
new file mode 100644
index 0000000000..1680934c61
--- /dev/null
+++ b/tests/testthat/_snaps/theme/large-spacing.svg
@@ -0,0 +1,96 @@
+
+
diff --git a/tests/testthat/test-theme.R b/tests/testthat/test-theme.R
index 895d4cf9fc..1200a56d99 100644
--- a/tests/testthat/test-theme.R
+++ b/tests/testthat/test-theme.R
@@ -649,6 +649,19 @@ test_that("themes look decent at larger base sizes", {
expect_doppelganger("theme_linedraw_large", plot + theme_linedraw(base_size = 33))
})
+test_that("setting 'spacing' and 'margins' affect the whole plot", {
+
+ df <- data_frame(x = 1:3, y = 1:3, z = c("a", "b", "a"), a = 1)
+ plot <- ggplot(df, aes(x, y, colour = z)) +
+ geom_point() +
+ facet_wrap(~ a) +
+ theme_gray()
+
+ expect_doppelganger("large spacing", plot + theme(spacing = unit(1, "cm")))
+ expect_doppelganger("large margins", plot + theme(margins = margin(1, 1, 1, 1, "cm")))
+
+})
+
test_that("axes can be styled independently", {
plot <- ggplot() +
geom_point(aes(1:10, 1:10)) +
diff --git a/vignettes/articles/faq-axes.Rmd b/vignettes/articles/faq-axes.Rmd
index 6a9ed45521..f9868cdf8e 100644
--- a/vignettes/articles/faq-axes.Rmd
+++ b/vignettes/articles/faq-axes.Rmd
@@ -193,7 +193,7 @@ ggplot(sales, aes(x = interaction(quarter, year), y = value, group = 1)) +
geom_line() +
coord_cartesian(ylim = c(9, 32), expand = FALSE, clip = "off") +
theme(
- plot.margin = unit(c(1, 1, 3, 1), "lines"),
+ plot.margin = margin(1, 1, 3, 1, "lines"),
axis.title.x = element_blank(),
axis.text.x = element_blank()
) +
@@ -215,7 +215,7 @@ ggplot(sales, aes(x = interaction(quarter, year), y = value)) +
annotate(geom = "text", x = seq_len(nrow(sales)), y = -1, label = sales$quarter, size = 3) +
annotate(geom = "text", x = c(2.5, 6.5), y = -3, label = unique(sales$year), size = 4) +
theme(
- plot.margin = unit(c(1, 1, 3, 1), "lines"),
+ plot.margin = margin(1, 1, 3, 1, "lines"),
axis.title.x = element_blank(),
axis.text.x = element_blank()
)
diff --git a/vignettes/extending-ggplot2.Rmd b/vignettes/extending-ggplot2.Rmd
index 01383378bc..6ee65ae718 100644
--- a/vignettes/extending-ggplot2.Rmd
+++ b/vignettes/extending-ggplot2.Rmd
@@ -724,11 +724,7 @@ render <- function(panels, layout, x_scales, y_scales, ranges, coord, data,
panel_table <- gtable::gtable_matrix("layout", panels,
widths = unit(c(1, 1), "null"), heights = unit(1, "null"), clip = "on")
# Add spacing according to theme
- panel_spacing <- if (is.null(theme$panel.spacing.x)) {
- theme$panel.spacing
- } else {
- theme$panel.spacing.x
- }
+ panel_spacing <- calc_element("panel.spacing.x", theme)
panel_table <- gtable::gtable_add_col_space(panel_table, panel_spacing)
} else {
panels <- matrix(panels, ncol = 1)
@@ -909,21 +905,13 @@ FacetTrans <- ggproto("FacetTrans", Facet,
panel_table <- gtable::gtable_matrix("layout", panels,
widths = unit(c(1, 1), "null"), heights = unit(1, "null"), clip = "on")
# Add spacing according to theme
- panel_spacing <- if (is.null(theme$panel.spacing.x)) {
- theme$panel.spacing
- } else {
- theme$panel.spacing.x
- }
+ panel_spacing <- calc_element("panel.spacing.x", theme)
panel_table <- gtable::gtable_add_col_space(panel_table, panel_spacing)
} else {
panels <- matrix(panels, ncol = 1)
panel_table <- gtable::gtable_matrix("layout", panels,
widths = unit(1, "null"), heights = unit(c(1, 1), "null"), clip = "on")
- panel_spacing <- if (is.null(theme$panel.spacing.y)) {
- theme$panel.spacing
- } else {
- theme$panel.spacing.y
- }
+ panel_spacing <- calc_element("panel.spacing.y", theme)
panel_table <- gtable::gtable_add_row_space(panel_table, panel_spacing)
}
# Name panel grobs so they can be found later