---
title: "Idle Callback"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Idle Callback}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

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


## Run a function continually while window is valid

An **idle callback** is an R function that will be run continually while the 
UI window is valid - regardless of what the user is doing.

Thanks to [ozjimbob](https://twitter.com/ozjimbob) for this great example!

## Video 

In this example, at each timestep the `rain()` function updates the size
of the current effect for all the current rain drops.

If the user changes values in the UI, then this will be used to updated the 
appearance of the rain drops.

<video controls>
  <source src="video/idle.mp4" type="video/mp4">
  Your browser does not support the video tag.
</video> 




## Code


```{r eval = FALSE}
library(grid)
library(tickle)


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Open a double-buffered graphics device that renders nice and fast
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
x11(type = 'dbcairo', antialias = 'none')
dev.control(displaylist = 'inhibit')


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Reactive variables controlled by the UI
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
size <- reactive_dbl(value=6)
rate <- reactive_dbl(value=10)


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Raindrops data: coordinates and current size
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
df = data.frame(x=runif(10,-1,1),y=runif(10,-1,1),size=rep(1,10))


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Plot the current rain drops
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
rain <- function() {
  df <<- tail(df,1000)
  df2 <- data.frame(x=runif(rate(),-1,1),y=runif(rate(),-1,1),size=rep(size(),rate()))
  df <<- rbind(df,df2)
  df$size <<- df$size * 0.9
  dev.hold()
  plot(df$y,df$x,cex=df$size,xlim=c(-1,1),ylim=c(-1,1))
  dev.flush()
}


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Define the UI.  
# The idle callback is attached to the top level window.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ui_spec <- tic_window(
  idle_func = rain, idle_fps = 10,
  tic_col(
    tic_label("Raindrops", style = 'h3'),
    tic_separator(),
    tic_row(
      tic_label("Thickness"),
      tic_slider(variable = size, from = 6, to = 20),
      tic_label("Rate"),
      tic_slider(variable = rate, from = 1, to = 40)
    )
  )
)


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Render the UI
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
win <- render_ui(ui_spec)
```


