---
title: "Help for ggplot extenders"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{extender-info}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)
```

```{r setup, message=FALSE, warning=FALSE, echo=FALSE}
library(ggdibbler)
```

## Your old `ggplot` extension *can* learn new tricks
The beauty of the broad solution `ggdibbler` provides is that it always works. It might not always look *good* or be exactly what you were looking for, but it always works. To illustrate this, we included the `ggraph` example in the [introduction to `ggdibbler`](https://harriet-mason.github.io/ggdibbler/articles/A_how-to-guide.html) vignette.

In the `ggraph` example, I illustrated how you can use the `ggdibbler` approach with a `ggplot` extension that isn't even aware `ggdibbler` exists. While that method works (well enough) it can be somewhat annoying to implement, and it doesn't give you access to the nested positions (as they use internal variables). I can understand fellow `ggplot` extenders might be chomping at the bit to see what their plots look like with uncertainty and nested positions. 

Currently, if you want a dibbled version of your `ggplot2` extension, you need to update your code to include it.  We plan to update `ggdibbler` such that the approach can be used by extensions without any required dependency on `ggdibbler` (see the related [Github issue](https://github.com/harriet-mason/ggdibbler/issues/55) on the topic) but if you want it to work for your extension literally right now, you will either have to push a bit of preprocessing onto your users, or you will need to write a `*_sample` variation of your functions.

## Implementing uncertainty visualisation as a nested stat
Sometimes, when making a `ggdibbler` version of a `ggplot2` base function, I would think to myself "What is the point of this, who on earth needs an uncertain version of `stat_unique`?". I still sometimes think that, but the reason we implemented it with *ALL* `ggplot2` functions, is not for the users, but rather for the extenders. If there is a `ggplot2` extension that is the child of a base `stat` or base position, a `geom_*_sample` variation of their function will simply be the child of the `ggdibbler` variation of the `ggplot2` stat, instead of the original `ggplot2` code. The only `ggplot2` extension that might not work with `ggdibbler` is `ggdist`, although it should work if you have a distribution of distributions. 

Now, I have made all functions in base `ggplot2` accept uncertain inputs, go me, but the real power of `ggplot2` comes from the wealth of extension packages. Now, as fun as I am sure it would be, I am not about to spend the next 5 years making pull requests on every `ggplot2` extension package so that they can all accept random variables. Largely because:

1) Going around making pull requests that forces dependency on *my* package sounds like the early warning signs of a personality disorder
2) (More importantly) that sounds really boring and I don't want to.

Thankfully, the `ggdibbler` approach is so easy if you are the author/maintainer of a `ggplot2` extension and you want it to accept random variables, you can just do it yourself. If your package implements a new geom or stat, then you can follow the instructions below, if your package implements anything else (like a scale or position) then you will need to wait until the update that doesn't require any of this at all (sorry).

### Geoms
`ggdibbler` doesn't actually implement any new geoms, the geoms are just wrappers for the stats. If you use an existing `ggplot2` stat, `ggdibbler` should already have a variation of it, so you can just make the wrapper function using code that looks like this:

```{r, eval = FALSE}
geom_YOURGEOM_sample <- make_constructor(YOURGEOM, stat = "GGPLOT2STAT_sample",
                                         times = 10, seed = NULL)
```

### Stats
Stats are slightly more complicated, but still shockingly simple. There are two approaches to this. The first options is to make a YOURSTATSample child version of your stat, similar to the relationship between the base stats in `ggplot` and the sample stats implemented in `ggdibbler`. When making these functions in `ggdibbler` I literally had a template that I would copy and paste into the .R file (don't tell me whether this is good or bad practice, I don't care).

```{r, eval = FALSE}
#' @importFrom ggplot2 ggproto Stat***
#' @format NULL
#' @usage NULL
#' @export
Stat***Sample <- ggplot2::ggproto("Stat***Sample", ggplot2::Stat***,
                                  ### INCLUDE SETUP PARAMS IF IN PARENT STAT 
                                  setup_params = function(self, data, params) {
                                    # take one sample just to train the parameters
                                    times <- params$times
                                    params$times <- 1
                                    data <- dibble_to_tibble(data, params)
                                    params <- ggplot2::ggproto_parent(ggplot2::Stat***, self)$setup_params(data, params)
                                    params$times <- times
                                    params
                                  }
                                  ###  SETUP_DATA MUST BE IMPLEMENTED...
                                  setup_data = function(data, params) {
                                    dibble_to_tibble(data, params) 
                                    # BUT YOU ONLY NEED TO INCLUDE THIS LINE IF THE MAIN STAT USES SETUP DATA 
                                    ggproto_parent(Stat***, self)$setup_data(data, scales)
                                    },
                                  
                                  extra_params = c("na.rm", "times", "seed")
)

#' @export
#' @inheritParams ggplot2::stat_***
#' @param times A parameter used to control the number of values sampled from 
#' each distribution.
#' @param seed Set the seed for the layers random draw, allows you to plot the
#' same draw across multiple layers.
stat_***_sample <- make_constructor(Stat***Sample, geom = "***", 
                                    times = 10, seed = NULL)




```

The alternative option is if your stat is the child of an existing `ggplot2` stat, you can just make a new version of your function that is a child of the `ggdibbler` version instead of the `ggplot2` version. I haven't implemented this one, so I am not 100% sure how it would work, but the *only* thing that `ggdibbler` does (99% of the time) is do a `setup_data` step.

```{r, include=FALSE, eval=FALSE}
library(spelling)
qmd <- "D_extender-info.Rmd"
check_spelling <- spell_check_files(
  qmd,
  lang = "en_GB"
)
if (nrow(check_spelling) > 0) {
  print(check_spelling)
  stop("Check spelling in Qmd files!")
}
```
