Dear list, As a minimal test of a more complex grid layout, I'm trying to find a clean and efficient way to arrange text grobs in a rectangular layout. The labels may be expressions, or text with a fontsize different of the default, which means that the cell sizes should probably be calculated using grobWidth() and grobHeight() as opposed to simpler stringWidth() and stringHeight(). (Correct?).
The input of this function is a vector of labels, which are arranged into a matrix layout. Below is my current version, followed by a few questions. e = expression(alpha,"testing very large width", hat(beta), integral(f(x)*dx, a, b)) rowMax.units <- function(u, nrow){ # rowMax with a fake matrix of units matrix.indices <- matrix(seq_along(u), nrow=nrow) do.call(unit.c, lapply(seq(1, nrow), function(ii) { max(u[matrix.indices[ii, ]]) })) } colMax.units <- function(u, ncol){ # colMax with a fake matrix of units matrix.indices <- matrix(seq_along(u), ncol=ncol) do.call(unit.c, lapply(seq(1, ncol), function(ii) { max(u[matrix.indices[, ii]]) })) } makeTableGrobs <- function(e, ncol, nrow, just = c("center", "center"), gpar.text = gpar(col="black", cex=1), gpar.fill = gpar(fill = "grey95", col="white", lwd=1.5)) { n <- length(e) # number of labels stopifnot(!n%%2) # only rectangular layouts if(missing(ncol) & missing(nrow)){ nm <- n2mfrow(n) # pretty default layout ncol = nm[1] nrow = nm[2] } makeOneLabel <- function(label.ind){ textGrob(label=e[label.ind], gp=gpar.text, name=paste("cells-label-",label.ind, sep="")) } lg <- lapply(seq_along(e), makeOneLabel) # list of grobs wg <- lapply(lg, grobWidth) # list of grob widths hg <- lapply(lg, grobHeight) # list of grob heights widths.all <- do.call(unit.c, wg) heights.all <- do.call(unit.c, hg) widths <- colMax.units(widths.all, ncol) heights <- rowMax.units(heights.all, nrow) gcells = frameGrob(name="table.cells", vp = "cells", layout = grid.layout(nrow, ncol, just=just, widths = widths, heights = heights) ) label.ind <- 1 # index running for the vector of labels for (ii in seq(1, ncol, 1)) { for (jj in seq(1, nrow, 1)) { gcells = placeGrob(gcells, rectGrob(gp=gpar.fill, name=paste("cells-fill-r",ii, "-c",jj,sep="")), row=jj, col=ii) text.grob.ij = textGrob(label=e[label.ind], gp=gpar.text, name=paste("cells-label-r",ii, "-c",jj,sep="")) gcells = placeGrob(gcells, text.grob.ij, row=jj, col=ii) label.ind <- label.ind + 1 } } gList( gcells) } # tests vp = viewport(name="cells") grid.draw(gTree(children=makeTableGrobs(e), childrenvp=vp)) grid.newpage() grid.draw(gTree(children=makeTableGrobs(e, 1, 4), childrenvp=vp)) grid.newpage() grid.draw(gTree(children=makeTableGrobs(e, 4, 1), childrenvp=vp)) This works as expected, however I would like some advice before going any further, - because this layout seems quite common, would it make sense to provide methods for the following objects? (i) a matrix of grobs; (ii) a matrix of units; (iii) cbind, rbind, rowMax, colMax methods for a matrix of units. - is there a better, recommended way to achieve the same thing? (examples would be great) Any other comments are very welcome. Best regards, baptiste ______________________________________________ R-help@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide http://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code.