Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
legend glyphs (@teunbrand, #6594)
* Fixed regression where `NULL`-aesthetics contributed to plot labels too
insistently. Now they contribute only as fallback labels (@teunbrand, #6616)
* The `theme(panel.widths, panel.heights)` setting attempts to preserve the
plot's aspect ratio when only one of the two settings is given, and the plot
has a single panel (@teunbrand, #6701).

# ggplot2 4.0.0

Expand Down
24 changes: 15 additions & 9 deletions R/facet-.R
Original file line number Diff line number Diff line change
Expand Up @@ -731,18 +731,24 @@ Facet <- ggproto("Facet", NULL,
return(table)
}

if (isTRUE(table$respect)) {
args <- !c(is.null(new_widths), is.null(new_heights))
args <- c("panel.widths", "panel.heights")[args]
cli::cli_warn(
"Aspect ratios are overruled by {.arg {args}} theme element{?s}."
)
table$respect <- FALSE
}

rows <- panel_rows(table)
cols <- panel_cols(table)

if (isTRUE(table$respect) && # Has fixed aspect ratio
xor(is.null(new_widths), is.null(new_heights)) && # One dimension is set
nrow(rows) == 1 && nrow(cols) == 1) { # Just a single panel
old_width <- table$widths[cols$l]
old_height <- table$heights[rows$t]
# Try to reconstruct aspect ratio from panel size
# We shouldn't attempt this with mixed or compound (e.g. "sum") units
if (identical(unitType(old_width), "null") &&
identical(unitType(old_height), "null")) {
ratio <- as.numeric(old_height) / as.numeric(old_width)
new_widths <- (new_widths %||% (new_heights / ratio))[1]
new_heights <- (new_heights %||% (new_widths * ratio))[1]
}
}

if (length(new_widths) == 1L && nrow(cols) > 1L) {
# Get total size of non-panel widths in between panels
extra <- setdiff(seq(min(cols$l), max(cols$r)), union(cols$l, cols$r))
Expand Down
5 changes: 4 additions & 1 deletion R/theme.R
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,10 @@
#' from `line`
#' @param panel.widths,panel.heights Sizes for panels (`units`). Can be a
#' single unit to set the total size for the panel area, or a unit vector to
#' set the size of individual panels.
#' set the size of individual panels. Using this setting overrides the
#' aspect ratio set by the theme, coord or facets. An exception is made when
#' the plot has a single panel and exactly one of the width *or* height is
#' set, in which case an attempt is made to preserve the aspect ratio.
#' @param panel.ontop option to place the panel (background, gridlines) over
#' the data layers (`logical`). Usually used with a transparent or blank
#' `panel.background`.
Expand Down
5 changes: 4 additions & 1 deletion man/theme.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 28 additions & 5 deletions tests/testthat/test-theme.R
Original file line number Diff line number Diff line change
Expand Up @@ -717,11 +717,34 @@ test_that("panel.widths and panel.heights works with free-space panels", {

})

test_that("panel.widths and panel.heights appropriately warn about aspect override", {
p <- ggplot(mpg, aes(displ, hwy)) +
geom_point() +
theme(aspect.ratio = 1, panel.widths = unit(4, "cm"))
expect_warning(ggplotGrob(p), "Aspect ratios are overruled")
test_that("panel.withs and panel.heights preserve aspect ratios with single panels", {

df <- data.frame(x = c(1, 2))

p <- ggplotGrob(
ggplot(df, aes(x, x)) +
geom_point() +
theme(
aspect.ratio = 2,
panel.heights = unit(10, "cm")
)
)

width <- p$widths[panel_cols(p)$l]
expect_equal(as.character(width), "5cm")

p <- ggplotGrob(
ggplot(df, aes(x, x)) +
geom_point() +
facet_wrap(~ x) + # This behaviour doesn't occur in multipanel plots.
theme(
aspect.ratio = 2,
panel.heights = unit(10, "cm")
)
)

width <- p$widths[panel_cols(p)$l]
expect_equal(as.character(width), c("1null", "1null"))
})

test_that("margin_part() mechanics work as expected", {
Expand Down