42
42
# ' @param keyheight A numeric or a [grid::unit()] object specifying
43
43
# ' the height of the legend key. Default value is `legend.key.height` or
44
44
# ' `legend.key.size` in [theme()].
45
+ # ' @param key.spacing,key.spacing.x,key.spacing.y A numeric or [grid::unit()]
46
+ # ' object specifying the distance between key-label pairs in the horizontal
47
+ # ' direction (`key.spacing.x`), vertical direction (`key.spacing.y`) or both
48
+ # ' (`key.spacing`).
45
49
# ' @param direction A character string indicating the direction of the guide.
46
50
# ' One of "horizontal" or "vertical."
47
51
# ' @param default.unit A character string indicating [grid::unit()]
@@ -143,6 +147,9 @@ guide_legend <- function(
143
147
# Key size
144
148
keywidth = NULL ,
145
149
keyheight = NULL ,
150
+ key.spacing = NULL ,
151
+ key.spacing.x = NULL ,
152
+ key.spacing.y = NULL ,
146
153
147
154
# General
148
155
direction = NULL ,
@@ -156,12 +163,24 @@ guide_legend <- function(
156
163
...
157
164
) {
158
165
# Resolve key sizes
159
- if (! inherits( keywidth , c( " NULL " , " unit" ))) {
166
+ if (! (is.null( keywidth ) || is. unit( keywidth ))) {
160
167
keywidth <- unit(keywidth , default.unit )
161
168
}
162
- if (! inherits( keyheight , c( " NULL " , " unit" ))) {
169
+ if (! (is.null( keyheight ) || is. unit( keyheight ))) {
163
170
keyheight <- unit(keyheight , default.unit )
164
171
}
172
+
173
+ # Resolve spacing
174
+ key.spacing.x <- key.spacing.x %|| % key.spacing
175
+ if (! is.null(key.spacing.x ) || is.unit(key.spacing.x )) {
176
+ key.spacing.x <- unit(key.spacing.x , default.unit )
177
+ }
178
+ key.spacing.y <- key.spacing.y %|| % key.spacing
179
+ if (! is.null(key.spacing.y ) || is.unit(key.spacing.y )) {
180
+ key.spacing.y <- unit(key.spacing.y , default.unit )
181
+ }
182
+
183
+
165
184
if (! is.null(title.position )) {
166
185
title.position <- arg_match0(title.position , .trbl )
167
186
}
@@ -187,6 +206,8 @@ guide_legend <- function(
187
206
# Key size
188
207
keywidth = keywidth ,
189
208
keyheight = keyheight ,
209
+ key.spacing.x = key.spacing.x ,
210
+ key.spacing.y = key.spacing.y ,
190
211
191
212
# General
192
213
direction = direction ,
@@ -226,9 +247,10 @@ GuideLegend <- ggproto(
226
247
227
248
keywidth = NULL ,
228
249
keyheight = NULL ,
250
+ key.spacing.x = NULL ,
251
+ key.spacing.y = NULL ,
229
252
230
253
# General
231
- direction = NULL ,
232
254
override.aes = list (),
233
255
nrow = NULL ,
234
256
ncol = NULL ,
@@ -249,9 +271,6 @@ GuideLegend <- ggproto(
249
271
elements = list (
250
272
background = " legend.background" ,
251
273
margin = " legend.margin" ,
252
- spacing = " legend.spacing" ,
253
- spacing.x = " legend.spacing.x" ,
254
- spacing.y = " legend.spacing.y" ,
255
274
key = " legend.key" ,
256
275
key.height = " legend.key.height" ,
257
276
key.width = " legend.key.width" ,
@@ -436,13 +455,35 @@ GuideLegend <- ggproto(
436
455
elements $ text $ size %|| % 11
437
456
gap <- unit(gap * 0.5 , " pt" )
438
457
# Should maybe be elements$spacing.{x/y} instead of the theme's spacing?
439
- elements $ hgap <- width_cm( theme $ legend.spacing.x %|| % gap )
440
- elements $ vgap <- height_cm(theme $ legend.spacing.y %|| % gap )
458
+
459
+ if (params $ direction == " vertical" ) {
460
+ # For backward compatibility, vertical default is no spacing
461
+ vgap <- params $ key.spacing.y %|| % unit(0 , " pt" )
462
+ } else {
463
+ vgap <- params $ key.spacing.y %|| % gap
464
+ }
465
+
466
+ elements $ hgap <- width_cm( params $ key.spacing.x %|| % gap )
467
+ elements $ vgap <- height_cm(vgap )
441
468
elements $ padding <- convertUnit(
442
469
elements $ margin %|| % margin(),
443
470
" cm" , valueOnly = TRUE
444
471
)
445
472
473
+ # When no explicit margin has been set, either in this guide or in the
474
+ # theme, we set a default text margin to leave a small gap in between
475
+ # the label and the key.
476
+ if (is.null(params $ label.theme $ margin %|| % theme $ legend.text $ margin ) &&
477
+ ! inherits(elements $ text , " element_blank" )) {
478
+ i <- match(params $ label.position , .trbl [c(3 , 4 , 1 , 2 )])
479
+ elements $ text $ margin [i ] <- elements $ text $ margin [i ] + gap
480
+ }
481
+ if (is.null(params $ title.theme $ margin %|| % theme $ legend.title $ margin ) &&
482
+ ! inherits(elements $ title , " element_blank" )) {
483
+ i <- match(params $ title.position , .trbl [c(3 , 4 , 1 , 2 )])
484
+ elements $ title $ margin [i ] <- elements $ title $ margin [i ] + gap
485
+ }
486
+
446
487
# Evaluate backgrounds early
447
488
if (! is.null(elements $ background )) {
448
489
elements $ background <- ggname(
@@ -527,22 +568,23 @@ GuideLegend <- ggproto(
527
568
hgap <- elements $ hgap %|| % 0
528
569
widths <- switch (
529
570
params $ label.position ,
530
- " left" = list (label_widths , hgap , widths , hgap ),
531
- " right" = list (widths , hgap , label_widths , hgap ),
532
- list (pmax(label_widths , widths ), hgap * ( ! byrow ) )
571
+ " left" = list (label_widths , widths , hgap ),
572
+ " right" = list (widths , label_widths , hgap ),
573
+ list (pmax(label_widths , widths ), hgap )
533
574
)
534
575
widths <- head(vec_interleave(!!! widths ), - 1 )
535
576
536
577
vgap <- elements $ vgap %|| % 0
537
578
heights <- switch (
538
579
params $ label.position ,
539
- " top" = list (label_heights , vgap , heights , vgap ),
540
- " bottom" = list (heights , vgap , label_heights , vgap ),
541
- list (pmax(label_heights , heights ), vgap * ( byrow ) )
580
+ " top" = list (label_heights , heights , vgap ),
581
+ " bottom" = list (heights , label_heights , vgap ),
582
+ list (pmax(label_heights , heights ), vgap )
542
583
)
543
584
heights <- head(vec_interleave(!!! heights ), - 1 )
544
585
545
586
has_title <- ! is.zero(grobs $ title )
587
+
546
588
if (has_title ) {
547
589
# Measure title
548
590
title_width <- width_cm(grobs $ title )
@@ -551,14 +593,14 @@ GuideLegend <- ggproto(
551
593
# Combine title with rest of the sizes based on its position
552
594
widths <- switch (
553
595
params $ title.position ,
554
- " left" = c(title_width , hgap , widths ),
555
- " right" = c(widths , hgap , title_width ),
596
+ " left" = c(title_width , widths ),
597
+ " right" = c(widths , title_width ),
556
598
c(widths , max(0 , title_width - sum(widths )))
557
599
)
558
600
heights <- switch (
559
601
params $ title.position ,
560
- " top" = c(title_height , vgap , heights ),
561
- " bottom" = c(heights , vgap , title_height ),
602
+ " top" = c(title_height , heights ),
603
+ " bottom" = c(heights , title_height ),
562
604
c(heights , max(0 , title_height - sum(heights )))
563
605
)
564
606
}
@@ -595,20 +637,20 @@ GuideLegend <- ggproto(
595
637
switch (
596
638
params $ label.position ,
597
639
" top" = {
598
- key_row <- key_row * 2
599
- label_row <- label_row * 2 - 2
640
+ key_row <- key_row + df $ R
641
+ label_row <- key_row - 1
600
642
},
601
643
" bottom" = {
602
- key_row <- key_row * 2 - 2
603
- label_row <- label_row * 2
644
+ key_row <- key_row + df $ R - 1
645
+ label_row <- key_row + 1
604
646
},
605
647
" left" = {
606
- key_col <- key_col * 2
607
- label_col <- label_col * 2 - 2
648
+ key_col <- key_col + df $ C
649
+ label_col <- key_col - 1
608
650
},
609
651
" right" = {
610
- key_col <- key_col * 2 - 2
611
- label_col <- label_col * 2
652
+ key_col <- key_col + df $ C - 1
653
+ label_col <- key_col + 1
612
654
}
613
655
)
614
656
@@ -617,8 +659,8 @@ GuideLegend <- ggproto(
617
659
switch (
618
660
params $ title.position ,
619
661
" top" = {
620
- key_row <- key_row + 2
621
- label_row <- label_row + 2
662
+ key_row <- key_row + 1
663
+ label_row <- label_row + 1
622
664
title_row <- 2
623
665
title_col <- seq_along(sizes $ widths ) + 1
624
666
},
@@ -627,8 +669,8 @@ GuideLegend <- ggproto(
627
669
title_col <- seq_along(sizes $ widths ) + 1
628
670
},
629
671
" left" = {
630
- key_col <- key_col + 2
631
- label_col <- label_col + 2
672
+ key_col <- key_col + 1
673
+ label_col <- label_col + 1
632
674
title_row <- seq_along(sizes $ heights ) + 1
633
675
title_col <- 2
634
676
},
0 commit comments