8
8
# ' in [grid::unit()]s.
9
9
# ' @param title A character string or expression indicating the title of guide.
10
10
# ' 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.
16
11
# ' @inheritParams guide_legend
17
12
# '
18
13
# ' @export
42
37
# ' ))
43
38
guide_custom <- function (
44
39
grob , width = grobWidth(grob ), height = grobHeight(grob ),
45
- title = NULL , title.position = " top " , margin = NULL ,
40
+ title = NULL , theme = NULL ,
46
41
position = NULL , order = 0
47
42
) {
48
43
check_object(grob , is.grob , " a {.cls grob} object" )
49
44
check_object(width , is.unit , " a {.cls unit} object" )
50
45
check_object(height , is.unit , " a {.cls unit} object" )
51
- check_object(margin , is.margin , " a {.cls margin} object" , allow_null = TRUE )
52
46
if (length(width ) != 1 ) {
53
47
cli :: cli_abort(" {.arg width} must be a single {.cls unit}, not a unit vector." )
54
48
}
55
49
if (length(height ) != 1 ) {
56
50
cli :: cli_abort(" {.arg height} must be a single {.cls unit}, not a unit vector." )
57
51
}
58
- title.position <- arg_match0(title.position , .trbl )
59
52
60
53
new_guide(
61
54
grob = grob ,
62
55
width = width ,
63
56
height = height ,
64
57
title = title ,
65
- title.position = title.position ,
66
- margin = margin ,
58
+ theme = theme ,
67
59
hash = hash(list (title , grob )), # hash is already known
68
60
position = position ,
69
61
order = order ,
@@ -79,19 +71,15 @@ guide_custom <- function(
79
71
GuideCustom <- ggproto(
80
72
" GuideCustom" , Guide ,
81
73
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 )),
88
75
89
76
hashables = exprs(title , grob ),
90
77
91
78
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"
95
83
),
96
84
97
85
train = function (... ) {
@@ -102,72 +90,93 @@ GuideCustom <- ggproto(
102
90
params
103
91
},
104
92
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 )
109
112
},
110
113
111
114
draw = function (self , theme , position = NULL , direction = NULL ,
112
115
params = self $ params ) {
113
116
117
+ if (is.zero(params $ grob )) {
118
+ return (zeroGrob())
119
+ }
120
+
114
121
# Render title
122
+ params $ direction <- params $ direction %|| % direction
115
123
elems <- self $ setup_elements(params , self $ elements , theme )
116
124
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
- }
126
125
126
+ # Start with putting the main grob in a gtable
127
127
width <- convertWidth(params $ width , " cm" , valueOnly = TRUE )
128
128
height <- convertHeight(params $ height , " cm" , valueOnly = TRUE )
129
129
gt <- gtable(widths = unit(width , " cm" ), heights = unit(height , " cm" ))
130
130
gt <- gtable_add_grob(gt , params $ grob , t = 1 , l = 1 , clip = " off" )
131
131
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 )
158
135
} 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()
161
137
}
162
138
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
+ }
164
170
171
+ # Add padding and background
172
+ gt <- gtable_add_padding(gt , elems $ margin )
165
173
background <- element_grob(elems $ background )
166
174
gt <- gtable_add_grob(
167
175
gt , background ,
168
176
t = 1 , l = 1 , r = - 1 , b = - 1 ,
169
177
z = - Inf , clip = " off"
170
178
)
179
+
171
180
gt
172
181
}
173
182
)
0 commit comments