Skip to content

Commit 5fea610

Browse files
authored
Old S3 guide wrapper (#5319)
* S3 guide necromancy * Wrap old guide system in ggproto * Validate old guides * Add test for old S3 guides * Add NEWS bullet
1 parent 98f04aa commit 5fea610

File tree

10 files changed

+330
-14
lines changed

10 files changed

+330
-14
lines changed

DESCRIPTION

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ Collate:
181181
'guide-colorsteps.R'
182182
'layer.R'
183183
'guide-none.R'
184+
'guide-old.R'
184185
'guides-.R'
185186
'guides-grid.R'
186187
'hexbin.R'

NAMESPACE

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,11 @@ S3method(grobWidth,absoluteGrob)
7575
S3method(grobWidth,zeroGrob)
7676
S3method(grobX,absoluteGrob)
7777
S3method(grobY,absoluteGrob)
78+
S3method(guide_gengrob,default)
79+
S3method(guide_geom,default)
80+
S3method(guide_merge,default)
81+
S3method(guide_train,default)
82+
S3method(guide_transform,default)
7883
S3method(heightDetails,titleGrob)
7984
S3method(heightDetails,zeroGrob)
8085
S3method(interleave,default)
@@ -211,6 +216,7 @@ export(GuideColourbar)
211216
export(GuideColoursteps)
212217
export(GuideLegend)
213218
export(GuideNone)
219+
export(GuideOld)
214220
export(Layout)
215221
export(Position)
216222
export(PositionDodge)
@@ -416,8 +422,13 @@ export(guide_colorbar)
416422
export(guide_colorsteps)
417423
export(guide_colourbar)
418424
export(guide_coloursteps)
425+
export(guide_gengrob)
426+
export(guide_geom)
419427
export(guide_legend)
428+
export(guide_merge)
420429
export(guide_none)
430+
export(guide_train)
431+
export(guide_transform)
421432
export(guides)
422433
export(has_flipped_aes)
423434
export(is.Coord)
@@ -451,6 +462,7 @@ export(mean_se)
451462
export(median_hilow)
452463
export(merge_element)
453464
export(new_guide)
465+
export(old_guide)
454466
export(panel_cols)
455467
export(panel_rows)
456468
export(position_dodge)

NEWS.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,13 @@
2727
in ggproto. The axes and legends now inherit from a <Guide> class, which makes
2828
them extensible in the same manner as geoms, stats, facets and coords
2929
(#3329, @teunbrand). In addition, the following changes were made:
30+
* A fallback for old S3 guides is encapsulated in the `GuideOld` ggproto
31+
class, which mostly just calls the old S3 generics.
32+
* While the S3 guide generics are still in place, the S3 methods for
33+
`guide_train()`, `guide_merge()`, `guide_geom()`, `guide_transform()`,
34+
`guide_gengrob()` have been superseded by the respective ggproto methods.
35+
In practise, this will mean that `NextMethod()` or sub-classing ggplot2's
36+
guides with the S3 system will no longer work.
3037
* Styling theme parts of the guide now inherit from the plot's theme
3138
(#2728).
3239
* Styling non-theme parts of the guides accept <element> objects, so that

R/guide-old.R

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
2+
#' The previous S3 guide system
3+
#'
4+
#' The guide system has been overhauled to use the ggproto infrastructure to
5+
#' accommodate guide extensions with the same flexibility as layers, scales and
6+
#' other ggplot2 objects. In rewriting, the old S3 system has become defunct,
7+
#' meaning that the previous methods for guides have been superseded by ggproto
8+
#' methods. As a fallback option, the generics, but not the methods, that the
9+
#' previous S3 system used are encapsulated in the `GuideOld` ggproto class.
10+
#'
11+
#' @param guide An old guide object
12+
#' @keywords internal
13+
#' @name old_guide
14+
15+
#' @export
16+
#' @rdname old_guide
17+
guide_train <- function(guide, scale, aesthetic = NULL) {
18+
UseMethod("guide_train")
19+
}
20+
21+
#' @export
22+
guide_train.default <- function(guide, ...) {
23+
cli::cli_abort(c(
24+
"{.cls Guide} classes have been rewritten as {.cls ggproto} classes.",
25+
"The old S3 guide methods have been superseded."
26+
))
27+
}
28+
29+
#' @export
30+
#' @rdname old_guide
31+
guide_merge <- function(guide, new_guide) {
32+
UseMethod("guide_merge")
33+
}
34+
35+
#' @export
36+
guide_merge.default <- guide_train.default
37+
38+
#' @export
39+
#' @rdname old_guide
40+
guide_geom <- function(guide, layers, default_mapping = NULL) {
41+
UseMethod("guide_geom")
42+
}
43+
44+
#' @export
45+
guide_geom.default <- guide_train.default
46+
47+
#' @export
48+
#' @rdname old_guide
49+
guide_transform <- function(guide, coord, panel_params) {
50+
UseMethod("guide_transform")
51+
}
52+
53+
#' @export
54+
guide_transform.default <- guide_train.default
55+
56+
#' @export
57+
#' @rdname old_guide
58+
guide_gengrob <- function(guide, theme) {
59+
UseMethod("guide_gengrob")
60+
}
61+
62+
#' @export
63+
guide_gengrob.default <- guide_train.default
64+
65+
#' @export
66+
#' @rdname old_guide
67+
old_guide <- function(guide) {
68+
deprecate_warn0(
69+
when = "3.5.0",
70+
what = I("The S3 guide system"),
71+
details = c(
72+
i = "It has been replaced by a ggproto system that can be extended."
73+
)
74+
)
75+
76+
ggproto(
77+
NULL, GuideOld,
78+
params = guide,
79+
available_aes = guide$available_aes %||% NULL
80+
)
81+
}
82+
83+
#' @rdname ggplot2-ggproto
84+
#' @format NULL
85+
#' @usage NULL
86+
#' @export
87+
GuideOld <- ggproto(
88+
"GuideOld", Guide,
89+
90+
train = function(self, params, scale, aesthetic = NULL,
91+
title = NULL, direction = NULL) {
92+
params <- guide_train(params, scale, aesthetic)
93+
params$title <- params$title %|W|% title
94+
params$direction <- params$direction %||% direction
95+
params
96+
},
97+
98+
merge = function(self, params, new_guide, new_params) {
99+
guide_merge(params, new_params)
100+
},
101+
102+
transform = function(self, params, coord, panel_params, ...) {
103+
guide_transform(params, coord, panel_params)
104+
},
105+
106+
get_layer_key = function(params, layers) {
107+
guide_geom(params, layers, default_mapping = NULL)
108+
},
109+
110+
draw = function(self, theme, params) {
111+
params$title.position <- params$title.position %||% switch(
112+
params$direction %||% "placeholder",
113+
vertical = "top", horizontal = "left",
114+
NULL
115+
)
116+
guide_gengrob(params, theme)
117+
}
118+
)
119+

R/guides-.R

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -635,8 +635,10 @@ validate_guide <- function(guide) {
635635
}
636636
}
637637
if (inherits(guide, "Guide")) {
638-
guide
639-
} else {
640-
cli::cli_abort("Unknown guide: {guide}")
638+
return(guide)
639+
}
640+
if (inherits(guide, "guide") && is.list(guide)) {
641+
return(old_guide(guide))
641642
}
643+
cli::cli_abort("Unknown guide: {guide}")
642644
}

man/ggplot2-ggproto.Rd

Lines changed: 12 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/old_guide.Rd

Lines changed: 35 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/_snaps/guides.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,8 @@
8080
The `guide` argument in `scale_*()` cannot be `FALSE`. This was deprecated in ggplot2 3.3.4.
8181
i Please use "none" instead.
8282

83+
# old S3 guides can be implemented
84+
85+
The S3 guide system was deprecated in ggplot2 3.5.0.
86+
i It has been replaced by a ggproto system that can be extended.
87+
Lines changed: 81 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)