@@ -60,28 +60,123 @@ collapse_guides <- function(guides) {
60
60
guides
61
61
}
62
62
63
+ # ' @importFrom utils getFromNamespace
63
64
# ' @importFrom ggplot2 calc_element
64
- assemble_guides <- function (guides , theme ) {
65
- position <- theme $ legend.position %|| % " right"
66
- if (length(position ) == 2 ) {
67
- warning(" Manual legend position not possible for collected guides. Defaulting to 'right'" , call. = FALSE )
68
- position <- " right"
69
- }
65
+ assemble_guides <- function (guides , position , theme ) {
70
66
# https://github.com/tidyverse/ggplot2/blob/57ba97fa04dadc6fd73db1904e39a09d57a4fcbe/R/guides-.R#L512
71
67
theme $ legend.spacing <- theme $ legend.spacing %|| % unit(0.5 , " lines" )
72
68
theme $ legend.spacing.y <- calc_element(" legend.spacing.y" , theme )
73
69
theme $ legend.spacing.x <- calc_element(" legend.spacing.x" , theme )
70
+
74
71
# for every position, collect all individual guides and arrange them
75
72
# into a guide box which will be inserted into the main gtable
76
- Guides <- utils :: getFromNamespace(" Guides" , " ggplot2" )
77
- Guides $ package_box(guides , position , theme )
73
+ Guides <- getFromNamespace(" Guides" , " ggplot2" )
74
+ package_box <- .subset2(Guides , " package_box" ) %|| % package_box
75
+ package_box(guides , position , theme )
76
+ }
77
+
78
+ # ' @importFrom grid valid.just editGrob
79
+ package_box <- function (guides , guide_pos , theme ) {
80
+ theme <- complete_guide_theme(guide_pos , theme )
81
+ guides <- guides_build(guides , theme )
82
+
83
+ # Set the justification of the legend box
84
+ # First value is xjust, second value is yjust
85
+ just <- valid.just(calc_element(" legend.justification" , theme ))
86
+ xjust <- just [1 ]
87
+ yjust <- just [2 ]
88
+ guides <- editGrob(guides ,
89
+ vp = viewport(x = xjust , y = yjust , just = c(xjust , yjust ))
90
+ )
91
+ guides <- gtable_add_rows(guides , unit(yjust , " null" ))
92
+ guides <- gtable_add_rows(guides , unit(1 - yjust , " null" ), 0 )
93
+ guides <- gtable_add_cols(guides , unit(xjust , " null" ), 0 )
94
+ guides <- gtable_add_cols(guides , unit(1 - xjust , " null" ))
95
+ guides
96
+ }
97
+
98
+ # ' @importFrom ggplot2 calc_element
99
+ complete_guide_theme <- function (guide_pos , theme ) {
100
+ if (guide_pos %in% c(" top" , " bottom" )) {
101
+ theme $ legend.box <- calc_element(" legend.box" , theme ) %|| % " horizontal"
102
+ theme $ legend.direction <- calc_element(" legend.direction" , theme ) %|| %
103
+ " horizontal"
104
+ theme $ legend.box.just <- calc_element(" legend.box.just" , theme ) %|| %
105
+ c(" center" , " top" )
106
+ } else {
107
+ theme $ legend.box <- calc_element(" legend.box" , theme ) %|| % " vertical"
108
+ theme $ legend.direction <- calc_element(" legend.direction" , theme ) %|| %
109
+ " vertical"
110
+ theme $ legend.box.just <- calc_element(" legend.box.just" , theme ) %|| %
111
+ c(" left" , " top" )
112
+ }
113
+ theme
114
+ }
115
+
116
+ # ' @importFrom gtable gtable_width gtable_height gtable gtable_add_grob
117
+ # ' @importFrom grid editGrob heightDetails widthDetails valid.just unit.c unit
118
+ # ' @importFrom ggplot2 margin element_grob element_blank calc_element element_render
119
+ guides_build <- function (guides , theme ) {
120
+ legend.spacing.y <- .subset2(theme , " legend.spacing.y" )
121
+ legend.spacing.x <- .subset2(theme , " legend.spacing.x" )
122
+ legend.box.margin <- calc_element(" legend.box.margin" , theme ) %|| % margin()
123
+
124
+ widths <- exec(unit.c , !!! lapply(guides , gtable_width ))
125
+ heights <- exec(unit.c , !!! lapply(guides , gtable_height ))
126
+
127
+ just <- valid.just(calc_element(" legend.box.just" , theme ))
128
+ xjust <- just [1 ]
129
+ yjust <- just [2 ]
130
+ vert <- identical(calc_element(" legend.box" , theme ), " horizontal" )
131
+ guides <- lapply(guides , function (g ) {
132
+ editGrob(g , vp = viewport(
133
+ x = xjust , y = yjust , just = c(xjust , yjust ),
134
+ height = if (vert ) heightDetails(g ) else 1 ,
135
+ width = if (! vert ) widthDetails(g ) else 1
136
+ ))
137
+ })
138
+ guide_ind <- seq(by = 2 , length.out = length(guides ))
139
+ sep_ind <- seq(2 , by = 2 , length.out = length(guides ) - 1 )
140
+ if (vert ) {
141
+ heights <- max(heights )
142
+ if (length(widths ) != 1 ) {
143
+ w <- unit(rep_len(0 , length(widths ) * 2 - 1 ), " mm" )
144
+ w [guide_ind ] <- widths
145
+ w [sep_ind ] <- legend.spacing.x
146
+ widths <- w
147
+ }
148
+ } else {
149
+ widths <- max(widths )
150
+ if (length(heights ) != 1 ) {
151
+ h <- unit(rep_len(0 , length(heights ) * 2 - 1 ), " mm" )
152
+ h [guide_ind ] <- heights
153
+ h [sep_ind ] <- legend.spacing.y
154
+ heights <- h
155
+ }
156
+ }
157
+ widths <- unit.c(legend.box.margin [4 ], widths , legend.box.margin [2 ])
158
+ heights <- unit.c(legend.box.margin [1 ], heights , legend.box.margin [3 ])
159
+ guides <- gtable_add_grob(
160
+ gtable(widths , heights , name = " guide-box" ),
161
+ guides ,
162
+ t = 1 + if (! vert ) guide_ind else 1 ,
163
+ l = 1 + if (vert ) guide_ind else 1 ,
164
+ name = " guides"
165
+ )
166
+
167
+ gtable_add_grob(
168
+ guides ,
169
+ element_render(theme , " legend.box.background" ),
170
+ t = 1 , l = 1 , b = - 1 , r = - 1 ,
171
+ z = - Inf , clip = " off" , name = " legend.box.background"
172
+ )
78
173
}
79
174
80
175
# ' @importFrom ggplot2 calc_element find_panel
81
176
# ' @importFrom gtable gtable_width gtable_height
82
177
# ' @importFrom grid unit.c
83
- attach_guides <- function (table , guides , theme ) {
84
- guide_areas <- grepl(' panel-guide_area' , table $ layout $ name )
178
+ attach_guides <- function (table , guides , position , theme ) {
179
+ guide_areas <- grepl(" panel-guide_area" , table $ layout $ name )
85
180
if (any(guide_areas )) {
86
181
area_ind <- which(guide_areas )
87
182
if (length(area_ind ) != 1 ) {
@@ -91,14 +186,8 @@ attach_guides <- function(table, guides, theme) {
91
186
return (table )
92
187
}
93
188
p_loc <- find_panel(table )
94
- position <- theme $ legend.position %|| % " right"
95
- if (length(position ) == 2 ) {
96
- warning(' Manual position of collected guides not supported' , call. = FALSE )
97
- position <- " right"
98
- }
99
-
100
- spacing <- calc_element(" legend.box.spacing" , theme ) %|| % unit(0.2 , ' cm' )
101
- legend_width <- gtable_width(guides )
189
+ spacing <- calc_element(" legend.box.spacing" , theme ) %|| % unit(0.2 , " cm" )
190
+ legend_width <- gtable_width(guides )
102
191
legend_height <- gtable_height(guides )
103
192
if (position == " left" ) {
104
193
table <- gtable_add_grob(table , guides , clip = " off" , t = p_loc $ t ,
0 commit comments