-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Add function for registering of new theme elements. #3678
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add function for registering of new theme elements. #3678
Conversation
And another reprex, changing the order of things (change theme default first, then register new element). library(ggplot2)
# define a new coord that includes a panel annotation
coord_annotate <- function(label = "panel annotation") {
ggproto(NULL, CoordCartesian,
limits = list(x = NULL, y = NULL),
expand = TRUE,
default = FALSE,
clip = "on",
render_fg = function(panel_params, theme) {
element_render(theme, "panel.annotation", label = label)
}
)
}
# change default theme
theme_set(theme_bw())
# register a new theme element `panel.annotation`
register_theme_elements(
panel.annotation = element_text(color = "blue", hjust = 0.95, vjust = 0.05),
element_tree = list(panel.annotation = el_def("element_text", "text"))
)
df <- data.frame(x = 1:3, y = 1:3)
ggplot(df, aes(x, y)) +
geom_point() +
coord_annotate("annotation in blue") # revert default to original ggplot2 settings, including currently active theme
register_theme_elements(reset_all = TRUE)
ggplot(df, aes(x, y)) +
geom_point() +
coord_annotate("annotation in blue")
#> Theme element `panel.annotation` missing Created on 2019-12-18 by the reprex package (v0.3.0) |
I realize this still needs a news item and some unit tests, but I'd first like to get some feedback. Am I on the right track? |
One side-effect of this PR is that you can now completely nuke the currently active theme and still things will generally work. library(ggplot2)
theme_set(theme(text = element_blank()))
#> Warning: New theme missing the following elements: line, rect,
#> title, aspect.ratio, axis.title, axis.title.x, axis.title.x.top,
#> axis.title.x.bottom, axis.title.y, axis.title.y.left, axis.title.y.right,
#> axis.text, axis.text.x, axis.text.x.top, axis.text.x.bottom, axis.text.y,
#> axis.text.y.left, axis.text.y.right, axis.ticks, axis.ticks.x,
#> axis.ticks.x.top, axis.ticks.x.bottom, axis.ticks.y, axis.ticks.y.left,
#> axis.ticks.y.right, 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.line,
#> axis.line.x, axis.line.x.top, axis.line.x.bottom, axis.line.y,
#> axis.line.y.left, axis.line.y.right, legend.background, legend.margin,
#> legend.spacing, legend.spacing.x, legend.spacing.y, legend.key,
#> legend.key.size, legend.key.height, legend.key.width, legend.text,
#> legend.text.align, legend.title, legend.title.align, legend.position,
#> legend.direction, legend.justification, legend.box, legend.box.just,
#> legend.box.margin, legend.box.background, legend.box.spacing,
#> panel.background, panel.border, panel.spacing, panel.spacing.x,
#> panel.spacing.y, panel.grid, panel.grid.major, panel.grid.minor,
#> panel.grid.major.x, panel.grid.major.y, panel.grid.minor.x,
#> panel.grid.minor.y, panel.ontop, plot.background, plot.title,
#> plot.title.position, plot.subtitle, plot.caption, plot.caption.position,
#> plot.tag, plot.tag.position, plot.margin, strip.background,
#> strip.background.x, strip.background.y, strip.placement, strip.text,
#> strip.text.x, strip.text.y, strip.switch.pad.grid and strip.switch.pad.wrap
df <- data.frame(x = 1:3, y = 1:3)
ggplot(df, aes(x, y)) +
geom_point() Created on 2019-12-18 by the reprex package (v0.3.0) |
In general, I think a warning should only be emitted if an element both isn't defined and doesn't have a defined parent. In the example above with I think we can enforce that newly registered theme elements must inherit from an existing element and thus ensure that it works with any valid complete theme |
Just so we're on the same page: The warning is carried over from the current ggplot2 behavior. See reprex below, with ggplot2 3.2.1. I'm happy to remove the warning, as I think it generates a lot of false positives on cases that ggplot2 can recover from just fine, and with the new PR even more so. I'm also happy to add in a new warning as long as the logic is straightforward. In either case, though, the logic you describe would imply that the majority of cases that currently throw a warning wouldn't anymore. Is this your intended outcome? library(ggplot2)
t <- theme_gray()
t$axis.text.x <- NULL
theme_set(t)
#> Warning: New theme missing the following elements: axis.text.x
df <- data.frame(x = 1:3, y = 1:3)
ggplot(df, aes(x, y)) +
geom_point() Created on 2019-12-19 by the reprex package (v0.3.0) Session infodevtools::session_info()
#> ─ Session info ──────────────────────────────────────────────────────────
#> setting value
#> version R version 3.6.0 (2019-04-26)
#> os macOS Mojave 10.14.5
#> system x86_64, darwin15.6.0
#> ui X11
#> language (EN)
#> collate en_US.UTF-8
#> ctype en_US.UTF-8
#> tz America/Chicago
#> date 2019-12-19
#>
#> ─ Packages ──────────────────────────────────────────────────────────────
#> package * version date lib source
#> assertthat 0.2.1 2019-03-21 [1] CRAN (R 3.6.0)
#> backports 1.1.5 2019-10-02 [1] CRAN (R 3.6.0)
#> callr 3.3.2 2019-09-22 [1] CRAN (R 3.6.0)
#> cli 1.1.0 2019-03-19 [1] CRAN (R 3.6.0)
#> colorspace 1.4-1 2019-03-18 [1] CRAN (R 3.6.0)
#> crayon 1.3.4 2017-09-16 [1] CRAN (R 3.6.0)
#> curl 4.1 2019-09-16 [1] CRAN (R 3.6.0)
#> desc 1.2.0 2018-05-01 [1] CRAN (R 3.6.0)
#> devtools 2.0.2 2019-04-08 [1] CRAN (R 3.6.0)
#> digest 0.6.23 2019-11-23 [1] CRAN (R 3.6.0)
#> dplyr 0.8.3 2019-07-04 [1] CRAN (R 3.6.0)
#> evaluate 0.14 2019-05-28 [1] CRAN (R 3.6.0)
#> farver 2.0.1 2019-11-13 [1] CRAN (R 3.6.0)
#> fs 1.3.1 2019-05-06 [1] CRAN (R 3.6.0)
#> ggplot2 * 3.2.1 2019-08-10 [1] CRAN (R 3.6.0)
#> glue 1.3.1 2019-03-12 [1] CRAN (R 3.6.0)
#> gtable 0.3.0 2019-03-25 [1] CRAN (R 3.6.0)
#> highr 0.8 2019-03-20 [1] CRAN (R 3.6.0)
#> htmltools 0.3.6 2017-04-28 [1] CRAN (R 3.6.0)
#> httr 1.4.1 2019-08-05 [1] CRAN (R 3.6.0)
#> knitr 1.25 2019-09-18 [1] CRAN (R 3.6.0)
#> labeling 0.3 2014-08-23 [1] CRAN (R 3.6.0)
#> lazyeval 0.2.2 2019-03-15 [1] CRAN (R 3.6.0)
#> lifecycle 0.1.0 2019-08-01 [1] CRAN (R 3.6.0)
#> magrittr 1.5 2014-11-22 [1] CRAN (R 3.6.0)
#> memoise 1.1.0 2017-04-21 [1] CRAN (R 3.6.0)
#> mime 0.7 2019-06-11 [1] CRAN (R 3.6.0)
#> munsell 0.5.0 2018-06-12 [1] CRAN (R 3.6.0)
#> pillar 1.4.2 2019-06-29 [1] CRAN (R 3.6.0)
#> pkgbuild 1.0.6 2019-10-09 [1] CRAN (R 3.6.0)
#> pkgconfig 2.0.3 2019-09-22 [1] CRAN (R 3.6.0)
#> pkgload 1.0.2 2018-10-29 [1] CRAN (R 3.6.0)
#> prettyunits 1.0.2 2015-07-13 [1] CRAN (R 3.6.0)
#> processx 3.4.1 2019-07-18 [1] CRAN (R 3.6.0)
#> ps 1.3.0 2018-12-21 [1] CRAN (R 3.6.0)
#> purrr 0.3.3 2019-10-18 [1] CRAN (R 3.6.0)
#> R6 2.4.1 2019-11-12 [1] CRAN (R 3.6.0)
#> Rcpp 1.0.3 2019-11-08 [1] CRAN (R 3.6.0)
#> remotes 2.1.0 2019-06-24 [1] CRAN (R 3.6.0)
#> rlang 0.4.2 2019-11-23 [1] CRAN (R 3.6.0)
#> rmarkdown 1.15 2019-08-21 [1] CRAN (R 3.6.0)
#> rprojroot 1.3-2 2018-01-03 [1] CRAN (R 3.6.0)
#> scales 1.1.0.9000 2019-12-18 [1] local
#> sessioninfo 1.1.1 2018-11-05 [1] CRAN (R 3.6.0)
#> stringi 1.4.3 2019-03-12 [1] CRAN (R 3.6.0)
#> stringr 1.4.0 2019-02-10 [1] CRAN (R 3.6.0)
#> testthat 2.3.1 2019-12-01 [1] CRAN (R 3.6.0)
#> tibble 2.1.3 2019-06-06 [1] CRAN (R 3.6.0)
#> tidyselect 0.2.5 2018-10-11 [1] CRAN (R 3.6.0)
#> usethis 1.5.0 2019-04-07 [1] CRAN (R 3.6.0)
#> withr 2.1.2 2018-03-15 [1] CRAN (R 3.6.0)
#> xfun 0.9 2019-08-21 [1] CRAN (R 3.6.0)
#> xml2 1.2.2 2019-08-09 [1] CRAN (R 3.6.0)
#> yaml 2.2.0 2018-07-25 [1] CRAN (R 3.6.0)
#>
#> [1] /Library/Frameworks/R.framework/Versions/3.6/Resources/library |
Ah - I wasn't aware of that warning in the current code. I think we should remove it. The inheritance setup specifically allows for NULL as long as it has a valid parent so warning against it seems weird. But I think you should enforce that new theme elements always inherit from something, e.g. Basically I think this would be a function solemnly for extension developers. They should not rely on what the current theme is, so modifying that instead of the default (which is fixed now, right?) is bad. Because they don't know the look of the current theme it is better to encourage them to inherit from an existing element as they are more likely to get a fitting look |
@thomasp85 You raise a number of points. I'll try to address them all, one by one, in order.
It's a little more complicated than that. In the latest code, an explicit
There are plenty of elements that don't inherit from anything, such as
I think Lines 403 to 419 in e6cbcc1
I would like to keep the default as
I don't have a strong opinion on this, but I played through my head a couple of scenarios of how I would use this functionality and I found it unlikely that I'd ever want to register a new theme element but not also add it to the currently active theme. Either way, I'm happy to set it to
Sure, fine by me. Do you have a suggested name?
I'm not exactly sure what you mean by "is fixed now". It is still possible to define an individual theme with its own element tree, and it is also possible to make that theme the currently active theme via Are you suggesting that we undo that decision and only allow changes to the element tree via |
@thomasp85 To summarize how I'll move forward:
|
I think I've addressed all the points. Here is a reprex demonstrating the current API. library(ggplot2)
# define a new coord that includes a panel annotation
coord_annotate <- function(label = "panel annotation") {
ggproto(NULL, CoordCartesian,
limits = list(x = NULL, y = NULL),
expand = TRUE,
default = FALSE,
clip = "on",
render_fg = function(panel_params, theme) {
element_render(theme, "panel.annotation", label = label)
}
)
}
# change default theme
theme_set(theme_bw())
# register a new theme element `panel.annotation`
register_theme_elements(
panel.annotation = element_text(color = "blue", hjust = 0.95, vjust = 0.05),
element_tree = list(panel.annotation = el_def("element_text", "text"))
)
df <- data.frame(x = 1:3, y = 1:3)
ggplot(df, aes(x, y)) +
geom_point() +
coord_annotate("annotation in blue") reset_theme_settings(reset_current = FALSE)
ggplot(df, aes(x, y)) +
geom_point() +
coord_annotate("annotation in blue")
#> Theme element `panel.annotation` missing # no more warnings when themes with missing elements are set via theme_set()
theme_set(theme())
# ggplot recovers and pulls missing elements from default
# (note we had previously set the current theme to `theme_bw()`)
ggplot(df, aes(x, y)) +
geom_point() Created on 2019-12-24 by the reprex package (v0.3.0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
This closes #3677.
Created on 2019-12-18 by the reprex package (v0.3.0)