Skip to content

Commit d0891dc

Browse files
clauswilkehadley
authored andcommitted
Close issues #2573 & #2576 (#2577)
* add improved debugging mode for justify_grobs * closes #2576 * Make justify_grobs() respect internal angle of grobs. Closes #2573. * fix regression * add visual test * use trigonometry * Enable continuous rotation for all text labels, regardless of vjust/hjust setting * code clean-up
1 parent daba7ab commit d0891dc

17 files changed

+204
-50
lines changed

R/guide-colorbar.r

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -342,8 +342,7 @@ guide_gengrob.colorbar <- function(guide, theme) {
342342

343343
title_width <- width_cm(grob.title)
344344
title_height <- height_cm(grob.title)
345-
title_fontsize <- title.theme$size
346-
if (is.null(title_fontsize)) title_fontsize <- 0
345+
title_fontsize <- title.theme$size %||% calc_element("legend.title", theme)$size %||% 0
347346

348347
# gap between keys etc
349348
# the default horizontal and vertical gap need to be the same to avoid strange
@@ -527,7 +526,13 @@ guide_gengrob.colorbar <- function(guide, theme) {
527526
b = 1 + max(vps$label.row), l = 1 + min(vps$label.col))
528527
gt <- gtable_add_grob(
529528
gt,
530-
justify_grobs(grob.title, hjust = title.hjust, vjust = title.vjust, debug = title.theme$debug),
529+
justify_grobs(
530+
grob.title,
531+
hjust = title.hjust,
532+
vjust = title.vjust,
533+
int_angle = title.theme$angle,
534+
debug = title.theme$debug
535+
),
531536
name = "title",
532537
clip = "off",
533538
t = 1 + min(vps$title.row), r = 1 + max(vps$title.col),

R/guide-legend.r

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -345,8 +345,7 @@ guide_gengrob.legend <- function(guide, theme) {
345345

346346
title_width <- width_cm(grob.title)
347347
title_height <- height_cm(grob.title)
348-
title_fontsize <- title.theme$size
349-
if (is.null(title_fontsize)) title_fontsize <- 0
348+
title_fontsize <- title.theme$size %||% calc_element("legend.title", theme)$size %||% 0
350349

351350
# gap between keys etc
352351
# the default horizontal and vertical gap need to be the same to avoid strange
@@ -375,17 +374,15 @@ guide_gengrob.legend <- function(guide, theme) {
375374
if (is.null(guide$label.theme$vjust) && is.null(theme$legend.text$vjust)) label.theme$vjust <- NULL
376375

377376
# label.theme in param of guide_legend() > theme$legend.text.align > default
378-
hjust <- x <- guide$label.hjust %||% theme$legend.text.align %||% label.theme$hjust %||%
377+
hjust <- guide$label.hjust %||% theme$legend.text.align %||% label.theme$hjust %||%
379378
just_defaults$hjust
380-
vjust <- y <- guide$label.vjust %||% label.theme$vjust %||%
379+
vjust <- guide$label.vjust %||% label.theme$vjust %||%
381380
just_defaults$vjust
382381

383382
grob.labels <- lapply(guide$key$.label, function(label, ...) {
384383
g <- element_grob(
385384
element = label.theme,
386385
label = label,
387-
x = x,
388-
y = y,
389386
hjust = hjust,
390387
vjust = vjust,
391388
margin_x = TRUE,
@@ -694,7 +691,13 @@ guide_gengrob.legend <- function(guide, theme) {
694691
)
695692
gt <- gtable_add_grob(
696693
gt,
697-
justify_grobs(grob.title, hjust = title.hjust, vjust = title.vjust, debug = title.theme$debug),
694+
justify_grobs(
695+
grob.title,
696+
hjust = title.hjust,
697+
vjust = title.vjust,
698+
int_angle = title.theme$angle,
699+
debug = title.theme$debug
700+
),
698701
name = "title",
699702
clip = "off",
700703
t = 1 + min(vps.title.row),
@@ -714,7 +717,13 @@ guide_gengrob.legend <- function(guide, theme) {
714717
)
715718
gt <- gtable_add_grob(
716719
gt,
717-
justify_grobs(grob.labels, hjust = hjust, vjust = vjust, debug = label.theme$debug),
720+
justify_grobs(
721+
grob.labels,
722+
hjust = hjust,
723+
vjust = vjust,
724+
int_angle = label.theme$angle,
725+
debug = label.theme$debug
726+
),
718727
name = paste("label", vps$label.row, vps$label.col, sep = "-"),
719728
clip = "off",
720729
t = 1 + vps$label.row,

R/margins.R

Lines changed: 51 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -39,24 +39,13 @@ title_spec <- function(label, x, y, hjust, vjust, angle, gp = gpar(),
3939

4040
if (is.null(label)) return(zeroGrob())
4141

42-
angle <- angle %% 360
43-
if (0 <= angle & angle < 90) {
44-
xp <- hjust
45-
yp <- vjust
46-
} else if (90 <= angle & angle < 180) {
47-
xp <- 1 - vjust
48-
yp <- hjust
49-
} else if (180 <= angle & angle < 270) {
50-
xp <- 1 - hjust
51-
yp <- 1 - vjust
52-
} else if (270 <= angle & angle < 360) {
53-
xp <- vjust
54-
yp <- 1 - hjust
55-
}
42+
# We rotate the justifiation values to obtain the correct x and y reference point,
43+
# since hjust and vjust are applied relative to the rotated text frame in textGrob
44+
just <- rotate_just(angle, hjust, vjust)
5645

5746
n <- max(length(x), length(y), 1)
58-
x <- x %||% unit(rep(xp, n), "npc")
59-
y <- y %||% unit(rep(yp, n), "npc")
47+
x <- x %||% unit(rep(just$hjust, n), "npc")
48+
y <- y %||% unit(rep(just$vjust, n), "npc")
6049

6150
text_grob <- textGrob(
6251
label,
@@ -234,14 +223,18 @@ heightDetails.titleGrob <- function(x) {
234223
#' should be performed. If `NULL`, justification will be done relative to the
235224
#' enclosing drawing area (i.e., `x = hjust` and `y = vjust`).
236225
#' @param hjust,vjust Horizontal and vertical justification of the grob relative to `x` and `y`.
226+
#' @param int_angle Internal angle of the grob to be justified. When justifying a text
227+
#' grob with rotated text, this argument can be used to make `hjust` and `vjust` operate
228+
#' relative to the direction of the text.
237229
#' @param debug If `TRUE`, aids visual debugging by drawing a solid
238230
#' rectangle behind the complete grob area.
239231
#'
240232
#' @noRd
241-
justify_grobs <- function(grobs, x = NULL, y = NULL, hjust = 0.5, vjust = 0.5, debug = FALSE) {
233+
justify_grobs <- function(grobs, x = NULL, y = NULL, hjust = 0.5, vjust = 0.5,
234+
int_angle = 0, debug = FALSE) {
242235
if (!inherits(grobs, "grob")) {
243236
if (is.list(grobs)) {
244-
return(lapply(grobs, justify_grobs, x, y, hjust, vjust, debug))
237+
return(lapply(grobs, justify_grobs, x, y, hjust, vjust, int_angle, debug))
245238
}
246239
else {
247240
stop("need individual grob or list of grobs as argument.")
@@ -252,8 +245,12 @@ justify_grobs <- function(grobs, x = NULL, y = NULL, hjust = 0.5, vjust = 0.5, d
252245
return(grobs)
253246
}
254247

255-
x <- x %||% unit(hjust, "npc")
256-
y <- y %||% unit(vjust, "npc")
248+
# adjust hjust and vjust according to internal angle
249+
just <- rotate_just(int_angle, hjust, vjust)
250+
251+
x <- x %||% unit(just$hjust, "npc")
252+
y <- y %||% unit(just$vjust, "npc")
253+
257254

258255
if (isTRUE(debug)) {
259256
children <- gList(
@@ -265,14 +262,46 @@ justify_grobs <- function(grobs, x = NULL, y = NULL, hjust = 0.5, vjust = 0.5, d
265262
children = gList(grobs)
266263
}
267264

268-
gTree(
265+
266+
result_grob <- gTree(
269267
children = children,
270268
vp = viewport(
271269
x = x,
272270
y = y,
273271
width = grobWidth(grobs),
274272
height = grobHeight(grobs),
275-
just = c(hjust, vjust)
273+
just = unlist(just)
276274
)
277275
)
276+
277+
278+
if (isTRUE(debug)) {
279+
#cat("x, y:", c(x, y), "\n")
280+
#cat("E - hjust, vjust:", c(hjust, vjust), "\n")
281+
grobTree(
282+
result_grob,
283+
pointsGrob(x, y, pch = 20, gp = gpar(col = "mediumturquoise"))
284+
)
285+
} else {
286+
result_grob
287+
}
288+
}
289+
290+
291+
#' Rotate justification parameters counter-clockwise
292+
#'
293+
#' @param angle angle of rotation, in degrees
294+
#' @param hjust horizontal justification
295+
#' @param vjust vertical justification
296+
#' @return A list with two components, `hjust` and `vjust`, containing the rotated hjust and vjust values
297+
#'
298+
#' @noRd
299+
rotate_just <- function(angle, hjust, vjust) {
300+
# convert angle to radians
301+
rad <- (angle %||% 0) * pi / 180
302+
303+
hnew <- cos(rad) * hjust - sin(rad) * vjust + (1 - cos(rad) + sin(rad)) / 2
304+
vnew <- sin(rad) * hjust + cos(rad) * vjust + (1 - cos(rad) - sin(rad)) / 2
305+
306+
list(hjust = hnew, vjust = vnew)
278307
}

R/plot-build.r

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,7 @@ ggplot_gtable.ggplot_built <- function(data) {
287287
tag_parent <- justify_grobs(tag, x = xpos, y = ypos,
288288
hjust = theme$plot.tag$hjust,
289289
vjust = theme$plot.tag$vjust,
290+
int_angle = theme$plot.tag$angle,
290291
debug = theme$plot.tag$debug)
291292
plot_table <- gtable_add_grob(plot_table, tag_parent, name = "tag", t = 1,
292293
b = nrow(plot_table), l = 1,

tests/figs/coord-polar/secondary-axis-ticks-and-labels.svg

Lines changed: 1 addition & 1 deletion
Loading

tests/figs/facetting/left-justified-facet-labels-with-margins.svg

Lines changed: 2 additions & 2 deletions
Loading

tests/figs/geom-dotplot/facets-3-groups-histodot-stackgroups.svg

Lines changed: 3 additions & 3 deletions
Loading

tests/figs/guides/facet-grid-legend-on-bottom.svg

Lines changed: 1 addition & 1 deletion
Loading

tests/figs/guides/facet-grid-legend-on-left.svg

Lines changed: 1 addition & 1 deletion
Loading

tests/figs/guides/facet-grid-legend-on-right.svg

Lines changed: 1 addition & 1 deletion
Loading

0 commit comments

Comments
 (0)