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

purpose of `validate_element`? #1240

Closed
baptiste opened this Issue Aug 5, 2015 · 6 comments

Comments

Projects
None yet
2 participants
@baptiste
Contributor

baptiste commented Aug 5, 2015

validate_element makes it hard to use a custom grob instead of the default theme element, say, replacing a facet strip text with a grob that handles multiple lines and plotmath expressions, or an axis with an arrow, etc.

Is there a strong argument to maintain this internal check?

@hadley

This comment has been minimized.

Member

hadley commented Aug 5, 2015

Yes, because otherwise if you supply the wrong type of grob you'll get an obscure error when the plot is drawn, not when you set the theme. The prior version of themes let you have custom grobs, but no one ever used its not a common request.

But it's just a test for inheritance, so if your custom grob implements the text protocol, why don't you inherit from element_text?

@hadley hadley closed this Aug 5, 2015

@hadley

This comment has been minimized.

Member

hadley commented Aug 5, 2015

In other words, make it work like the other element functions:

library(ggplot2)

element_custom <- function() {
  structure(list(), class = c("element_custom", "element_text"))
}

element_grob.element_custom <- function(element, label="", ...)  {
  disect <- strsplit(label, "\\n")[[1]]
  g1 <- gridExtra::tableGrob(as.matrix(disect), 
    parse = TRUE,
    theme = gridExtra::theme.list(
      gpar.corefill = grid::gpar(fill = NA, col = NA), 
      core.just = "center")
  )
  grid::gTree(
    children = grid::gList(g1), 
    height = grid::grobHeight(g1), 
    cl = "custom_strip"
  )
}
# gTrees don't know their size and ggplot would squash it, so give it room
grobHeight.custom_strip <- function(x, ...) x$height
heightDetails.custom_axis <- function(x, ...) x$height

title <- c(
  "First*line \n italic('see that second')", 
  "this~is~boring",
  "integral(f(x)*dx, a, b)"
)

iris2 <- iris
iris2$Species <- factor(iris$Species, labels = title)
ggplot(iris2, aes(Sepal.Length, Sepal.Width)) +
  geom_line() + facet_grid(.~Species) +
  theme(strip.text.x = element_custom())
@hadley

This comment has been minimized.

Member

hadley commented Aug 5, 2015

Ooh, but that doesn't work because of the way themes elements are merged. This works, but is a bit clunky:

ggplot(iris2, aes(Sepal.Length, Sepal.Width)) +
  geom_line() + facet_grid(. ~ Species) + 
  (theme_grey() %+replace% theme(strip.text.x = element_custom()))

@wch is there a way to override/replace a theme element on the current plot?

@baptiste

This comment has been minimized.

Contributor

baptiste commented Aug 5, 2015

The prior version of themes let you have custom grobs, but no one ever used its not a common request.

Maybe, but another way to look at it is that if it's too difficult/hacky, no-one will think it's possible in the first place. I posted about ~10 answers over the years on the mailing list and SO, with the old and new theme systems; most of them would otherwise be unanswered, or involve heavy post-processing.
Other examples I can remember included replacing the axis labels with small images, chemical formulas, or tables.

But it's just a test for inheritance, so if your custom grob implements the text protocol, why don't you inherit from element_text?

it doesn't work, unfortunately, for reasons I don't understand. I've updated the SO code by-the-way, as it wasn't working anymore.

@hadley

This comment has been minimized.

Member

hadley commented Aug 6, 2015

@baptiste I provided an example that works for me

@baptiste

This comment has been minimized.

Contributor

baptiste commented Aug 29, 2015

it works, but the %+replace% workaround is still not very intuitive, is there a way to get + theme(strip.text.x = element_custom()) to work?

Here's a practical example: http://stackoverflow.com/a/32281523/471093

@lock lock bot locked as resolved and limited conversation to collaborators Jun 19, 2018

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.