Skip to content

Commit 25fa5f4

Browse files
teunbrandthomasp85
authored andcommitted
Guide custom theme (#5602)
* Apply #5554 to `guide_custom()` * build in early exit
1 parent ae8ed74 commit 25fa5f4

File tree

2 files changed

+76
-69
lines changed

2 files changed

+76
-69
lines changed

R/guide-custom.R

Lines changed: 70 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,6 @@
88
#' in [grid::unit()]s.
99
#' @param title A character string or expression indicating the title of guide.
1010
#' If `NULL` (default), no title is shown.
11-
#' @param title.position A character string indicating the position of a title.
12-
#' One of `"top"` (default), `"bottom"`, `"left"` or `"right"`.
13-
#' @param margin Margins around the guide. See [margin()] for more details. If
14-
#' `NULL` (default), margins are taken from the `legend.margin` theme setting.
15-
#' @param position Currently not in use.
1611
#' @inheritParams guide_legend
1712
#'
1813
#' @export
@@ -42,28 +37,25 @@
4237
#' ))
4338
guide_custom <- function(
4439
grob, width = grobWidth(grob), height = grobHeight(grob),
45-
title = NULL, title.position = "top", margin = NULL,
40+
title = NULL, theme = NULL,
4641
position = NULL, order = 0
4742
) {
4843
check_object(grob, is.grob, "a {.cls grob} object")
4944
check_object(width, is.unit, "a {.cls unit} object")
5045
check_object(height, is.unit, "a {.cls unit} object")
51-
check_object(margin, is.margin, "a {.cls margin} object", allow_null = TRUE)
5246
if (length(width) != 1) {
5347
cli::cli_abort("{.arg width} must be a single {.cls unit}, not a unit vector.")
5448
}
5549
if (length(height) != 1) {
5650
cli::cli_abort("{.arg height} must be a single {.cls unit}, not a unit vector.")
5751
}
58-
title.position <- arg_match0(title.position, .trbl)
5952

6053
new_guide(
6154
grob = grob,
6255
width = width,
6356
height = height,
6457
title = title,
65-
title.position = title.position,
66-
margin = margin,
58+
theme = theme,
6759
hash = hash(list(title, grob)), # hash is already known
6860
position = position,
6961
order = order,
@@ -79,19 +71,15 @@ guide_custom <- function(
7971
GuideCustom <- ggproto(
8072
"GuideCustom", Guide,
8173

82-
params = c(Guide$params, list(
83-
grob = NULL, width = NULL, height = NULL,
84-
margin = NULL,
85-
title = NULL,
86-
title.position = "top"
87-
)),
74+
params = c(Guide$params, list(grob = NULL, width = NULL, height = NULL)),
8875

8976
hashables = exprs(title, grob),
9077

9178
elements = list(
92-
background = "legend.background",
93-
theme.margin = "legend.margin",
94-
theme.title = "legend.title"
79+
background = "legend.background",
80+
margin = "legend.margin",
81+
title = "legend.title",
82+
title_position = "legend.title.position"
9583
),
9684

9785
train = function(...) {
@@ -102,72 +90,93 @@ GuideCustom <- ggproto(
10290
params
10391
},
10492

105-
override_elements = function(params, elements, theme) {
106-
elements$title <- elements$theme.title
107-
elements$margin <- params$margin %||% elements$theme.margin
108-
elements
93+
setup_elements = function(params, elements, theme) {
94+
theme <- add_theme(theme, params$theme)
95+
title_position <- theme$legend.title.position %||% switch(
96+
params$direction, vertical = "top", horizontal = "left"
97+
)
98+
title_position <- arg_match0(
99+
title_position, .trbl, arg_nm = "legend.title.position"
100+
)
101+
theme$legend.title.position <- title_position
102+
theme$legend.key.spacing <- theme$legend.key.spacing %||% unit(5.5, "pt")
103+
gap <- calc_element("legend.key.spacing", theme)
104+
105+
margin <- calc_element("text", theme)$margin
106+
title <- theme(text = element_text(
107+
hjust = 0, vjust = 0.5,
108+
margin = position_margin(title_position, margin, gap)
109+
))
110+
elements$title <- calc_element("legend.title", add_theme(theme, title))
111+
Guide$setup_elements(params, elements, theme)
109112
},
110113

111114
draw = function(self, theme, position = NULL, direction = NULL,
112115
params = self$params) {
113116

117+
if (is.zero(params$grob)) {
118+
return(zeroGrob())
119+
}
120+
114121
# Render title
122+
params$direction <- params$direction %||% direction
115123
elems <- self$setup_elements(params, self$elements, theme)
116124
elems <- self$override_elements(params, elems, theme)
117-
if (!is.waive(params$title) && !is.null(params$title)) {
118-
title <- self$build_title(params$title, elems, params)
119-
} else {
120-
title <- zeroGrob()
121-
}
122-
title.position <- params$title.position
123-
if (is.zero(title)) {
124-
title.position <- "none"
125-
}
126125

126+
# Start with putting the main grob in a gtable
127127
width <- convertWidth(params$width, "cm", valueOnly = TRUE)
128128
height <- convertHeight(params$height, "cm", valueOnly = TRUE)
129129
gt <- gtable(widths = unit(width, "cm"), heights = unit(height, "cm"))
130130
gt <- gtable_add_grob(gt, params$grob, t = 1, l = 1, clip = "off")
131131

132-
extra_width <- max(0, width_cm(title) - width)
133-
extra_height <- max(0, height_cm(title) - height)
134-
just <- with(elems$title, rotate_just(angle, hjust, vjust))
135-
hjust <- just$hjust
136-
vjust <- just$vjust
137-
138-
if (params$title.position == "top") {
139-
gt <- gtable_add_rows(gt, elems$margin[1], pos = 0)
140-
gt <- gtable_add_rows(gt, unit(height_cm(title), "cm"), pos = 0)
141-
gt <- gtable_add_grob(gt, title, t = 1, l = 1, name = "title", clip = "off")
142-
} else if (params$title.position == "bottom") {
143-
gt <- gtable_add_rows(gt, elems$margin[3], pos = -1)
144-
gt <- gtable_add_rows(gt, unit(height_cm(title), "cm"), pos = -1)
145-
gt <- gtable_add_grob(gt, title, t = -1, l = 1, name = "title", clip = "off")
146-
} else if (params$title.position == "left") {
147-
gt <- gtable_add_cols(gt, elems$margin[4], pos = 0)
148-
gt <- gtable_add_cols(gt, unit(width_cm(title), "cm"), pos = 0)
149-
gt <- gtable_add_grob(gt, title, t = 1, l = 1, name = "title", clip = "off")
150-
} else if (params$title.position == "right") {
151-
gt <- gtable_add_cols(gt, elems$margin[2], pos = -1)
152-
gt <- gtable_add_cols(gt, unit(width_cm(title), "cm"), pos = 0)
153-
gt <- gtable_add_grob(gt, title, t = 1, l = -1, name = "title", clip = "off")
154-
}
155-
if (params$title.position %in% c("top", "bottom")) {
156-
gt <- gtable_add_cols(gt, unit(extra_width * hjust, "cm"), pos = 0)
157-
gt <- gtable_add_cols(gt, unit(extra_width * (1 - hjust), "cm"), pos = -1)
132+
# Render title
133+
if (!is.waive(params$title) && !is.null(params$title)) {
134+
title <- self$build_title(params$title, elems, params)
158135
} else {
159-
gt <- gtable_add_rows(gt, unit(extra_height * (1 - vjust), "cm"), pos = 0)
160-
gt <- gtable_add_rows(gt, unit(extra_height * vjust, "cm"), pos = -1)
136+
title <- zeroGrob()
161137
}
162138

163-
gt <- gtable_add_padding(gt, elems$margin)
139+
# Add title
140+
if (!is.zero(title)) {
141+
common_args <- list(name = "title", clip = "off", grobs = title)
142+
if (elems$title_position == "top") {
143+
gt <- gtable_add_rows(gt, unit(height_cm(title), "cm"), pos = 0)
144+
gt <- inject(gtable_add_grob(gt, t = 1, l = 1, !!!common_args))
145+
} else if (elems$title_position == "bottom") {
146+
gt <- gtable_add_rows(gt, unit(height_cm(title), "cm"), pos = -1)
147+
gt <- inject(gtable_add_grob(gt, t = -1, l = 1, !!!common_args))
148+
} else if (elems$title_position == "left") {
149+
gt <- gtable_add_cols(gt, unit(width_cm(title), "cm"), pos = 0)
150+
gt <- inject(gtable_add_grob(gt, t = 1, l = 1, !!!common_args))
151+
} else if (elems$title_position == "right") {
152+
gt <- gtable_add_cols(gt, unit(width_cm(title), "cm"), pos = -1)
153+
gt <- inject(gtable_add_grob(gt, t = 1, l = -1, !!!common_args))
154+
}
155+
156+
# Add extra space for large titles
157+
extra_width <- max(0, width_cm(title) - width)
158+
extra_height <- max(0, height_cm(title) - height)
159+
just <- with(elems$title, rotate_just(angle, hjust, vjust))
160+
hjust <- just$hjust
161+
vjust <- just$vjust
162+
if (elems$title_position %in% c("top", "bottom")) {
163+
gt <- gtable_add_cols(gt, unit(extra_width * hjust, "cm"), pos = 0)
164+
gt <- gtable_add_cols(gt, unit(extra_width * (1 - hjust), "cm"), pos = -1)
165+
} else {
166+
gt <- gtable_add_rows(gt, unit(extra_height * (1 - vjust), "cm"), pos = 0)
167+
gt <- gtable_add_rows(gt, unit(extra_height * vjust, "cm"), pos = -1)
168+
}
169+
}
164170

171+
# Add padding and background
172+
gt <- gtable_add_padding(gt, elems$margin)
165173
background <- element_grob(elems$background)
166174
gt <- gtable_add_grob(
167175
gt, background,
168176
t = 1, l = 1, r = -1, b = -1,
169177
z = -Inf, clip = "off"
170178
)
179+
171180
gt
172181
}
173182
)

man/guide_custom.Rd

Lines changed: 6 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)