Skip to content

Commit 9fdf452

Browse files
authored
Clean up strip rendering code (#3683)
1 parent a56abd3 commit 9fdf452

File tree

7 files changed

+288
-183
lines changed

7 files changed

+288
-183
lines changed

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ matrix:
99
env: _R_CHECK_SYSTEM_CLOCK_=false
1010
- r: release
1111
env: VDIFFR_RUN_TESTS=true
12+
env: VDIFFR_LOG_PATH="../vdiffr.Rout.fail"
1213
before_cache:
1314
- Rscript -e 'remotes::install_cran("pkgdown")'
1415
- Rscript -e 'remotes::install_github("tidyverse/tidytemplate")'

R/labeller.r

Lines changed: 47 additions & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -496,68 +496,35 @@ build_strip <- function(label_df, labeller, theme, horizontal) {
496496
})
497497
}
498498

499-
text_theme <- if (horizontal) "strip.text.x" else "strip.text.y"
500-
501-
element <- calc_element(text_theme, theme)
502-
503-
if (inherits(element, "element_blank")) {
504-
grobs <- rep(list(zeroGrob()), nrow(label_df))
505-
return(structure(
506-
list(grobs, grobs),
507-
names = if (horizontal) c('top', 'bottom') else c('left', 'right')
508-
))
509-
}
510-
511499
# Create matrix of labels
512500
labels <- lapply(labeller(label_df), cbind)
513501
labels <- do.call("cbind", labels)
514502

515-
gp <- gpar(
516-
fontsize = element$size,
517-
col = element$colour,
518-
fontfamily = element$family,
519-
fontface = element$face,
520-
lineheight = element$lineheight
521-
)
522-
523503
if (horizontal) {
504+
grobs_top <- lapply(labels, element_render, theme = theme,
505+
element = "strip.text.x.top", margin_x = TRUE,
506+
margin_y = TRUE)
507+
grobs_top <- assemble_strips(grobs_top, theme, horizontal, clip = "on")
524508

525-
grobs <- create_strip_labels(labels, element, gp)
526-
grobs <- ggstrip(grobs, theme, element, gp, horizontal, clip = "on")
509+
grobs_bottom <- lapply(labels, element_render, theme = theme,
510+
element = "strip.text.x.bottom", margin_x = TRUE,
511+
margin_y = TRUE)
512+
grobs_bottom <- assemble_strips(grobs_bottom, theme, horizontal, clip = "on")
527513

528514
list(
529-
top = grobs,
530-
bottom = grobs
515+
top = grobs_top,
516+
bottom = grobs_bottom
531517
)
532518
} else {
519+
grobs_left <- lapply(labels, element_render, theme = theme,
520+
element = "strip.text.y.left", margin_x = TRUE,
521+
margin_y = TRUE)
522+
grobs_left <- assemble_strips(grobs_left, theme, horizontal, clip = "on")
533523

534-
grobs <- create_strip_labels(labels, element, gp)
535-
grobs_right <- grobs[, rev(seq_len(ncol(grobs))), drop = FALSE]
536-
537-
grobs_right <- ggstrip(
538-
grobs_right,
539-
theme,
540-
element,
541-
gp,
542-
horizontal,
543-
clip = "on"
544-
)
545-
546-
# Change angle of strip labels for y strips that are placed on the left side
547-
if (inherits(element, "element_text")) {
548-
element$angle <- adjust_angle(element$angle)
549-
}
550-
551-
grobs_left <- create_strip_labels(labels, element, gp)
552-
553-
grobs_left <- ggstrip(
554-
grobs_left,
555-
theme,
556-
element,
557-
gp,
558-
horizontal,
559-
clip = "on"
560-
)
524+
grobs_right <- lapply(labels, element_render, theme = theme,
525+
element = "strip.text.y.right", margin_x = TRUE,
526+
margin_y = TRUE)
527+
grobs_right <- assemble_strips(grobs_right, theme, horizontal, clip = "on")
561528

562529
list(
563530
left = grobs_left,
@@ -566,126 +533,57 @@ build_strip <- function(label_df, labeller, theme, horizontal) {
566533
}
567534
}
568535

569-
#' Create list of strip labels
570-
#'
571-
#' Calls [title_spec()] on all the labels for a set of strips to create a list
572-
#' of text grobs, heights, and widths.
573-
#'
574-
#' @param labels Matrix of strip labels
575-
#' @param element Theme element (see [calc_element()]).
576-
#' @param gp Additional graphical parameters.
577-
#'
578-
#' @noRd
579-
create_strip_labels <- function(labels, element, gp) {
580-
grobs <- lapply(labels, title_spec,
581-
x = NULL,
582-
y = NULL,
583-
hjust = element$hjust,
584-
vjust = element$vjust,
585-
angle = element$angle,
586-
gp = gp,
587-
debug = element$debug
588-
)
589-
dim(grobs) <- dim(labels)
590-
grobs
591-
}
592-
593536
#' Grob for strip labels
594537
#'
595538
#' Takes the output from title_spec, adds margins, creates gList with strip
596539
#' background and label, and returns gtable matrix.
597540
#'
598-
#' @param grobs Output from [title_spec()].
541+
#' @param grobs Output from [titleGrob()].
599542
#' @param theme Theme object.
600-
#' @param element Theme element (see [calc_element()]).
601-
#' @param gp Additional graphical parameters.
602543
#' @param horizontal Whether the strips are horizontal (e.g. x facets) or not.
603544
#' @param clip should drawing be clipped to the specified cells (‘"on"’),the
604545
#' entire table (‘"inherit"’), or not at all (‘"off"’).
605546
#'
606547
#' @noRd
607-
ggstrip <- function(grobs, theme, element, gp, horizontal = TRUE, clip) {
548+
assemble_strips <- function(grobs, theme, horizontal = TRUE, clip) {
549+
if (length(grobs) == 0 || is.zero(grobs[[1]])) return(grobs)
550+
551+
# Add margins to non-titleGrobs so they behave eqivalently
552+
grobs <- lapply(grobs, function(g) {
553+
if (inherits(g, "titleGrob")) return(g)
554+
add_margins(gList(g), grobHeight(g), grobWidth(g), margin_x = TRUE, margin_y = TRUE)
555+
})
608556

609557
if (horizontal) {
610-
height <- max_height(lapply(grobs, function(x) x$text_height))
558+
height <- max_height(lapply(grobs, function(x) x$heights[2]))
611559
width <- unit(1, "null")
612560
} else {
613561
height <- unit(1, "null")
614-
width <- max_width(lapply(grobs, function(x) x$text_width))
562+
width <- max_width(lapply(grobs, function(x) x$widths[2]))
615563
}
616-
617-
# Add margins around text grob
618-
grobs <- apply(
619-
grobs,
620-
c(1, 2),
621-
function(x) {
622-
add_margins(
623-
grob = x[[1]]$text_grob,
624-
height = height,
625-
width = width,
626-
gp = gp,
627-
margin = element$margin,
628-
margin_x = TRUE,
629-
margin_y = TRUE
630-
)
631-
}
632-
)
633-
634-
background <- if (horizontal) "strip.background.x" else "strip.background.y"
635-
636-
# Put text on a strip
637-
grobs <- apply(
638-
grobs,
639-
c(1, 2),
640-
function(label) {
641-
ggname(
642-
"strip",
643-
gTree(
644-
children = gList(
645-
element_render(theme, background),
646-
label[[1]]
647-
)
648-
)
649-
)
650-
})
651-
564+
grobs <- lapply(grobs, function(x) {
565+
# Avoid unit subset assignment to support R 3.2
566+
x$widths <- unit.c(x$widths[1], width, x$widths[c(-1, -2)])
567+
x$heights <- unit.c(x$heights[1], height, x$heights[c(-1, -2)])
568+
x$vp$parent$layout$widths <- unit.c(x$vp$parent$layout$widths[1], width, x$vp$parent$layout$widths[c(-1, -2)])
569+
x$vp$parent$layout$heights <- unit.c(x$vp$parent$layout$heights[1], height, x$vp$parent$layout$heights[c(-1, -2)])
570+
x
571+
})
652572
if (horizontal) {
653-
height <- height + sum(element$margin[c(1, 3)])
573+
height <- sum(grobs[[1]]$heights)
654574
} else {
655-
width <- width + sum(element$margin[c(2, 4)])
575+
width <- sum(grobs[[1]]$widths)
656576
}
657577

578+
background <- if (horizontal) "strip.background.x" else "strip.background.y"
579+
background <- element_render(theme, background)
658580

659-
apply(
660-
grobs,
661-
1,
662-
function(x) {
663-
if (horizontal) {
664-
mat <- matrix(x, ncol = 1)
665-
} else {
666-
mat <- matrix(x, nrow = 1)
667-
}
668-
669-
gtable_matrix(
670-
"strip",
671-
mat,
672-
rep(width, ncol(mat)),
673-
rep(height, nrow(mat)),
674-
clip = clip
675-
)
676-
})
677-
678-
}
679-
680-
# Helper to adjust angle of switched strips
681-
adjust_angle <- function(angle) {
682-
if (is.null(angle)) {
683-
-90
684-
} else if ((angle + 180) > 360) {
685-
angle - 180
686-
} else {
687-
angle + 180
688-
}
581+
# Put text on a strip
582+
lapply(grobs, function(x) {
583+
strip <- ggname("strip", gTree(children = gList(background, x)))
584+
strip_table <- gtable(width, height, name = "strip")
585+
gtable_add_grob(strip_table, strip, 1, 1, clip = clip)
586+
})
689587
}
690588

691589
# Check for old school labeller

R/margins.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ title_spec <- function(label, x, y, hjust, vjust, angle, gp = gpar(),
9696
#' Given a text grob, `add_margins()` adds margins around the grob in the
9797
#' directions determined by `margin_x` and `margin_y`.
9898
#'
99-
#' @param grob Text grob to add margins to.
99+
#' @param grob A gList containing a grob, such as a text grob
100100
#' @param height,width Usually the height and width of the text grob. Passed as
101101
#' separate arguments from the grob itself because in the special case of
102102
#' facet strip labels each set of strips should share the same height and

R/theme-defaults.r

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ theme_grey <- function(base_size = 11, base_family = "",
202202
),
203203
strip.text.x = NULL,
204204
strip.text.y = element_text(angle = -90),
205+
strip.text.y.left = element_text(angle = 90),
205206
strip.placement = "inside",
206207
strip.placement.x = NULL,
207208
strip.placement.y = NULL,

R/theme-elements.r

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,11 @@ el_def <- function(class = NULL, inherit = NULL, description = NULL) {
470470
strip.background.x = el_def("element_rect", "strip.background"),
471471
strip.background.y = el_def("element_rect", "strip.background"),
472472
strip.text.x = el_def("element_text", "strip.text"),
473+
strip.text.x.top = el_def("element_text", "strip.text.x"),
474+
strip.text.x.bottom = el_def("element_text", "strip.text.x"),
473475
strip.text.y = el_def("element_text", "strip.text"),
476+
strip.text.y.left = el_def("element_text", "strip.text.y"),
477+
strip.text.y.right = el_def("element_text", "strip.text.y"),
474478
strip.placement = el_def("character"),
475479
strip.placement.x = el_def("character", "strip.placement"),
476480
strip.placement.y = el_def("character", "strip.placement"),

0 commit comments

Comments
 (0)