@@ -266,23 +266,23 @@ element_grob.element_line <- function(element, x = 0:1, y = 0:1,
266
266
)
267
267
}
268
268
269
-
270
-
271
- # ' Define new elements for a theme's element tree
269
+ # ' Define and register new theme elements
272
270
# '
273
- # ' Each theme has an element tree that defines which theme elements inherit
274
- # ' theme parameters from which other elements. The function `el_def()` can be used
275
- # ' to define new or modified elements for this tree.
271
+ # ' The underlying structure of a ggplot2 theme is defined via the element tree, which
272
+ # ' specifies for each theme element what type it should have and whether it inherits from
273
+ # ' a parent element. In some use cases, it may be necessary to modify or extend this
274
+ # ' element tree and provide default settings for newly defined theme elements.
276
275
# '
277
- # ' @param class The name of the element class. Examples are "element_line" or
278
- # ' "element_text" or "unit", or one of the two reserved keywords "character" or
279
- # ' "margin". The reserved keyword "character" implies a character
280
- # ' or numeric vector, not a class called "character". The keyword
281
- # ' "margin" implies a unit vector of length 4, as created by [margin()].
282
- # ' @param inherit A vector of strings, naming the elements that this
283
- # ' element inherits from.
284
- # ' @param description An optional character vector providing a description
285
- # ' for the element.
276
+ # ' The function `register_theme_elements()` provides the option to globally register new
277
+ # ' theme elements with ggplot2. In general, for each new theme element both an element
278
+ # ' definition and a corresponding entry in the element tree should be provided. See
279
+ # ' examples for details. For extension package that use this functionality, it is
280
+ # ' recommended to call `register_theme_elements()` from the `.onLoad()` function.
281
+ # ' @param ... Element specifications
282
+ # ' @param element_tree Addition of or modification to the element tree, which specifies the
283
+ # ' inheritance relationship of the theme elements. The element tree must be provided as
284
+ # ' a list of named element definitions created with el_def().
285
+ # ' @param complete If `TRUE` (the default), elements are set to inherit from blank elements.
286
286
# ' @examples
287
287
# ' # define a new coord that includes a panel annotation
288
288
# ' coord_annotate <- function(label = "panel annotation") {
@@ -297,9 +297,8 @@ element_grob.element_line <- function(element, x = 0:1, y = 0:1,
297
297
# ' )
298
298
# ' }
299
299
# '
300
- # ' # update the default theme by adding a new `panel.annotation`
301
- # ' # theme element
302
- # ' old <- theme_update(
300
+ # ' # register a new theme element `panel.annotation`
301
+ # ' register_theme_elements(
303
302
# ' panel.annotation = element_text(color = "blue", hjust = 0.95, vjust = 0.05),
304
303
# ' element_tree = list(panel.annotation = el_def("element_text", "text"))
305
304
# ' )
@@ -309,18 +308,74 @@ element_grob.element_line <- function(element, x = 0:1, y = 0:1,
309
308
# ' geom_point() +
310
309
# ' coord_annotate("annotation in blue")
311
310
# '
312
- # ' # revert to original default theme
313
- # ' theme_set(old)
311
+ # ' # revert to original ggplot2 settings
312
+ # ' reset_theme_settings()
313
+ # ' @keywords internal
314
+ # ' @export
315
+ register_theme_elements <- function (... , element_tree = NULL , complete = TRUE ) {
316
+ old <- ggplot_global $ theme_default
317
+ t <- theme(... , complete = complete )
318
+ ggplot_global $ theme_default <- ggplot_global $ theme_default %+ replace % t
319
+
320
+ # Merge element trees
321
+ ggplot_global $ element_tree <- defaults(element_tree , ggplot_global $ element_tree )
322
+
323
+ invisible (old )
324
+ }
325
+
326
+ # ' @rdname register_theme_elements
327
+ # ' @details
328
+ # ' The function `reset_theme_settings()` restores the default element tree, discards
329
+ # ' all new element definitions, and (unless turned off) resets the currently active
330
+ # ' theme to the default.
331
+ # ' @param reset_current If `TRUE` (the default), the currently active theme is
332
+ # ' reset to the default theme.
333
+ # ' @keywords internal
334
+ # ' @export
335
+ reset_theme_settings <- function (reset_current = TRUE ) {
336
+ ggplot_global $ element_tree <- .element_tree
337
+
338
+ # reset the underlying fallback default theme
339
+ ggplot_global $ theme_default <- theme_grey()
340
+
341
+ if (isTRUE(reset_current )) {
342
+ # reset the currently active theme
343
+ ggplot_global $ theme_current <- ggplot_global $ theme_default
344
+ }
345
+ }
346
+
347
+ # ' @rdname register_theme_elements
348
+ # ' @details
349
+ # ' The function `get_element_tree()` returns the currently active element tree.
350
+ # ' @keywords internal
351
+ # ' @export
352
+ get_element_tree <- function () {
353
+ ggplot_global $ element_tree
354
+ }
355
+
356
+ # ' @rdname register_theme_elements
357
+ # ' @details
358
+ # ' The function `el_def()` is used to define new or modified element types and
359
+ # ' element inheritance relationships for the element tree.
360
+ # ' @param class The name of the element class. Examples are "element_line" or
361
+ # ' "element_text" or "unit", or one of the two reserved keywords "character" or
362
+ # ' "margin". The reserved keyword "character" implies a character
363
+ # ' or numeric vector, not a class called "character". The keyword
364
+ # ' "margin" implies a unit vector of length 4, as created by [margin()].
365
+ # ' @param inherit A vector of strings, naming the elements that this
366
+ # ' element inherits from.
367
+ # ' @param description An optional character vector providing a description
368
+ # ' for the element.
314
369
# ' @keywords internal
315
370
# ' @export
316
371
el_def <- function (class = NULL , inherit = NULL , description = NULL ) {
317
372
list (class = class , inherit = inherit , description = description )
318
373
}
319
374
320
375
321
- # This data structure represents the theme elements and the inheritance
322
- # among them. (In the future, .element_tree should be removed in favor
323
- # of direct assignment to ggplot_global$element_tree, see below.)
376
+ # This data structure represents the default theme elements and the inheritance
377
+ # among them. It should not be read from directly, since users may modify the
378
+ # current element tree stored in ggplot_global$element_tree
324
379
.element_tree <- list (
325
380
line = el_def(" element_line" ),
326
381
rect = el_def(" element_rect" ),
@@ -424,8 +479,6 @@ el_def <- function(class = NULL, inherit = NULL, description = NULL) {
424
479
aspect.ratio = el_def(" character" )
425
480
)
426
481
427
- ggplot_global $ element_tree <- .element_tree
428
-
429
482
# Check that an element object has the proper class
430
483
#
431
484
# Given an element object and the name of the element, this function
0 commit comments