Skip to content

Commit 32a2c27

Browse files
authored
Add inherit.blank argument to element constructors (#1754)
Fixes #1555, #1557, #1565, and #1567 * Add inherit.blank argument to element constructors * Look for inherit.blank when combining * Set inherit.blank = TRUE automatically when theme is complete
1 parent 2eee836 commit 32a2c27

File tree

9 files changed

+99
-32
lines changed

9 files changed

+99
-32
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,7 @@
44
inst/doc
55
.httr-oauth
66
.*.Rnb.cached
7+
8+
man/.Rapp.history
9+
10+
.DS_Store

NEWS.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@
5050
I have also very slightly increased the inner margins of axis titles,
5151
and removed the outer margins.
5252

53+
* Theme element inheritance is now more easy to work with. Modification now
54+
overrides default `element_blank` elements (#1555, #1557, #1565, #1567)
55+
5356
* Themes are more homogeneous visually, and match `theme_grey` better.
5457
(@jiho, #1679)
5558

R/theme-defaults.r

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,9 @@ theme_grey <- function(base_size = 11, base_family = "") {
7676
margin = margin(), debug = FALSE
7777
),
7878

79-
axis.line = element_line(),
80-
axis.line.x = element_blank(),
81-
axis.line.y = element_blank(),
79+
axis.line = element_blank(),
80+
axis.line.x = NULL,
81+
axis.line.y = NULL,
8282
axis.text = element_text(size = rel(0.8), colour = "grey30"),
8383
axis.text.x = element_text(margin = margin(t = 0.8 * half_line / 2), vjust = 1),
8484
axis.text.x.top = element_text(margin = margin(b = 0.8 * half_line / 2), vjust = 0),
@@ -185,7 +185,9 @@ theme_bw <- function(base_size = 11, base_family = "") {
185185
# contour strips to match panel contour
186186
strip.background = element_rect(fill = "grey85", colour = "grey20"),
187187
# match legend key to background
188-
legend.key = element_rect(fill = "white", colour=NA)
188+
legend.key = element_rect(fill = "white", colour=NA),
189+
190+
complete = TRUE
189191
)
190192
}
191193

@@ -209,7 +211,9 @@ theme_linedraw <- function(base_size = 11, base_family = "") {
209211

210212
# strips with black background and white text
211213
strip.background = element_rect(fill = "black"),
212-
strip.text = element_text(colour = "white", size = rel(0.8))
214+
strip.text = element_text(colour = "white", size = rel(0.8)),
215+
216+
complete = TRUE
213217
)
214218
}
215219

@@ -235,7 +239,9 @@ theme_light <- function(base_size = 11, base_family = "") {
235239

236240
# dark strips with light text (inverse contrast compared to theme_grey)
237241
strip.background = element_rect(fill = "grey70", colour = NA),
238-
strip.text = element_text(colour = "white", size = rel(0.8))
242+
strip.text = element_text(colour = "white", size = rel(0.8)),
243+
244+
complete = TRUE
239245
)
240246

241247
}
@@ -261,7 +267,9 @@ theme_dark <- function(base_size = 11, base_family = "") {
261267

262268
# dark strips with light text (inverse contrast compared to theme_grey)
263269
strip.background = element_rect(fill = "grey15", colour = NA),
264-
strip.text = element_text(colour = "grey90", size = rel(0.8))
270+
strip.text = element_text(colour = "grey90", size = rel(0.8)),
271+
272+
complete = TRUE
265273
)
266274
}
267275

@@ -271,14 +279,15 @@ theme_minimal <- function(base_size = 11, base_family = "") {
271279
# Starts with theme_bw and remove most parts
272280
theme_bw(base_size = base_size, base_family = base_family) %+replace%
273281
theme(
274-
axis.ticks.x = element_blank(),
275-
axis.ticks.y = element_blank(),
282+
axis.ticks = element_blank(),
276283
legend.background = element_blank(),
277284
legend.key = element_blank(),
278285
panel.background = element_blank(),
279286
panel.border = element_blank(),
280287
strip.background = element_blank(),
281-
plot.background = element_blank()
288+
plot.background = element_blank(),
289+
290+
complete = TRUE
282291
)
283292
}
284293

@@ -293,15 +302,16 @@ theme_classic <- function(base_size = 11, base_family = ""){
293302
panel.grid.minor = element_blank(),
294303

295304
# show axes
296-
axis.line.x = element_line(colour = "black", size = 0.5),
297-
axis.line.y = element_line(colour = "black", size = 0.5),
305+
axis.line = element_line(colour = "black", size = 0.5),
298306

299307
# match legend key to panel.background
300308
legend.key = element_blank(),
301309

302310
# simple, black and white strips
303-
strip.background = element_rect(fill = "white", colour = "black", size = 1)
311+
strip.background = element_rect(fill = "white", colour = "black", size = 1),
304312
# NB: size is 1 but clipped, it looks like the 0.5 of the axes
313+
314+
complete = TRUE
305315
)
306316
}
307317

@@ -319,10 +329,8 @@ theme_void <- function(base_size = 11, base_family = "") {
319329
lineheight = 0.9, hjust = 0.5, vjust = 0.5, angle = 0,
320330
margin = margin(), debug = FALSE
321331
),
322-
axis.text.x = element_blank(),
323-
axis.text.y = element_blank(),
324-
axis.title.x = element_blank(),
325-
axis.title.y = element_blank(),
332+
axis.text = element_blank(),
333+
axis.title = element_blank(),
326334
legend.text = element_text(size = rel(0.8)),
327335
legend.title = element_text(hjust = 0),
328336
strip.text = element_text(size = rel(0.8)),

R/theme-elements.r

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@
1313
#' @param fill Fill colour.
1414
#' @param colour,color Line/border colour. Color is an alias for colour.
1515
#' @param size Line/border size in mm; text size in pts.
16+
#' @param inherit.blank Should this element inherit the existence of an
17+
#' element_blank among its parents? If \code{TRUE} the existence of a blank
18+
#' element among its parents will cause this element to be blank as well. If
19+
#' \code{FALSE} any blank parent element will be ignored when calculating final
20+
#' element state.
1621
#' @name element
1722
#' @return An S3 object of class \code{element}.
1823
#' @examples
@@ -49,11 +54,12 @@ element_blank <- function() {
4954
#' @export
5055
#' @rdname element
5156
element_rect <- function(fill = NULL, colour = NULL, size = NULL,
52-
linetype = NULL, color = NULL) {
57+
linetype = NULL, color = NULL, inherit.blank = FALSE) {
5358

5459
if (!is.null(color)) colour <- color
5560
structure(
56-
list(fill = fill, colour = colour, size = size, linetype = linetype),
61+
list(fill = fill, colour = colour, size = size, linetype = linetype,
62+
inherit.blank = inherit.blank),
5763
class = c("element_rect", "element")
5864
)
5965
}
@@ -67,13 +73,13 @@ element_rect <- function(fill = NULL, colour = NULL, size = NULL,
6773
#' @param lineend Line end Line end style (round, butt, square)
6874
#' @param arrow Arrow specification, as created by \code{\link[grid]{arrow}}
6975
element_line <- function(colour = NULL, size = NULL, linetype = NULL,
70-
lineend = NULL, color = NULL, arrow = NULL) {
76+
lineend = NULL, color = NULL, arrow = NULL, inherit.blank = FALSE) {
7177

7278
if (!is.null(color)) colour <- color
7379
if (is.null(arrow)) arrow <- FALSE
7480
structure(
7581
list(colour = colour, size = size, linetype = linetype, lineend = lineend,
76-
arrow = arrow),
82+
arrow = arrow, inherit.blank = inherit.blank),
7783
class = c("element_line", "element")
7884
)
7985
}
@@ -95,13 +101,13 @@ element_line <- function(colour = NULL, size = NULL, linetype = NULL,
95101
#' @rdname element
96102
element_text <- function(family = NULL, face = NULL, colour = NULL,
97103
size = NULL, hjust = NULL, vjust = NULL, angle = NULL, lineheight = NULL,
98-
color = NULL, margin = NULL, debug = NULL) {
104+
color = NULL, margin = NULL, debug = NULL, inherit.blank = FALSE) {
99105

100106
if (!is.null(color)) colour <- color
101107
structure(
102108
list(family = family, face = face, colour = colour, size = size,
103109
hjust = hjust, vjust = vjust, angle = angle, lineheight = lineheight,
104-
margin = margin, debug = debug),
110+
margin = margin, debug = debug, inherit.blank = inherit.blank),
105111
class = c("element_text", "element")
106112
)
107113
}

R/theme.r

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,9 @@ print.theme <- function(x, ...) utils::str(x)
239239
#' existing theme.
240240
#' @param complete set this to TRUE if this is a complete theme, such as
241241
#' the one returned \code{by theme_grey()}. Complete themes behave
242-
#' differently when added to a ggplot object.
242+
#' differently when added to a ggplot object. Also, when setting
243+
#' \code{complete = TRUE} all elements will be set to inherit from blank
244+
#' elements.
243245
#' @param validate TRUE to run validate_element, FALSE to bypass checks.
244246
#'
245247
#' @seealso \code{\link{+.gg}}
@@ -423,6 +425,15 @@ theme <- function(..., complete = FALSE, validate = TRUE) {
423425
mapply(validate_element, elements, names(elements))
424426
}
425427

428+
# If complete theme set all non-blank elements to inherit from blanks
429+
if (complete) {
430+
elements <- lapply(elements, function(el) {
431+
if (inherits(el, "element") && !inherits(el, "element_blank")) {
432+
el$inherit.blank <- TRUE
433+
}
434+
el
435+
})
436+
}
426437
structure(elements, class = c("theme", "gg"),
427438
complete = complete, validate = validate)
428439
}
@@ -641,10 +652,15 @@ calc_element <- function(element, theme, verbose = FALSE) {
641652
combine_elements <- function(e1, e2) {
642653

643654
# If e2 is NULL, nothing to inherit
644-
if (is.null(e2)) return(e1)
645-
646-
# If e1 is NULL, or if e2 is element_blank, inherit everything from e2
647-
if (is.null(e1) || inherits(e2, "element_blank")) return(e2)
655+
if (is.null(e2) || inherits(e1, "element_blank")) return(e1)
656+
# If e1 is NULL inherit everything from e2
657+
if (is.null(e1)) return(e2)
658+
# If e2 is element_blank, and e1 inherits blank inherit everything from e2,
659+
# otherwise ignore e2
660+
if (inherits(e2, "element_blank")) {
661+
if (e1$inherit.blank) return(e2)
662+
else return(e1)
663+
}
648664

649665
# If e1 has any NULL properties, inherit them from e2
650666
n <- vapply(e1[names(e2)], is.null, logical(1))

man/.Rapp.history

Whitespace-only changes.

man/element.Rd

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

man/theme.Rd

Lines changed: 3 additions & 1 deletion
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: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ test_that("Adding theme object to ggplot object with + operator", {
5151
expect_true(p$theme$text$colour == 'red')
5252
tt <- theme_grey()$text
5353
tt$colour <- 'red'
54+
expect_true(tt$inherit.blank)
55+
tt$inherit.blank <- FALSE
5456
expect_identical(p$theme$text, tt)
5557

5658
})
@@ -188,3 +190,23 @@ test_that("theme(validate=FALSE) means do not validate_element", {
188190
red.before <- p + red.text + theme(animint.width = 500, validate = FALSE)
189191
expect_equal(red.before$theme$animint.width, 500)
190192
})
193+
194+
test_that("All elements in complete themes have inherit.blank=TRUE", {
195+
inherit_blanks <- function(theme) {
196+
all(vapply(theme, function(el) {
197+
if (inherits(el, "element") && !inherits(el, "element_blank")) {
198+
el$inherit.blank
199+
} else {
200+
TRUE
201+
}
202+
}, logical(1)))
203+
}
204+
expect_true(inherit_blanks(theme_grey()))
205+
expect_true(inherit_blanks(theme_bw()))
206+
expect_true(inherit_blanks(theme_classic()))
207+
expect_true(inherit_blanks(theme_dark()))
208+
expect_true(inherit_blanks(theme_light()))
209+
expect_true(inherit_blanks(theme_linedraw()))
210+
expect_true(inherit_blanks(theme_minimal()))
211+
expect_true(inherit_blanks(theme_void()))
212+
})

0 commit comments

Comments
 (0)