Skip to content

Commit b3d5071

Browse files
authored
New spacing and margins root theme elements (#5631)
* add missing `calc_element()`s * declare new theme elements * rewire inheritance * Use theme for `legend.ticks.length` * fix bug * adapt theme_test() * temp * add visual tests * fix panel spacing in vignette * use `margin()` in vignette * reformat news bullet
1 parent ea6b799 commit b3d5071

16 files changed

+316
-99
lines changed

NEWS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
cannot be transformed (@teunbrand, #3171).
3434
* `stat_density()` has the new computed variable: `wdensity`, which is
3535
calculated as the density times the sum of weights (@teunbrand, #4176).
36+
* `theme()` gets new `spacing` and `margins` arguments that all other spacings
37+
and (non-text) margins inherit from (@teunbrand, #5622).
3638

3739
# ggplot2 3.5.1
3840

R/facet-grid-.R

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -412,10 +412,10 @@ FacetGrid <- ggproto("FacetGrid", Facet,
412412
panel_widths, panel_heights, respect = respect, clip = coord$clip, z = mtx(1))
413413
panel_table$layout$name <- paste0('panel-', rep(seq_len(nrow), ncol), '-', rep(seq_len(ncol), each = nrow))
414414

415-
panel_table <- gtable_add_col_space(panel_table,
416-
theme$panel.spacing.x %||% theme$panel.spacing)
417-
panel_table <- gtable_add_row_space(panel_table,
418-
theme$panel.spacing.y %||% theme$panel.spacing)
415+
spacing_x <- calc_element("panel.spacing.x", theme)
416+
spacing_y <- calc_element("panel.spacing.y", theme)
417+
panel_table <- gtable_add_col_space(panel_table, spacing_x)
418+
panel_table <- gtable_add_row_space(panel_table, spacing_y)
419419

420420
# Add axes
421421
if (params$draw_axes$x) {
@@ -445,7 +445,7 @@ FacetGrid <- ggproto("FacetGrid", Facet,
445445
switch_y <- !is.null(params$switch) && params$switch %in% c("both", "y")
446446
inside_x <- (theme$strip.placement.x %||% theme$strip.placement %||% "inside") == "inside"
447447
inside_y <- (theme$strip.placement.y %||% theme$strip.placement %||% "inside") == "inside"
448-
strip_padding <- convertUnit(theme$strip.switch.pad.grid, "cm")
448+
strip_padding <- convertUnit(calc_element("strip.switch.pad.grid", theme), "cm")
449449
panel_pos_col <- panel_cols(panel_table)
450450
if (switch_x) {
451451
if (!is.null(strips$x$bottom)) {

R/facet-wrap.R

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -325,10 +325,9 @@ FacetWrap <- ggproto("FacetWrap", Facet,
325325
heights = unit(rep(abs(aspect_ratio), nrow), "null"), respect = respect, clip = coord$clip, z = matrix(1, ncol = ncol, nrow = nrow))
326326
panel_table$layout$name <- paste0('panel-', rep(seq_len(ncol), nrow), '-', rep(seq_len(nrow), each = ncol))
327327

328-
panel_table <- gtable_add_col_space(panel_table,
329-
theme$panel.spacing.x %||% theme$panel.spacing)
330-
panel_table <- gtable_add_row_space(panel_table,
331-
theme$panel.spacing.y %||% theme$panel.spacing)
328+
329+
panel_table <- gtable_add_col_space(panel_table, calc_element("panel.spacing.x", theme))
330+
panel_table <- gtable_add_row_space(panel_table, calc_element("panel.spacing.y", theme))
332331

333332
# Add axes
334333
axis_mat_x_top <- empty_table
@@ -442,7 +441,7 @@ FacetWrap <- ggproto("FacetWrap", Facet,
442441
axis_size <- panel_table$sizes
443442
panel_table <- panel_table$panels
444443

445-
strip_padding <- convertUnit(theme$strip.switch.pad.wrap, "cm")
444+
strip_padding <- convertUnit(calc_element("strip.switch.pad.wrap", theme), "cm")
446445
strip_name <- paste0("strip-", substr(params$strip.position, 1, 1))
447446
strip_mat <- empty_table
448447
strip_mat[panel_pos] <- unlist(unname(strips), recursive = FALSE)[[params$strip.position]]

R/guide-legend.R

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -313,8 +313,8 @@ GuideLegend <- ggproto(
313313
arg_match0(title_position, .trbl, arg_nm = "legend.title.position")
314314

315315
# Set default spacing
316-
theme$legend.key.spacing <- theme$legend.key.spacing %||% unit(5.5, "pt")
317-
gap <- calc_element("legend.key.spacing", theme)
316+
theme$legend.key.spacing <- calc_element("legend.key.spacing", theme)
317+
gap <- theme$legend.key.spacing
318318

319319
# For backward compatibility, default vertical spacing is no spacing
320320
if (params$direction == "vertical") {

R/guides-.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -608,7 +608,7 @@ Guides <- ggproto(
608608
box_xjust <- box_just[1]
609609
box_yjust <- box_just[2]
610610

611-
margin <- theme$legend.box.margin %||% margin()
611+
margin <- calc_element("legend.box.margin", theme) %||% margin()
612612

613613
# setting that is different for vertical and horizontal guide-boxes.
614614
if (identical(theme$legend.box, "horizontal")) {

R/plot-build.R

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -261,10 +261,8 @@ ggplot_gtable.ggplot_built <- function(data) {
261261
plot_table <- table_add_tag(plot_table, plot$labels$tag, theme)
262262

263263
# Margins
264-
plot_table <- gtable_add_rows(plot_table, theme$plot.margin[1], pos = 0)
265-
plot_table <- gtable_add_cols(plot_table, theme$plot.margin[2])
266-
plot_table <- gtable_add_rows(plot_table, theme$plot.margin[3])
267-
plot_table <- gtable_add_cols(plot_table, theme$plot.margin[4], pos = 0)
264+
plot_margin <- calc_element("plot.margin", theme)
265+
plot_table <- gtable_add_padding(plot_table, plot_margin)
268266

269267
if (inherits(theme$plot.background, "element")) {
270268
plot_table <- gtable_add_grob(plot_table,
@@ -443,7 +441,7 @@ table_add_legends <- function(table, legends, theme) {
443441
empty <- vapply(legends, is.zero, logical(1))
444442
widths[!empty] <- lapply(legends[!empty], gtable_width)
445443
heights[!empty] <- lapply(legends[!empty], gtable_height)
446-
spacing <- theme$legend.box.spacing %||% unit(0.2, "cm")
444+
spacing <- calc_element("legend.box.spacing", theme) %||% unit(0.2, "cm")
447445

448446
# If legend is missing, set spacing to zero for that legend
449447
zero <- unit(0, "pt")

R/theme-defaults.R

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,8 @@ theme_grey <- function(base_size = 11, base_family = "",
133133
lineheight = 0.9, hjust = 0.5, vjust = 0.5, angle = 0,
134134
margin = margin(), debug = FALSE
135135
),
136+
spacing = unit(half_line, "pt"),
137+
margins = margin(half_line, half_line, half_line, half_line),
136138

137139
axis.line = element_blank(),
138140
axis.line.x = NULL,
@@ -145,7 +147,7 @@ theme_grey <- function(base_size = 11, base_family = "",
145147
axis.text.r = element_text(margin = margin(l = 0.8 * half_line / 2, r = 0.8 * half_line / 2),
146148
hjust = 0.5),
147149
axis.ticks = element_line(colour = "grey20"),
148-
axis.ticks.length = unit(half_line / 2, "pt"),
150+
axis.ticks.length = rel(0.5),
149151
axis.ticks.length.x = NULL,
150152
axis.ticks.length.x.top = NULL,
151153
axis.ticks.length.x.bottom = NULL,
@@ -173,31 +175,31 @@ theme_grey <- function(base_size = 11, base_family = "",
173175
),
174176

175177
legend.background = element_rect(colour = NA),
176-
legend.spacing = unit(2 * half_line, "pt"),
178+
legend.spacing = rel(2),
177179
legend.spacing.x = NULL,
178180
legend.spacing.y = NULL,
179-
legend.margin = margin(half_line, half_line, half_line, half_line),
181+
legend.margin = NULL,
180182
legend.key = NULL,
181183
legend.key.size = unit(1.2, "lines"),
182184
legend.key.height = NULL,
183185
legend.key.width = NULL,
184-
legend.key.spacing = unit(half_line, "pt"),
186+
legend.key.spacing = NULL,
185187
legend.text = element_text(size = rel(0.8)),
186188
legend.title = element_text(hjust = 0),
187189
legend.ticks.length = rel(0.2),
188190
legend.position = "right",
189191
legend.direction = NULL,
190192
legend.justification = "center",
191193
legend.box = NULL,
192-
legend.box.margin = margin(0, 0, 0, 0, "cm"),
194+
legend.box.margin = rel(0),
193195
legend.box.background = element_blank(),
194-
legend.box.spacing = unit(2 * half_line, "pt"),
196+
legend.box.spacing = rel(2),
195197

196198
panel.background = element_rect(fill = "grey92", colour = NA),
197199
panel.border = element_blank(),
198200
panel.grid = element_line(colour = "white"),
199201
panel.grid.minor = element_line(linewidth = rel(0.5)),
200-
panel.spacing = unit(half_line, "pt"),
202+
panel.spacing = NULL,
201203
panel.spacing.x = NULL,
202204
panel.spacing.y = NULL,
203205
panel.ontop = FALSE,
@@ -240,7 +242,7 @@ theme_grey <- function(base_size = 11, base_family = "",
240242
hjust = 0.5, vjust = 0.5
241243
),
242244
plot.tag.position = 'topleft',
243-
plot.margin = margin(half_line, half_line, half_line, half_line),
245+
plot.margin = NULL,
244246

245247
complete = TRUE
246248
)
@@ -466,30 +468,35 @@ theme_void <- function(base_size = 11, base_family = "",
466468
lineheight = 0.9, hjust = 0.5, vjust = 0.5, angle = 0,
467469
margin = margin(), debug = FALSE
468470
),
471+
spacing = unit(half_line, "pt"),
472+
margins = margin(half_line, half_line, half_line, half_line),
469473
axis.text = element_blank(),
470474
axis.title = element_blank(),
471-
axis.ticks.length = unit(0, "pt"),
475+
axis.ticks.length = rel(0),
472476
axis.ticks.length.x = NULL,
473477
axis.ticks.length.x.top = NULL,
474478
axis.ticks.length.x.bottom = NULL,
475479
axis.ticks.length.y = NULL,
476480
axis.ticks.length.y.left = NULL,
477481
axis.ticks.length.y.right = NULL,
478-
axis.minor.ticks.length = unit(0, "pt"),
482+
axis.minor.ticks.length = NULL,
479483
legend.box = NULL,
480484
legend.key.size = unit(1.2, "lines"),
481485
legend.position = "right",
482486
legend.text = element_text(size = rel(0.8)),
483487
legend.title = element_text(hjust = 0),
484-
legend.key.spacing = unit(half_line, "pt"),
488+
legend.key.spacing = rel(1),
489+
legend.margin = rel(0),
490+
legend.box.margin = rel(0),
491+
legend.box.spacing = unit(0.2, "cm"),
485492
legend.ticks.length = rel(0.2),
486493
strip.clip = "inherit",
487494
strip.text = element_text(size = rel(0.8)),
488-
strip.switch.pad.grid = unit(half_line / 2, "pt"),
489-
strip.switch.pad.wrap = unit(half_line / 2, "pt"),
495+
strip.switch.pad.grid = rel(0.5),
496+
strip.switch.pad.wrap = rel(0.5),
490497
panel.ontop = FALSE,
491-
panel.spacing = unit(half_line, "pt"),
492-
plot.margin = unit(c(0, 0, 0, 0), "lines"),
498+
panel.spacing = NULL,
499+
plot.margin = rel(0),
493500
plot.title = element_text(
494501
size = rel(1.2),
495502
hjust = 0, vjust = 1,
@@ -542,6 +549,8 @@ theme_test <- function(base_size = 11, base_family = "",
542549
lineheight = 0.9, hjust = 0.5, vjust = 0.5, angle = 0,
543550
margin = margin(), debug = FALSE
544551
),
552+
spacing = unit(half_line, "pt"),
553+
margins = margin(half_line, half_line, half_line, half_line),
545554

546555
axis.line = element_blank(),
547556
axis.line.x = NULL,
@@ -552,7 +561,7 @@ theme_test <- function(base_size = 11, base_family = "",
552561
axis.text.y = element_text(margin = margin(r = 0.8 * half_line / 2), hjust = 1),
553562
axis.text.y.right = element_text(margin = margin(l = 0.8 * half_line / 2), hjust = 0),
554563
axis.ticks = element_line(colour = "grey20"),
555-
axis.ticks.length = unit(half_line / 2, "pt"),
564+
axis.ticks.length = rel(0.5),
556565
axis.ticks.length.x = NULL,
557566
axis.ticks.length.x.top = NULL,
558567
axis.ticks.length.x.bottom = NULL,
@@ -580,15 +589,15 @@ theme_test <- function(base_size = 11, base_family = "",
580589
),
581590

582591
legend.background = element_rect(colour = NA),
583-
legend.spacing = unit(2 * half_line, "pt"),
592+
legend.spacing = rel(2),
584593
legend.spacing.x = NULL,
585594
legend.spacing.y = NULL,
586595
legend.margin = margin(0, 0, 0, 0, "cm"),
587596
legend.key = NULL,
588597
legend.key.size = unit(1.2, "lines"),
589598
legend.key.height = NULL,
590599
legend.key.width = NULL,
591-
legend.key.spacing = unit(half_line, "pt"),
600+
legend.key.spacing = NULL,
592601
legend.key.spacing.x = NULL,
593602
legend.key.spacing.y = NULL,
594603
legend.text = element_text(size = rel(0.8)),
@@ -600,13 +609,13 @@ theme_test <- function(base_size = 11, base_family = "",
600609
legend.box = NULL,
601610
legend.box.margin = margin(0, 0, 0, 0, "cm"),
602611
legend.box.background = element_blank(),
603-
legend.box.spacing = unit(2 * half_line, "pt"),
612+
legend.box.spacing = rel(2),
604613

605614
panel.background = element_rect(fill = "white", colour = NA),
606615
panel.border = element_rect(fill = NA, colour = "grey20"),
607616
panel.grid.major = element_blank(),
608617
panel.grid.minor = element_blank(),
609-
panel.spacing = unit(half_line, "pt"),
618+
panel.spacing = NULL,
610619
panel.spacing.x = NULL,
611620
panel.spacing.y = NULL,
612621
panel.ontop = FALSE,
@@ -624,8 +633,8 @@ theme_test <- function(base_size = 11, base_family = "",
624633
strip.placement = "inside",
625634
strip.placement.x = NULL,
626635
strip.placement.y = NULL,
627-
strip.switch.pad.grid = unit(half_line / 2, "pt"),
628-
strip.switch.pad.wrap = unit(half_line / 2, "pt"),
636+
strip.switch.pad.grid = rel(0.5),
637+
strip.switch.pad.wrap = rel(0.5),
629638

630639
plot.background = element_rect(colour = "white"),
631640
plot.title = element_text(
@@ -649,7 +658,7 @@ theme_test <- function(base_size = 11, base_family = "",
649658
hjust = 0.5, vjust = 0.5
650659
),
651660
plot.tag.position = 'topleft',
652-
plot.margin = margin(half_line, half_line, half_line, half_line),
661+
plot.margin = NULL,
653662

654663
complete = TRUE
655664
)

R/theme-elements.R

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -419,11 +419,14 @@ el_def <- function(class = NULL, inherit = NULL, description = NULL) {
419419
rect = el_def("element_rect"),
420420
text = el_def("element_text"),
421421
title = el_def("element_text", "text"),
422+
spacing = el_def("unit"),
423+
margins = el_def("margin"),
424+
422425
axis.line = el_def("element_line", "line"),
423426
axis.text = el_def("element_text", "text"),
424427
axis.title = el_def("element_text", "title"),
425428
axis.ticks = el_def("element_line", "line"),
426-
legend.key.size = el_def("unit"),
429+
legend.key.size = el_def(c("unit", "rel"), "spacing"),
427430
panel.grid = el_def("element_line", "line"),
428431
panel.grid.major = el_def("element_line", "panel.grid"),
429432
panel.grid.minor = el_def("element_line", "panel.grid"),
@@ -447,7 +450,7 @@ el_def <- function(class = NULL, inherit = NULL, description = NULL) {
447450
axis.text.theta = el_def("element_text", "axis.text.x"),
448451
axis.text.r = el_def("element_text", "axis.text.y"),
449452

450-
axis.ticks.length = el_def("unit"),
453+
axis.ticks.length = el_def(c("unit", "rel"), "spacing"),
451454
axis.ticks.length.x = el_def(c("unit", "rel"), "axis.ticks.length"),
452455
axis.ticks.length.x.top = el_def(c("unit", "rel"), "axis.ticks.length.x"),
453456
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) {
503506
),
504507

505508
legend.background = el_def("element_rect", "rect"),
506-
legend.margin = el_def("margin"),
507-
legend.spacing = el_def("unit"),
509+
legend.margin = el_def(c("margin", "rel"), "margins"),
510+
legend.spacing = el_def(c("unit", "rel"), "spacing"),
508511
legend.spacing.x = el_def(c("unit", "rel"), "legend.spacing"),
509512
legend.spacing.y = el_def(c("unit", "rel"), "legend.spacing"),
510513
legend.key = el_def("element_rect", "panel.background"),
511514
legend.key.height = el_def(c("unit", "rel"), "legend.key.size"),
512515
legend.key.width = el_def(c("unit", "rel"), "legend.key.size"),
513-
legend.key.spacing = el_def("unit"),
516+
legend.key.spacing = el_def(c("unit", "rel"), "spacing"),
514517
legend.key.spacing.x = el_def(c("unit", "rel"), "legend.key.spacing"),
515518
legend.key.spacing.y = el_def(c("unit", "rel"), "legend.key.spacing"),
516519
legend.frame = el_def("element_rect", "rect"),
@@ -552,13 +555,13 @@ el_def <- function(class = NULL, inherit = NULL, description = NULL) {
552555

553556
legend.box = el_def("character"),
554557
legend.box.just = el_def("character"),
555-
legend.box.margin = el_def("margin"),
558+
legend.box.margin = el_def(c("margin", "rel"), "margins"),
556559
legend.box.background = el_def("element_rect", "rect"),
557-
legend.box.spacing = el_def("unit"),
560+
legend.box.spacing = el_def(c("unit", "rel"), "spacing"),
558561

559562
panel.background = el_def("element_rect", "rect"),
560563
panel.border = el_def("element_rect", "rect"),
561-
panel.spacing = el_def("unit"),
564+
panel.spacing = el_def(c("unit", "rel"), "spacing"),
562565
panel.spacing.x = el_def(c("unit", "rel"), "panel.spacing"),
563566
panel.spacing.y = el_def(c("unit", "rel"), "panel.spacing"),
564567
panel.grid.major.x = el_def("element_line", "panel.grid.major"),
@@ -580,8 +583,8 @@ el_def <- function(class = NULL, inherit = NULL, description = NULL) {
580583
strip.placement = el_def("character"),
581584
strip.placement.x = el_def("character", "strip.placement"),
582585
strip.placement.y = el_def("character", "strip.placement"),
583-
strip.switch.pad.grid = el_def("unit"),
584-
strip.switch.pad.wrap = el_def("unit"),
586+
strip.switch.pad.grid = el_def(c("unit", "rel"), "spacing"),
587+
strip.switch.pad.wrap = el_def(c("unit", "rel"), "spacing"),
585588

586589
plot.background = el_def("element_rect", "rect"),
587590
plot.title = el_def("element_text", "title"),
@@ -592,7 +595,7 @@ el_def <- function(class = NULL, inherit = NULL, description = NULL) {
592595
plot.tag = el_def("element_text", "title"),
593596
plot.tag.position = el_def(c("character", "numeric", "integer")), # Need to also accept numbers
594597
plot.tag.location = el_def("character"),
595-
plot.margin = el_def("margin"),
598+
plot.margin = el_def(c("margin", "rel"), "margins"),
596599

597600
aspect.ratio = el_def(c("numeric", "integer"))
598601
)

0 commit comments

Comments
 (0)