Skip to content
Open
Show file tree
Hide file tree
Changes from all 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