Skip to content

Commit 61bc5f3

Browse files
committed
added proxy methods
1 parent 486a7c5 commit 61bc5f3

21 files changed

Lines changed: 715 additions & 28 deletions

DESCRIPTION

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ RoxygenNote: 7.3.2
2323
Imports:
2424
htmlwidgets,
2525
jsonlite,
26-
magrittr
26+
magrittr,
27+
shiny
2728
Depends:
2829
R (>= 2.10)
2930
LazyData: true

NAMESPACE

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,20 @@
33
export("%>%")
44
export(JS)
55
export(renderUPlot)
6+
export(uAddSeries)
67
export(uAxesX)
78
export(uAxesY)
89
export(uBands)
910
export(uColors)
11+
export(uDelSeries)
1012
export(uPlot)
1113
export(uPlotOutput)
14+
export(uProxy)
15+
export(uRedraw)
1216
export(uScatter)
1317
export(uSeries)
18+
export(uSetData)
19+
export(uSetSeries)
1420
importFrom(grDevices,palette)
1521
importFrom(htmlwidgets,JS)
1622
importFrom(htmlwidgets,createWidget)
@@ -19,4 +25,5 @@ importFrom(htmlwidgets,shinyWidgetOutput)
1925
importFrom(htmlwidgets,sizingPolicy)
2026
importFrom(jsonlite,as_gzjson_b64)
2127
importFrom(magrittr,"%>%")
28+
importFrom(shiny,getDefaultReactiveDomain)
2229
importFrom(utils,modifyList)

R/proxy.R

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
2+
#' Call a proxy method
3+
#'
4+
#' @param proxy A \code{proxy} \code{htmlwidget} object.
5+
#' @param name Proxy method.
6+
#' @param ... Arguments passed to method.
7+
#'
8+
#' @return A \code{htmlwidgetProxy} \code{htmlwidget} object.
9+
#' @noRd
10+
.call_proxy <- function(proxy, name, ...) {
11+
if (!"htmlwidgetProxy" %in% class(proxy))
12+
stop("This function must be used with a htmlwidgetProxy object", call. = FALSE)
13+
proxy$session$sendCustomMessage(
14+
type = sprintf("uplot-%s", name),
15+
message = drop_nulls(list(id = proxy$id, ...))
16+
)
17+
proxy
18+
}
19+
20+
#' Proxy for uPlot
21+
#'
22+
#' @param shinyId single-element character vector indicating the output ID of the
23+
#' chart to modify (if invoked from a Shiny module, the namespace will be added
24+
#' automatically).
25+
#' @param session the Shiny session object to which the chart belongs; usually the
26+
#' default value will suffice.
27+
#'
28+
#' @return A `uProxy` object.
29+
#'
30+
#'
31+
#' @export
32+
#'
33+
#' @importFrom shiny getDefaultReactiveDomain
34+
#'
35+
#' @examples
36+
#' \dontrun{
37+
#'
38+
#' # Consider having created a editor widget with
39+
#' uPlotOutput("mychart") # UI
40+
#' output$mychart <- renderUPlot({}) # Server
41+
#'
42+
#' # Then you can call proxy methods in observer:
43+
#'
44+
#'
45+
#' }
46+
uProxy <- function(shinyId, session = shiny::getDefaultReactiveDomain()) {
47+
if (is.null(session)) {
48+
stop("uProxy must be called from the server function of a Shiny app")
49+
}
50+
if (!is.null(session$ns) && nzchar(session$ns(NULL)) && substring(shinyId, 1, nchar(session$ns(""))) != session$ns("")) {
51+
shinyId <- session$ns(shinyId)
52+
}
53+
structure(
54+
list(
55+
session = session,
56+
id = shinyId,
57+
x = list()
58+
),
59+
class = c("uProxy", "htmlwidgetProxy")
60+
)
61+
}
62+
63+
64+
is_proxy <- function(uplot) {
65+
inherits(uplot, "uProxy")
66+
}
67+
68+
69+
#' Redraw a chart
70+
#'
71+
#' @param uplot Proxy for a chart created with [uProxy()].
72+
#' @param rebuildPaths If `FALSE` use cached series.
73+
#' @param recalcAxes Recalculate axes.
74+
#'
75+
#' @return An `htmlwidget` object of class `"uPlot"` or a `uProxy` object.
76+
#' @export
77+
#'
78+
#'
79+
#' @example examples/shiny-proxy-series-deladd.R
80+
uRedraw <- function(uplot, rebuildPaths = TRUE, recalcAxes = TRUE) {
81+
if (is_proxy(uplot)) {
82+
proxy <- .call_proxy(
83+
proxy = uplot,
84+
name = "redraw",
85+
rebuildPaths = rebuildPaths,
86+
recalcAxes = recalcAxes
87+
)
88+
return(proxy)
89+
}
90+
check_uplot(uplot)
91+
warning("uRedraw: no method for uPlot object, can only be used with uProxy()")
92+
return(uplot)
93+
}
94+
95+
96+
#' Set data to a chart
97+
#'
98+
#' @param uplot Chart created with [uPlot()] or [uProxy()].
99+
#' @param data The `data.frame` to use in chart.
100+
#'
101+
#' @return An `htmlwidget` object of class `"uPlot"` or a `uProxy` object.
102+
#' @export
103+
#'
104+
#' @examples
105+
#' uPlot() %>%
106+
#' uSetData(temperatures)
107+
#'
108+
#' @example examples/shiny-proxy-setdata.R
109+
uSetData <- function(uplot, data) {
110+
if (is_proxy(uplot)) {
111+
proxy <- .call_proxy(
112+
proxy = uplot,
113+
name = "setData",
114+
data = prepare_data(data)
115+
)
116+
return(proxy)
117+
}
118+
check_uplot(uplot)
119+
data <- prepare_data(data)
120+
uplot$x$config$data <- data
121+
series_nms <- attr(data, ".nms")
122+
uplot$xseries_nms <- series_nms
123+
if (length(uplot$x$config$options$series) < 1) {
124+
strokes <- rep_len(palette(), length(series_nms))
125+
uplot$x$config$options$series <- prepare_options_series(
126+
label = series_nms,
127+
stroke = strokes
128+
)
129+
}
130+
return(uplot)
131+
}
132+
133+
134+
#' Update series to a chart via proxy
135+
#'
136+
#' @param uplot Chart created with [uPlot()] or [uProxy()].
137+
#' @param seriesIdx Index of the serie to set.
138+
#' @param show,focus Toggles series visibility or focus.
139+
#' @param ... Options for the series, see [uSeries()].
140+
#'
141+
#' @return An `htmlwidget` object of class `"uPlot"` or a `uProxy` object.
142+
#' @export
143+
#'
144+
#' @name proxy-series
145+
#'
146+
#' @examples
147+
#' uPlot() %>%
148+
#' uSetData(temperatures)
149+
#'
150+
#' @example examples/shiny-proxy-series-visibility.R
151+
#' @example examples/shiny-proxy-series-deladd.R
152+
uSetSeries <- function(uplot, seriesIdx, show = TRUE, focus = NULL) {
153+
if (is_proxy(uplot)) {
154+
proxy <- .call_proxy(
155+
proxy = uplot,
156+
name = "setSeries",
157+
seriesIdx = seriesIdx - 1,
158+
options = drop_nulls(list(show = show, focus = focus))
159+
)
160+
return(proxy)
161+
}
162+
check_uplot(uplot)
163+
warning("uSetSeries: no method for uPlot object, can only be used with uProxy()")
164+
return(uplot)
165+
}
166+
167+
#' @export
168+
#'
169+
#' @rdname proxy-series
170+
uAddSeries <- function(uplot, seriesIdx, ...) {
171+
if (is_proxy(uplot)) {
172+
proxy <- .call_proxy(
173+
proxy = uplot,
174+
name = "addSeries",
175+
seriesIdx = seriesIdx - 1,
176+
options = list(...)
177+
)
178+
return(proxy)
179+
}
180+
check_uplot(uplot)
181+
uplot <- uSeries(uSeries, serie = seriesIdx, ...)
182+
return(uplot)
183+
}
184+
185+
#' @export
186+
#'
187+
#' @rdname proxy-series
188+
uDelSeries <- function(uplot, seriesIdx) {
189+
if (is_proxy(uplot)) {
190+
proxy <- .call_proxy(
191+
proxy = uplot,
192+
name = "delSeries",
193+
seriesIdx = seriesIdx - 1
194+
)
195+
return(proxy)
196+
}
197+
check_uplot(uplot)
198+
warning("uDelSeries: no method for uPlot object, can only be used with uProxy()")
199+
return(uplot)
200+
}

R/uPlot.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
#' )
3333
#' )
3434
#' )
35-
uPlot <- function(data,
35+
uPlot <- function(data = NULL,
3636
options = list(),
3737
...,
3838
use_gzipped_json = FALSE,

R/uSeries.R

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#' Series options
33
#'
44
#' @param uplot Chart created with [uPlot()].
5-
#' @param name Name of the serie (column's name in data).
5+
#' @param serie Name (column's name in data) or index of the serie.
66
#' @param label Label to display in legend.
77
#' @param stroke Stroke color of the line.
88
#' @param ... Other options.
@@ -13,12 +13,16 @@
1313
#' @importFrom utils modifyList
1414
#'
1515
#' @example examples/ex-uSeries.R
16-
uSeries <- function(uplot, name, label = NULL, stroke = NULL, ...) {
16+
uSeries <- function(uplot, serie, label = NULL, stroke = NULL, ...) {
1717
check_uplot(uplot)
1818
stopifnot(
19-
"'name' must be a character of length 1" = is.character(name) & identical(length(name), 1L)
19+
"'name' must be a character of length 1" = identical(length(serie), 1L)
2020
)
21-
serie_index <- find_serie_index(uplot, name)
21+
if (is.character(serie)) {
22+
serie_index <- find_serie_index(uplot, serie)
23+
} else {
24+
serie_index <- as.numeric(serie)
25+
}
2226
uplot$x$config$options$series[[serie_index]] <- modifyList(
2327
x = uplot$x$config$options$series[[serie_index]],
2428
val = drop_nulls(list(
@@ -63,7 +67,7 @@ find_serie_index <- function(uplot, name) {
6367
uColors <- function(uplot, ...) {
6468
args <- list(...)
6569
for (i in seq_along(args)) {
66-
uplot <- uSeries(uplot, name = names(args)[i], stroke = args[[i]])
70+
uplot <- uSeries(uplot, serie = names(args)[i], stroke = args[[i]])
6771
}
6872
uplot
6973
}

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,14 +83,14 @@ uPlot(
8383
uBands("temperature", "average", fill = "#F681804D") %>%
8484
uBands("average", "temperature", fill = "#2F64FF4D") %>%
8585
uSeries(
86-
name = "temperature",
86+
serie = "temperature",
8787
label = "Temperature 2022",
8888
stroke = "red",
8989
width = 2,
9090
value = htmlwidgets::JS("function(u, v) {return v + '°C';}")
9191
) %>%
9292
uSeries(
93-
name = "average",
93+
serie = "average",
9494
label = "Average 2018-2021",
9595
stroke = "black",
9696
width = 2,

examples/ex-uSeries.R

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,37 +2,37 @@
22
# Change label and color
33
uPlot(temperatures[, c("date", "temperature")]) %>%
44
uSeries(
5-
name = "temperature",
5+
serie = "temperature",
66
label = "Temperature in 2022",
77
stroke = "steelblue"
88
)
99

1010
# Hide a serie at start
1111
uPlot(temperatures) %>%
1212
uSeries(
13-
name = "temperature",
13+
serie = "temperature",
1414
show = FALSE
1515
)
1616

1717
### Line style
1818
# default
1919
uPlot(temperatures[11:40, c("date", "temperature")]) %>%
2020
uSeries(
21-
name = "temperature",
21+
serie = "temperature",
2222
paths = JS("uPlot.paths.linear()"),
2323
points = list(show = TRUE)
2424
)
2525
# spline curve
2626
uPlot(temperatures[11:40, c("date", "temperature")]) %>%
2727
uSeries(
28-
name = "temperature",
28+
serie = "temperature",
2929
paths = JS("uPlot.paths.spline()"),
3030
points = list(show = TRUE)
3131
)
3232
# stepped line
3333
uPlot(temperatures[11:40, c("date", "temperature")]) %>%
3434
uSeries(
35-
name = "temperature",
35+
serie = "temperature",
3636
paths = JS("uPlot.paths.stepped({align: 1})"),
3737
points = list(show = TRUE)
3838
)

examples/shiny-default.R

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ server <- function(input, output, session) {
2121
)
2222
) %>%
2323
uSeries(
24-
name = "datetime",
24+
serie = "datetime",
2525
label = "Datetime"
2626
) %>%
2727
uSeries(
28-
name = "consumption",
28+
serie = "consumption",
2929
label = "Consumption (MW)",
3030
stroke = "#0174DF"
3131
)

0 commit comments

Comments
 (0)