44# ' for legends. See \code{\link[graphics]{legend}} for more details.
55# '
66# ' @param object gsplot object
7- # ' @param \dots Further graphical parameters may also be supplied as arguments. See 'Details'.
7+ # ' @param \dots Overall legend parameters may also be supplied as arguments. See 'Details'.
88# '
9- # ' @details Additional graphical parameter inputs:
10- # ' \itemize{
11- # ' \item{\code{location}} {position of the legend, specified by x- and y-coordinates or by keyword ("bottomright", "bottom", "bottomleft", "left", "topleft", "top", "topright", "right", or "center")}
12- # ' \item{\code{title}} {character string indicating the legend title}
13- # ' }
9+ # ' @details
10+ # ' Overall legend inputs:
11+ # '
12+ # ' \code{x, y} coordinates OR use \code{location} which is a character string indicating the legend location: above, toright, toleft, or below (see \code{\link[graphics]{legend}} for more)
13+ # '
14+ # ' \code{bty, bg, box.lty, box.lwd, box.col, cex, xjust, yjust
15+ # ' x.intersp, y.intersp, adj, text.width, merge, trace,
16+ # ' plot, ncol, horiz, title, inset, xpd, title.col
17+ # ' title.adj, seg.len}
18+ # '
19+ # ' Parameter inputs for each graphics call (use inside of lines, points, curve, etc):
20+ # '
21+ # ' \code{legend.name, fill, col, border, lty, lwd, pch, angle,
22+ # ' density, pt.bg, pt.cex, pt.lwd, text.col, text.font}
1423# '
1524# ' @export
1625# ' @importFrom graphics par
@@ -51,44 +60,19 @@ legend <- function(object, ...){
5160}
5261
5362
54- legend.gsplot <- function (object , ... , location = " topright" , title = " EXPLANATION " , legend_offset = 0.3 ) {
63+ legend.gsplot <- function (object , ... , location = " topright" , legend_offset = 0.3 ) {
5564 arguments <- list (... )
5665
57- # current_list <- config("legend") # grabbing yaml defaults
58- # title <- current_list$title
59- # location <- current_list$location
66+ gsConfig <- list (location = location , legend_offset = legend_offset , ... )
6067
6168 if (" x" %in% names(arguments )){
62- location <- arguments $ x
69+ gsConfig $ location <- gsConfig $ x
70+ gsConfig $ x <- NULL
6371 }
6472
65- gsConfig <- list (location = location , legend_offset = legend_offset , title = title )
66-
67- arguments <- appendLegendPositionConfiguration(location , gsConfig , arguments )
68- arguments <- append(arguments , list (title = title ))
69-
70- object <- append(object , list (legend = list (arguments = arguments , gs.config = gsConfig )))
71-
72- return (gsplot(object ))
73- }
74-
75- appendLegendPositionConfiguration <- function (location , gsConfig , arguments ) {
76- # TODO support explicit x/y coords
77- legend_offset <- gsConfig $ legend_offset
73+ object [[' legend' ]] <- append(object [[' legend' ]], list (gs.config = gsConfig ))
7874
79- if (location == " below" ) {
80- return (append(arguments , list (x = " bottom" , y = NULL , inset = c(0 , - legend_offset ), bty = " n" )))
81- } else if (location == " above" ) {
82- return (append(arguments , list (x = " top" , y = NULL , inset = c(0 , - legend_offset ), bty = " n" )))
83- } else if (location == " toright" ) {
84- return (append(arguments , list (x = " right" , y = NULL , inset = c(- legend_offset , 0 ), bty = " n" )))
85- } else if (location == " toleft" ) {
86- return (append(arguments , list (x = " left" , y = NULL , inset = c(- legend_offset , 0 ), bty = " n" )))
87- } else if (" x" %in% names(arguments )){
88- return (arguments )
89- } else {
90- return (append(arguments , list (x = location )))
91- }
75+ return (object )
9276}
9377
9478# ' gsplot draw_legend
@@ -100,98 +84,90 @@ appendLegendPositionConfiguration <- function(location, gsConfig, arguments) {
10084
10185draw_legend <- function (gsplot ) {
10286
87+ if (all(! names(gsplot [[' legend' ]]) %in% " gs.config" )){
88+ return ()
89+ }
90+
10391 oldXPD <- par()$ xpd
92+ oldBg <- par(' bg' )
10493
105- for (index in which(names(gsplot ) %in% " legend" )){
106-
107- legendParams <- gsplot [[index ]][[' arguments' ]]
94+ for (index in which(names(gsplot [[' legend' ]]) %in% " gs.config" )){
10895
10996 par(xpd = TRUE )
11097
111- if (! (" legend" %in% names(legendParams ))){
98+ if (any(names(gsplot [[' legend' ]]) == " legend.args" )) {
99+
100+ default.args <- formals(graphics :: legend )
101+ overall.legend <- c(" x" , " y" , " bty" , " bg" , " box.lty" , " box.lwd" , " box.col" , " cex" ,
102+ " xjust" , " yjust" , " x.intersp" , " y.intersp" , " adj" , " text.width" ,
103+ " merge" , " trace" , " plot" , " ncol" , " horiz" , " title" , " inset" ,
104+ " xpd" , " title.col" , " title.adj" , " seg.len" )
105+ not.overall <- default.args [which(! names(default.args ) %in% overall.legend )]
106+ legendParamsALL <- vector(" list" , length(not.overall ))
107+ names(legendParamsALL ) <- names(not.overall )
112108
113- if (! is.null(legendParams )) {
114-
115- smartLegend <- data.frame (row.names = names(formals(graphics :: legend )), stringsAsFactors = FALSE )
116- views = views(gsplot )
117- for (v in seq_len(length(views ))){
118- for (i in seq_len(length(names(views [[v ]])))) {
119-
120- plotElement <- names(views [[v ]][i ])
121-
122- params <- c(' legend' = views [[v ]][[i ]][[' legend.name' ]])
123- if (is.null(params )) {next }
124-
125- params <- append(params , views [[v ]][[i ]][which(names(views [[v ]][[i ]]) %in% names(formals(graphics :: legend ))[- c(1 ,2 )])])
126- type <- views [[v ]][[i ]][[' arguments$type' ]]
127-
128- if (plotElement == " points" ) {
129- names(params )[which(names(params ) %in% " bg" )] <- ' pt.bg'
130- names(params )[which(names(params ) %in% " cex" )] <- ' pt.cex'
131- names(params )[which(names(params ) %in% " lwd" )] <- ' pt.lwd'
132- if (! is.null(type ) && type %in% c(" l" , " o" , " b" , " c" , " s" , " S" , " h" )) {
133- if (all(! names(params ) %in% c(" lty" ))) {params <- append(params , list (lty = par(" lty" )))}
134- }
135- }
136- if (plotElement == " lines" && ! is.null(type ) && type %in% c(" p" , " o" , " b" , " c" )) {
137- if (all(! names(params ) %in% c(" pch" ))) {params <- append(params , list (pch = par(" pch" )))}
138- params <- append(params , list (pt.lwd = params $ lwd ))
139- if (type == " p" ) {params <- params [- which(names(params ) %in% c(' lty' , ' lwd' ))]}
140- names(params )[which(names(params ) %in% " bg" )] <- ' pt.bg'
141- names(params )[which(names(params ) %in% " cex" )] <- ' pt.cex'
142- }
143- if (plotElement %in% c(" rect" , " polygon" )) {
144- names(params )[which(names(params ) %in% " col" )] <- ' fill'
145- }
146-
147- ifelse(length(smartLegend ) == 0 , smartLegendNames <- row.names(smartLegend ), smartLegendNames <- names(smartLegend ))
148- newsmartLegend <- match(smartLegendNames , names(params ))
149- newsmartLegend [which(! is.na(newsmartLegend ))] <- params [newsmartLegend [which(! is.na(newsmartLegend ))]]
150- names(newsmartLegend ) <- smartLegendNames
151-
152- smartLegend <- rbind(smartLegend , as.data.frame(newsmartLegend , stringsAsFactors = FALSE ))
153-
154- }
155- }
156-
157-
158-
159- # take out any calls with all NA, and add overall legend calls from legendParams
160- indices <- unlist(sapply(seq_len(length(smartLegend )), function (x ) {! all(is.na(smartLegend [[x ]]))}))
161- legendParams <- append(legendParams , smartLegend [indices ])
162-
163- # change any numeric linetypes to character
164- lineTypes <- c(" blank" , " solid" , " dashed" , " dotted" , " dotdash" , " longdash" , " twodash" )
165- if (any(legendParams $ lty %in% c(as.character(1 : 6 )))) {
166- ltyIndices <- which(legendParams $ lty %in% c(as.character(1 : 6 )))
167- legendParams $ lty [ltyIndices ] <- sapply(as.numeric(legendParams $ lty [ltyIndices ]), function (x ) lineTypes [x + 1 ])
109+ for (i in which(names(gsplot [[' legend' ]]) %in% ' legend.args' )) {
110+ orderedParams <- gsplot [[' legend' ]][[i ]][match(names(legendParamsALL ), names(gsplot [[' legend' ]][[i ]]))]
111+ for (j in seq_along(legendParamsALL )) {
112+ legendParamsALL [[j ]] <- c(legendParamsALL [[j ]], orderedParams [[j ]])
168113 }
169-
170- # if density is specified, default should be "NULL"
171- # if (!is.null(legendParams$density)) {legendParams$density[which(is.na(legendParams$density))] <- par("bg")}
172-
173- # for above/below, dynamically set the number of columns
174- location <- gsplot [[' legend' ]][[' gs.config' ]][[' location' ]]
175- if (location == " below" || location == " above" ) {
176- itemsPerCol <- 3 # TODO load this from config
177- cols <- NROW(smartLegend ) %/% 3 ;
178- if (NROW(smartLegend ) %% 3 > 0 ) {
179- cols <- cols + 1
180- }
181- legendParams <- append(legendParams , list (ncol = cols ))
114+ }
115+
116+ # for above/below, dynamically set the number of columns
117+ location <- gsplot [[' legend' ]][[' gs.config' ]][[' location' ]]
118+ if (location == " below" || location == " above" ) {
119+ itemsPerCol <- 3 # TODO load this from config
120+ cols <- length(legendParamsALL $ legend ) %/% 3 ;
121+ if (length(legendParamsALL $ legend ) %% 3 > 0 ) {
122+ cols <- cols + 1
182123 }
183-
184- legend(legendParams )
185-
124+ legendParamsALL <- append(legendParamsALL , list (ncol = cols ))
125+ }
126+
127+ overallLegendArgs <- appendLegendPositionConfiguration(gsplot [[' legend' ]][[' gs.config' ]])
128+ legendParamsALL <- append(legendParamsALL , overallLegendArgs )
129+ legendOrdered <- legendParamsALL [na.omit(match(names(default.args ), names(legendParamsALL )))]
130+
131+ # set bg so that fill/border/etc args are correct, then evaluate any quoted list items
132+ if (any(names(overallLegendArgs ) %in% c(" bg" ))) {
133+ par(bg = overallLegendArgs $ bg )
186134 }
135+ legendComplete <- lapply(legendOrdered , function (x ) {unname(sapply(x , function (x ) {eval(x )}))})
136+
187137 } else {
188- legend( legendParams )
138+ legendComplete <- appendLegendPositionConfiguration( gsplot [[ ' legend ' ]][[ index ]] )
189139 }
140+
141+ legend(legendComplete )
142+ par(xpd = oldXPD )
143+ par(bg = oldBg )
190144 }
145+
146+ }
147+
148+ appendLegendPositionConfiguration <- function (gsConfig ) {
149+ # TODO support explicit x/y coords
150+ legend_offset <- gsConfig $ legend_offset
151+ location <- gsConfig $ location
152+ gsConfig $ legend_offset <- NULL
153+ gsConfig $ location <- NULL
191154
192- par(xpd = oldXPD )
155+ if (location == " below" ) {
156+ return (append(gsConfig , list (x = " bottom" , y = NULL , inset = c(0 , - legend_offset ), bty = " n" )))
157+ } else if (location == " above" ) {
158+ return (append(gsConfig , list (x = " top" , y = NULL , inset = c(0 , - legend_offset ), bty = " n" )))
159+ } else if (location == " toright" ) {
160+ return (append(gsConfig , list (x = " right" , y = NULL , inset = c(- legend_offset , 0 ), bty = " n" )))
161+ } else if (location == " toleft" ) {
162+ return (append(gsConfig , list (x = " left" , y = NULL , inset = c(- legend_offset , 0 ), bty = " n" )))
163+ } else if (" x" %in% names(gsConfig )){
164+ return (gsConfig )
165+ } else {
166+ return (append(gsConfig , list (x = location )))
167+ }
193168}
194169
170+ # What is this for?
195171legend_adjusted_margins <- function (gsPlot ) {
196172 defaults <- config(" plot" )
197173 defaultMargins <- c(3 , 3 , 3 , 3 ) # default margins should come from config
0 commit comments