Skip to content

Commit e14c856

Browse files
author
Yunuuuu
committed
feat: add resize argument to free_vp to control viewport resizing
1 parent c0474f9 commit e14c856

4 files changed

Lines changed: 64 additions & 34 deletions

File tree

R/alignpatch-free-vp.R

Lines changed: 47 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,38 @@
11
#' @inheritParams grid::viewport
22
#' @inheritDotParams grid::viewport -x -y -width -height
3+
#' @param resize A logical value. If `TRUE`, the viewport will be resized to
4+
#' accommodate the underlying gtable. This only applies when both the viewport
5+
#' width/height and the underlying gtable widths/heights are specified using
6+
#' absolute units. If `TRUE` and the viewport width/height is `NA`, the
7+
#' width/height will be set to match the gtable's widths/heights. Otherwise,
8+
#' the width/height will be set to `unit(1, "npc")`. See
9+
#' [`absolute.size()`][grid::absolute.size] for absolute unit.
310
#' @return
411
#' - `free_vp`: A modified version of `plot` with a `ggalign_free_vp` class.
512
#' @export
613
#' @rdname free
7-
free_vp <- function(plot, x = 0.5, y = 0.5, width = NA, height = NA, ...) {
14+
free_vp <- function(plot, x = 0.5, y = 0.5, width = NA, height = NA, ...,
15+
resize = TRUE) {
816
UseMethod("free_vp")
917
}
1018

1119
#' @importFrom grid viewport
1220
#' @export
1321
free_vp.default <- function(plot, x = 0.5, y = 0.5,
14-
width = NA, height = NA, ...) {
15-
attr(plot, "ggalign_free_vp") <- viewport(
16-
x = x, y = y, width = width, height = height, ...,
17-
)
22+
width = NA, height = NA, ...,
23+
resize = TRUE) {
24+
vp <- viewport(x = x, y = y, width = width, height = height, ..., )
25+
attr(plot, "ggalign_free_vp") <- list(vp = vp, resize = resize)
1826
add_class(plot, "ggalign_free_vp")
1927
}
2028

2129
#' @importFrom grid viewport
2230
#' @export
2331
free_vp.ggalign_free_vp <- function(plot, x = 0.5, y = 0.5,
24-
width = NA, height = NA, ...) {
25-
attr(plot, "ggalign_free_vp") <- viewport(
26-
x = x, y = y, width = width, height = height, ...,
27-
)
32+
width = NA, height = NA, ...,
33+
resize = TRUE) {
34+
vp <- viewport(x = x, y = y, width = width, height = height, ..., )
35+
attr(plot, "ggalign_free_vp") <- list(vp = vp, resize = resize)
2836
plot
2937
}
3038

@@ -40,23 +48,37 @@ patch.ggalign_free_vp <- function(x) {
4048
vp = attr(x, "ggalign_free_vp", exact = TRUE),
4149
place = function(self, gtable, gt, t, l, b, r, i, bg_z, plot_z) {
4250
if (is.grob(gt)) {
43-
vp <- self$vp
44-
45-
if (all(is_absolute_unit(widths <- .subset2(gt, "widths")))) {
46-
vp$width <- sum(widths)
47-
} else if (!is.na(as.numeric(vp$width))) {
48-
# we guess the width from the gtable
49-
vp$width <- max(vp$width, sum(widths))
50-
} else {
51-
vp$width <- unit(1, "npc")
52-
}
53-
if (all(is_absolute_unit(heights <- .subset2(gt, "heights")))) {
54-
vp$height <- sum(heights)
55-
} else if (!is.na(as.numeric(vp$height))) {
56-
# we guess the height from the gtable
57-
vp$height <- max(vp$height, sum(heights))
51+
vp <- self$vp$vp
52+
widths <- .subset2(gt, "widths")
53+
heights <- .subset2(gt, "heights")
54+
if (isTRUE(self$vp$resize)) {
55+
if (is.na(as.numeric(vp$width))) {
56+
# we guess the width from the gtable
57+
if (all(is_absolute_unit(widths))) {
58+
vp$width <- sum(widths)
59+
} else {
60+
vp$width <- unit(1, "npc")
61+
}
62+
} else if (is_absolute_unit(vp$width)) {
63+
vp$width <- max(vp$width, sum(widths))
64+
}
65+
if (is.na(as.numeric(vp$height))) {
66+
# we guess the height from the gtable
67+
if (all(is_absolute_unit(heights))) {
68+
vp$height <- sum(heights)
69+
} else {
70+
vp$height <- unit(1, "npc")
71+
}
72+
} else if (is_absolute_unit(vp$height)) {
73+
vp$height <- max(vp$height, sum(heights))
74+
}
5875
} else {
59-
vp$height <- unit(1, "npc")
76+
if (is.na(as.numeric(vp$width))) {
77+
vp$width <- unit(1, "npc")
78+
}
79+
if (is.na(as.numeric(vp$height))) {
80+
vp$height <- unit(1, "npc")
81+
}
6082
}
6183
gt <- editGrob(gt, vp = vp)
6284
}

R/layout-chain-stack-composer.R

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -120,13 +120,13 @@ stack_composer_add <- function(box, stack, composer, ...) {
120120
composer$align <- .subset2(composer, "align") + 1L
121121
}
122122
if (is_absolute_unit(size <- .subset2(sizes, "top"))) {
123-
attr(top, "ggalign_free_vp")$height <- size
123+
attr(top, "ggalign_free_vp")$vp$height <- size
124124
}
125125
composer <- stack_composer_add_plot(composer, top, t = 1L, l = l)
126126
}
127127
if (!is.null(bottom <- .subset2(plots, "bottom"))) {
128128
if (is_absolute_unit(size <- .subset2(sizes, "bottom"))) {
129-
attr(bottom, "ggalign_free_vp")$height <- size
129+
attr(bottom, "ggalign_free_vp")$vp$height <- size
130130
}
131131
composer <- stack_composer_add_plot(composer, bottom,
132132
t = .subset2(composer, "align") + 1L, l = l
@@ -160,13 +160,13 @@ stack_composer_add <- function(box, stack, composer, ...) {
160160
composer$align <- .subset2(composer, "align") + 1L
161161
}
162162
if (is_absolute_unit(size <- .subset2(sizes, "left"))) {
163-
attr(left, "ggalign_free_vp")$width <- size
163+
attr(left, "ggalign_free_vp")$vp$width <- size
164164
}
165165
composer <- stack_composer_add_plot(composer, left, t = t, l = 1L)
166166
}
167167
if (!is.null(right <- .subset2(plots, "right"))) {
168168
if (is_absolute_unit(size <- .subset2(sizes, "right"))) {
169-
attr(right, "ggalign_free_vp")$width <- size
169+
attr(right, "ggalign_free_vp")$vp$width <- size
170170
}
171171
composer <- stack_composer_add_plot(composer, right,
172172
t = t, l = .subset2(composer, "align") + 1L

man/free.Rd

Lines changed: 9 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/test-free-vp.R

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ test_that("free_vp() assigns class and viewport attribute", {
55

66
expect_s3_class(p_vp, "ggalign_free_vp")
77
expect_s3_class(p_vp, "ggplot")
8-
vp <- attr(p_vp, "ggalign_free_vp")
8+
vp <- attr(p_vp, "ggalign_free_vp")$vp
99
expect_true(inherits(vp, "viewport"))
1010
expect_equal(as.numeric(vp$x), 0.3)
1111
expect_equal(as.numeric(vp$y), 0.7)
@@ -20,16 +20,16 @@ test_that("free_space() works with alignpatch objects", {
2020
p_vp <- free_vp(p, x = 0.1, y = 0.9)
2121

2222
expect_s3_class(p_vp, "ggalign_free_vp")
23-
expect_equal(as.numeric(attr(p_vp, "ggalign_free_vp")$x), 0.1)
24-
expect_equal(as.numeric(attr(p_vp, "ggalign_free_vp")$y), 0.9)
23+
expect_equal(as.numeric(attr(p_vp, "ggalign_free_vp")$vp$x), 0.1)
24+
expect_equal(as.numeric(attr(p_vp, "ggalign_free_vp")$vp$y), 0.9)
2525
})
2626

2727
test_that("free_vp() uses defaults when width/height missing", {
2828
p <- ggplot2::ggplot(mtcars, ggplot2::aes(mpg, wt)) +
2929
ggplot2::geom_point()
3030
p_vp <- free_vp(p)
3131

32-
vp <- attr(p_vp, "ggalign_free_vp")
32+
vp <- attr(p_vp, "ggalign_free_vp")$vp
3333
expect_true(inherits(vp, "viewport"))
3434
expect_equal(as.numeric(vp$x), 0.5)
3535
expect_equal(as.numeric(vp$y), 0.5)

0 commit comments

Comments
 (0)