|
| 1 | +#' Caching scale breaks |
| 2 | +#' |
| 3 | +#' This helper caches the output of another breaks function the first time it is |
| 4 | +#' evaluated. All subsequent calls will return the same breaks vector |
| 5 | +#' regardless of the provided limits. In general this is not what you want |
| 6 | +#' since the breaks should change when the limits change. It is helpful in the |
| 7 | +#' specific case that you are using `follow.scale` on `stat_bin()` and related |
| 8 | +#' binning stats, because it ensures that the breaks are not recomputed after |
| 9 | +#' they are used to define the bin edges. |
| 10 | +#' |
| 11 | +#' @param breaks A function that takes the limits as input and returns breaks |
| 12 | +#' as output. See `ggplot2::continuous_scale` for details. |
| 13 | +#' |
| 14 | +#' @return A wrapped breaks function suitable for use with ggplot scales. |
| 15 | +#' @export |
| 16 | +breaks_cached <- function(breaks) { |
| 17 | + if (! rlang::is_function(breaks)) { |
| 18 | + cli::cli_abort("{.arg breaks} must be a function") |
| 19 | + } |
| 20 | + |
| 21 | + cached <- ggplot2::ggproto( |
| 22 | + "BreaksCached", NULL, |
| 23 | + fn = breaks, |
| 24 | + cached = NULL, |
| 25 | + get_breaks = function(self, limits) { |
| 26 | + if (is.null(self$cached)) self$cached <- self$fn(limits) |
| 27 | + self$cached |
| 28 | + } |
| 29 | + )$get_breaks |
| 30 | + |
| 31 | + class(cached) <- c("ggplot2_cached_breaks", class(cached)) |
| 32 | + cached |
| 33 | +} |
| 34 | + |
| 35 | +#' @export |
| 36 | +format.ggplot2_cached_breaks <- function(x, ...) { |
| 37 | + bc <- environment(x)$self |
| 38 | + inner <- environment(bc$fn)$f |
| 39 | + |
| 40 | + paste0( |
| 41 | + "<cached breaks function>\n", |
| 42 | + ifelse( |
| 43 | + is.null(bc$cached), |
| 44 | + paste0(" ", format(inner), collapse = "\n"), |
| 45 | + paste0(" [", class(bc$cached), "] ", paste0(format(bc$cached), collapse = " ")) |
| 46 | + ) |
| 47 | + ) |
| 48 | +} |
| 49 | + |
| 50 | +#' @export |
| 51 | +print.ggplot2_cached_breaks <- function(x, ...) { |
| 52 | + cat(format(x), sep = "") |
| 53 | +} |
0 commit comments