Skip to content

Theme element dual inheritance#5175

Merged
teunbrand merged 5 commits intotidyverse:mainfrom
teunbrand:character_elements
Feb 21, 2023
Merged

Theme element dual inheritance#5175
teunbrand merged 5 commits intotidyverse:mainfrom
teunbrand:character_elements

Conversation

@teunbrand
Copy link
Copy Markdown
Collaborator

This PR aims to fix a problem I ran into during 2 previous PRs (#5167 and #4879). Instead of the pragmatic hotfixes in those PRs, this one addresses the root cause.

The problem is that calc_element() could not be used to calculate any part of the theme that had dual <character/numeric> inheritance. Under the hood, an exception was made in the validation to allow character elements to also be numeric. This was the case for legend.position that could be either "top" or c(0, 1), for example. This is all fine, however, calc_element() did not special-case the <character/numeric> dual inheritance, and would throw an error if you provide a numeric vector (see reprex).

The solution in this PR is to properly give those elements that should support dual inheritance a dual class. By doing this, we no longer need to special-case in the validator, and calc_element() gives the right answers. Also, we can let aspect.ratio inherit from <numeric> now, whereas previously it would throw uninformative errors from later in the plotting process.

A demonstration of before this PR (backtraces omitted):

library(ggplot2)

theme <- theme_get() +
  theme(
    aspect.ratio = "foobar",
    plot.tag.position = c(0, 1)
  )

calc_element("aspect.ratio", theme)
#> [1] "foobar"
calc_element("plot.tag.position", theme)
#> Error:
#> ! Theme element `plot.tag.position` must have class <character>

Whereas now:

devtools::load_all("~/packages/ggplot2")
#> ℹ Loading ggplot2

calc_element("aspect.ratio", theme)
#> Error:
#> ! Theme element `aspect.ratio` must have class <numeric>

calc_element("plot.tag.position", theme)
#> [1] 0 1

Created on 2023-02-02 with reprex v2.0.2

@teunbrand teunbrand mentioned this pull request Feb 4, 2023
legend.key.width = el_def("unit", "legend.key.size"),
legend.text = el_def("element_text", "text"),
legend.text.align = el_def("character"),
legend.text.align = el_def("numeric"),
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we want to accept both numeric and character? ie. both e.g. "center" and 0.5

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently, giving a character(1) results in a grid-error, i.e. legend.text.align = "left" gets:

Error in valid.charjust(just) : invalid vertical justification

Whereas with this PR, the error will be:

! The legend.text.align theme element must be a <numeric> object.

Which is slightly more informative. I can see how allowing character justification might help here, but that might be a separate PR from this one.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

huh... surprising - but agreed that it is separate from this

Copy link
Copy Markdown
Member

@thomasp85 thomasp85 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@teunbrand
Copy link
Copy Markdown
Collaborator Author

Thanks for the review!

@teunbrand teunbrand merged commit 519bc83 into tidyverse:main Feb 21, 2023
@teunbrand teunbrand deleted the character_elements branch February 21, 2023 18:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants