Skip to content

Commit 2eda0a8

Browse files
committed
version bump; copy unexported ggiraph functions; reorganize ggiraph files
1 parent fb9b8b3 commit 2eda0a8

File tree

6 files changed

+206
-32
lines changed

6 files changed

+206
-32
lines changed

CRAN-SUBMISSION

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
Version: 0.12.2
2-
Date: 2025-07-31 11:40:16 UTC
3-
SHA: 8267c0a30c0c496752e3054f636b48c1be643e5b
1+
Version: 0.14.0
2+
Date: 2025-09-20 03:27:51 UTC
3+
SHA: fb9b8b3d37b3a2820589a35b488b3a54b5f26111

DESCRIPTION

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ Package: ggformula
22
Title: Formula Interface to the Grammar of Graphics
33
Description: Provides a formula interface to 'ggplot2' graphics.
44
Type: Package
5-
Version: 0.14.0
5+
Version: 1.0.0
66
Authors@R: c(
77
person("Daniel", "Kaplan", email = "[email protected]", role = c("aut")),
88
person("Randall", "Pruim", email = "[email protected]", role = c("aut","cre"))
@@ -62,14 +62,14 @@ Collate:
6262
'formula2aes.R'
6363
'gf_aux.R'
6464
'gf_dist.R'
65+
'ggiraph.R'
6566
'layer_factory.R'
6667
'gf_function2d.R'
6768
'gf_functions.R'
6869
'gf_plot.R'
6970
'ggridges.R'
7071
'ggstrings.R'
7172
'newplots.R'
72-
'ggiraph.R'
7373
'ggiraph-themes.R'
7474
'ggiraph-documentation-with-examples.R'
7575
'reexports.R'

NEWS.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
# ggformula
2-
3-
## ggformula 0.14.0
1+
# ggformula 1.0.0
42

53
* Added support for interactive graphics based on {ggiraph}.
64
* Modifications to support {ggplot2} version 4.0.

R/ggiraph.R

Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#' @export
3939

4040
gf_girafe <- function(ggobj, code, ...) {
41+
4142
if (missing(code)) {
4243
return(ggiraph::girafe(ggobj = ggobj, ...))
4344
}
@@ -212,3 +213,201 @@ gf_labeller_interactive <- function(..., .mapping) {
212213

213214
ggiraph::labeller_interactive(.mapping = .mapping, !!!qdots)
214215
}
216+
217+
###############################################################################
218+
##
219+
## modified version of function in ggiraph, branching based on whether position
220+
## is specified.
221+
222+
layer_interactive <- function(
223+
layer_func, stat = NULL, position = NULL, ...,
224+
interactive_geom = NULL, extra_interactive_params = NULL) {
225+
226+
dots <- list(...)
227+
if (is.null(position)) {
228+
ggiraph_layer_interactive(
229+
layer_func, stat = stat, ...,
230+
interactive_geom = interactive_geom, extra_interactive_params = extra_interactive_params
231+
)
232+
} else {
233+
ggiraph_layer_interactive(
234+
layer_func, stat = stat, position = position, ...,
235+
interactive_geom = interactive_geom, extra_interactive_params = extra_interactive_params
236+
)
237+
}
238+
}
239+
240+
241+
##########################################################################
242+
## Functions copied from ggiraph because they are not (yet) exported there.
243+
244+
ggiraph_layer_interactive <-
245+
function (layer_func, ..., interactive_geom = NULL, extra_interactive_params = NULL)
246+
{
247+
args <- rlang::list2(...)
248+
interactive_mapping <- NULL
249+
interactive_params <- NULL
250+
index <- purrr::detect_index(args, function(x) {
251+
inherits(x, "uneval")
252+
})
253+
ipar <- ggiraph_get_default_ipar(extra_interactive_params)
254+
if (index > 0 && ggiraph_has_interactive_attrs(args[[index]], ipar = ipar)) {
255+
interactive_mapping <- ggiraph_get_interactive_attrs(args[[index]],
256+
ipar = ipar)
257+
args[[index]] <- ggiraph_remove_interactive_attrs(args[[index]],
258+
ipar = ipar)
259+
}
260+
if (ggiraph_has_interactive_attrs(args, ipar = ipar)) {
261+
interactive_params <- ggiraph_get_interactive_attrs(args, ipar = ipar)
262+
args <- ggiraph_remove_interactive_attrs(args, ipar = ipar)
263+
}
264+
result <- do.call(layer_func, args)
265+
layer_ <- NULL
266+
if (is.list(result)) {
267+
index <- purrr::detect_index(result, function(x) {
268+
inherits(x, "LayerInstance")
269+
})
270+
if (index > 0) {
271+
layer_ <- result[[index]]
272+
}
273+
}
274+
else if (inherits(result, "LayerInstance")) {
275+
layer_ <- result
276+
}
277+
if (!is.null(layer_)) {
278+
if (is.null(interactive_geom)) {
279+
interactive_geom <- ggiraph_find_interactive_class(layer_$geom)
280+
}
281+
layer_$geom <- interactive_geom
282+
if (!is.null(interactive_mapping)) {
283+
layer_$mapping <- ggiraph_append_aes(layer_$mapping, interactive_mapping)
284+
}
285+
if (!is.null(interactive_params)) {
286+
layer_$aes_params <- append(layer_$aes_params, interactive_params)
287+
}
288+
layer_$geom_params <- append(layer_$geom_params, list(.ipar = ipar))
289+
default_aes_names <- names(layer_$geom$default_aes)
290+
missing_names <- setdiff(ipar, default_aes_names)
291+
if (length(missing_names) > 0) {
292+
defaults <- Map(missing_names, f = function(x) NULL)
293+
layer_$geom$default_aes <- ggiraph_append_aes(layer_$geom$default_aes,
294+
defaults)
295+
}
296+
if (is.list(result)) {
297+
result[[index]] <- layer_
298+
}
299+
else {
300+
result <- layer_
301+
}
302+
}
303+
result
304+
}
305+
306+
ggiraph_get_ineteractive_attrs <-
307+
function (x = rlang::caller_env(), ipar = ggiraph_IPAR_NAMES)
308+
{
309+
if (is.environment(x)) {
310+
rlang::env_get_list(env = x, ipar, NULL)
311+
}
312+
else {
313+
if (!is.null(attr(x, "interactive"))) {
314+
x <- attr(x, "interactive")
315+
}
316+
x[ggiraph_get_interactive_attr_names(x, ipar = ipar)]
317+
}
318+
}
319+
320+
ggiraph_get_default_ipar <-
321+
function (extra_names = NULL)
322+
{
323+
if (is.character(extra_names) && length(extra_names) > 0) {
324+
extra_names <- Filter(x = extra_names, function(x) {
325+
!is.na(x) && nzchar(trimws(x))
326+
})
327+
}
328+
unique(c(ggiraph_IPAR_NAMES, extra_names))
329+
}
330+
331+
ggiraph_get_interactive_attrs <-
332+
function (x = rlang::caller_env(), ipar = ggiraph_IPAR_NAMES)
333+
{
334+
if (is.environment(x)) {
335+
rlang::env_get_list(env = x, ipar, NULL)
336+
}
337+
else {
338+
if (!is.null(attr(x, "interactive"))) {
339+
x <- attr(x, "interactive")
340+
}
341+
x[ggiraph_get_interactive_attr_names(x, ipar = ipar)]
342+
}
343+
}
344+
345+
ggiraph_get_interactive_attr_names <-
346+
function (x, ipar = ggiraph_IPAR_NAMES)
347+
{
348+
intersect(names(x), ipar)
349+
}
350+
351+
ggiraph_remove_interactive_attrs <-
352+
function (x, ipar = ggiraph_IPAR_NAMES)
353+
{
354+
for (a in ipar) {
355+
x[[a]] <- NULL
356+
}
357+
x
358+
}
359+
360+
ggiraph_find_interactive_class <-
361+
function (gg, baseclass = c("Geom", "Guide"), env = parent.frame())
362+
{
363+
baseclass <- rlang::arg_match(baseclass)
364+
if (inherits(gg, baseclass)) {
365+
name <- class(gg)[1]
366+
}
367+
else if (is.character(gg) && length(gg) == 1) {
368+
name <- gg
369+
if (name == "histogram") {
370+
name <- "bar"
371+
}
372+
}
373+
else {
374+
rlang::abort(paste0("`gg` must be either a string or a ", baseclass,
375+
"* object, not ", obj_desc(gg)), call = NULL)
376+
}
377+
if (!startsWith(name, baseclass)) {
378+
name <- paste0(baseclass, camelize(name, first = TRUE))
379+
}
380+
baseinteractive <- paste0(baseclass, "Interactive")
381+
if (!startsWith(name, baseinteractive)) {
382+
name <- sub(baseclass, baseinteractive, name)
383+
}
384+
obj <- find_global(name, env = env)
385+
if (is.null(obj) || !inherits(obj, baseclass)) {
386+
rlang::abort(paste0("Can't find interactive ", baseclass, " function based on ",
387+
as_label(gg)), call = NULL)
388+
}
389+
else {
390+
obj
391+
}
392+
}
393+
394+
ggiraph_has_interactive_attrs <-
395+
function (x, ipar = ggiraph_IPAR_NAMES)
396+
{
397+
length(intersect(names(x), ipar)) > 0
398+
}
399+
400+
ggiraph_append_aes <-
401+
function (mapping, lst)
402+
{
403+
mapping[names(lst)] <- lst
404+
mapping
405+
}
406+
407+
ggiraph_IPAR_NAMES <-
408+
c(
409+
"data_id", "tooltip", "onclick", "hover_css", "selected_css",
410+
"tooltip_fill", "hover_nearest")
411+
412+
413+
###############################################################################

R/layer_factory.R

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,23 +14,6 @@ utils::globalVariables("role")
1414
#'
1515
NA
1616

17-
layer_interactive <- function(
18-
layer_func, stat = NULL, position = NULL, ...,
19-
interactive_geom = NULL, extra_interactive_params = NULL) {
20-
21-
dots <- list(...)
22-
if (is.null(position)) {
23-
ggiraph:::layer_interactive(
24-
layer_func, stat = stat, ...,
25-
interactive_geom = interactive_geom, extra_interactive_params = extra_interactive_params
26-
)
27-
} else {
28-
ggiraph:::layer_interactive(
29-
layer_func, stat = stat, position = position, ...,
30-
interactive_geom = interactive_geom, extra_interactive_params = extra_interactive_params
31-
)
32-
}
33-
}
3417

3518
#' Create a ggformula layer function
3619
#'
@@ -122,7 +105,7 @@ layer_factory <-
122105
environment = parent.frame(),
123106
...
124107
) {
125-
# pre will be placed in the function environment so it is available here
108+
# pre and will be placed in the function environment so available here
126109
eval(pre)
127110

128111
# evaluate quosures

cran-comments.md

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,6 @@ This release
55
* addresses issues caused by the update of {ggplot2}
66
* adds interactive features based on {ggiraph}, which has also been updated subsequent to {ggplot2}.
77

8-
I am aware of the use of ::: to access ggiraph:::layer_interactive().
9-
I have a request out for that function to be exported by the package.
10-
I'm hoping that will happen soonish. If it does not, I'll likely just copy
11-
the function into {ggformula}, but I'd rather not do that if it can be
12-
avoided.
13-
148
## Test environments
159

1610
* local

0 commit comments

Comments
 (0)