library(grid) library(RGraphics) # Four arrangements, with aspect ratios # 4:1, 3:2, 1:1, 2:3, 1:4 boxSize <- .5 calcLayout <- function() { # Determine current device aspect ratio width <- convertWidth(unit(1, "npc"), "inches", valueOnly=TRUE) height <- convertHeight(unit(1, "npc"), "inches", valueOnly=TRUE) aspect <- log(height/width) if (aspect > (log(4) + log(1.5))/2) layout <- 1 # c(4, 1) else if (aspect > (log(1.5) + log(1))/2) layout <- 2 # c(3, 2) else if (aspect > (log(1) + log(2/3))/2) layout <- 3 # c(2, 2) else if (aspect > (log(2/3) + log(.25))/2) layout <- 4 # c(2, 3) else layout <- 5 # c(1, 4) layout } layoutRows <- function(layout) { switch(layout, 4, 3, 2, 2, 1) } layoutCols <- function(layout) { switch(layout, 1, 2, 2, 3, 4) } layoutRow <- function(layout, i) { switch(layout, switch(i, 1, 2, 3, 4), switch(i, 1, 2, 3, 3), switch(i, 1, 2, 2, 1), switch(i, 1, 2, 2, 2), switch(i, 1, 1, 1, 1)) } layoutCol <- function(layout, i) { switch(layout, switch(i, 1, 1, 1, 1), switch(i, 1, 1, 1, 2), switch(i, 1, 1, 2, 2), switch(i, 1, 1, 2, 3), switch(i, 1, 2, 3, 4)) } lineX <- function(layout, i, rr) { switch(layout, switch(i, c(.5, .5), c(.5, .5), c(.5, .5)), switch(i, c(.5, .5), c(.5, .5), c(.5 + boxSize/2, 1.5 - boxSize/2)), switch(i, c(.5, .5), c(.5 + boxSize/2, 1.5 - boxSize/2), c(.5, .5)), switch(i, c(.5, .5), c(.5 + boxSize/2, 1.5 - boxSize/2), c(.5 + boxSize/2, 1.5 - boxSize/2)), switch(i, c(.5 + boxSize/2, 1.5 - boxSize/2), c(.5 + boxSize/2, 1.5 - boxSize/2), c(.5 + boxSize/2, 1.5 - boxSize/2))) } lineY <- function(layout, i, rr) { switch(layout, switch(i, c(.5 - boxSize/2, -.5 + boxSize/2), c(.5 - boxSize/2, -.5 + boxSize/2), c(.5 - boxSize/2, -.5 + boxSize/2)), switch(i, c(.5 - boxSize/2, -.5 + boxSize/2), c(.5 - boxSize/2, -.5 + boxSize/2), c(.5, .5)), switch(i, c(.5 - boxSize/2, -.5 + boxSize/2), c(.5, .5), c(.5 + boxSize/2, 1.5 - boxSize/2)), switch(i, c(.5 - boxSize/2, -.5 + boxSize/2), c(.5, .5), c(.5, .5)), switch(i, c(.5, .5), c(.5, .5), c(.5, .5))) } dynamicGrob <- function() { grob(cl="dynamic") } grid.dynamic <- function() { grid.draw(dynamicGrob()) } drawDetails.dynamic <- function(x, recording) { layout <- calcLayout() pushViewport(viewport(layout=grid.layout(layoutRows(layout), layoutCols(layout), respect=TRUE))) for (i in 1:4) { pushViewport(viewport(layout.pos.col=layoutCol(layout, i), layout.pos.row=layoutRow(layout, i))) rr <- roundRect(width=boxSize, height=boxSize, name=paste("rr", i, sep=""), gp=gpar(fill="black")) grid.draw(rr) grid.text(i, gp=gpar(col="white", fontsize=convertHeight(unit(0.3, "npc"), "points", valueOnly=TRUE))) if (i < 4) grid.lines(lineX(layout, i, rr), lineY(layout, i, rr), arrow=arrow(length=unit(0.1, "npc")), gp=gpar(lwd=convertHeight(unit(0.01, "npc"), "points", valueOnly=TRUE)*5*72/96)) popViewport() } popViewport() } # grid.newpage() # grid.dynamic() # Resize window by hand # Simulated window change # rows <- 1:9 # cols <- 9:1 # grid.newpage() # pushViewport(viewport(layout=grid.layout(3, 3, respect=TRUE))) # for (i in 1:9) { # pushViewport(viewport(layout.pos.row=(i - 1) %% 3 + 1, # layout.pos.col=(i - 1) %/% 3 + 1, # layout=grid.layout(1, 1, # widths=cols[i], heights=rows[i], respect=TRUE))) # pushViewport(viewport(layout.pos.col=1)) # grid.rect() # grid.draw(demoGrob()) # popViewport(2) # } # upViewport()