2 ##Helper functions for simulating inheritance
3 ## (strongly inspired by the R.oo package)
5 extend <- function(baseObj, className, ..., warningOnOverlap=TRUE)
7 extend.list <- function(baseObj, className, ..., warningOnOverlap=TRUE) {
10 nms <- names(attr.new)
11 ovl <- intersect(nms, names(ans))
12 if(warningOnOverlap && (length(ovl) > 0))
13 warning('Attributes already in', class(baseObj)[1], 'object: ', paste(ovl, collapse=', '))
15 ans[[nm]] <- attr.new[[nm]]
16 class(ans) <- c(className, class(ans))
20 ###############################
21 ##Abstract contentsGrob class##
22 ###############################
23 contentsGrob <- function(xlim, ylim, respect=FALSE, name=NULL, gp=gpar(), vp=NULL)
24 extend(grob(name=name, gp=gp, vp=vp), 'contents', xlim=xlim, ylim=ylim, respect=respect)
25 getXlim <- function(x) UseMethod('getXlim')
26 getXlim.grob <- function(x) 0:1
27 getXlim.contents <- function(x) getField(x, 'xlim')
28 getYlim <- function(x) UseMethod('getYlim')
29 getYlim.grob <- function(x) 0:1
30 getYlim.contents <- function(x) getField(x, 'ylim')
31 getRespect <- function(x) UseMethod('getRespect')
32 getRespect.grob <- function(x) FALSE
33 getRespect.contents <- function(x) getField(x, 'respect')
35 ##Get field from specified object
36 ##Warns if field isn't found
37 getField <- function(obj, fieldName, warningOnNotFount=TRUE)
39 getField.list <- function(obj, fieldName, warningOnNotFound=TRUE) {
40 if(warningOnNotFound && (!(fieldName %in% names(obj))))
41 stop('cannot find field ', fieldName, 'in ', deparse(substitute(obj)))
42 return(obj[[fieldName]])
46 ##Generic grob classes
48 plotGrob <- function(contents=NULL, main=NULL, xlab=NULL, ylab=NULL,
49 xlim=0:1, ylim=0:1, axes=FALSE, respect=NULL, mar=NULL, name=NULL, gp=NULL, vp=NULL) {
50 cv <- mkPlotChildsAndViewports(contents=contents, main=main, xlab=xlab, ylab=ylab, xlim=xlim, ylim=ylim,
51 axes=axes, respect = respect, mar=mar)
52 gTree(contents=contents, main=main, xlab=xlab, ylab=ylab, xlim=xlim, ylim=ylim, mar=mar,
53 children = cv$children, childrenvp = cv$viewports,
54 name=name, gp=gp, vp=vp, cl='plotGrob')
56 editDetails.plotGrob <- function(x, specs) {
57 do.call(plotGrob, specs)
60 makePlotGrobViewports <- function(xlim, ylim, respect, mar) {
61 ws <- unit(c(mar[2], diff(xlim), mar[4]), c('lines','null','lines'))
62 hs <- unit(c(mar[3], diff(ylim), mar[1]), c('lines','null','lines'))
63 ly <- grid.layout(3, 3, widths=ws, heights=hs)
64 lyIso <- grid.layout(1, 1, widths= ws[2], heights= hs[2], respect=respect)
65 vpStack(viewport(layout=lyIso, name='plotLayout'),
66 viewport(layout.pos.col=1, layout.pos.row=1, layout=ly, name='rootArea', clip=FALSE),
68 viewport(layout.pos.col=2, layout.pos.row=2, name='axesArea', xscale=xlim, yscale=ylim, clip=FALSE),
69 viewport(layout.pos.col=2, layout.pos.row=2, name='plotArea', xscale=xlim, yscale=ylim, clip=TRUE),
70 viewport(layout.pos.row=1, name='titleArea', gp=gpar(cex=par('cex.main'))),
71 viewport(layout.pos.col=2, layout.pos.row=3, name='xlabArea'),
72 viewport(layout.pos.col=1, layout.pos.row=2, name='ylabArea')))
75 mkPlotChildsAndViewports <- function(contents=NULL, main=NULL, xlab=NULL, ylab=NULL,
76 xlim=NULL, ylim=NULL, respect=NULL, axes=FALSE, mar=NULL) {
77 null.mar <- is.null(mar)
81 append <- function(lst, elt) {
82 lst[[length(lst)+1]] <- elt
85 if(!is.null(main)) { ##reserve title space
88 childs <- append(childs, textGrob(main, name='title', y=unit(3,'lines'), just=c('center','top'),
89 vp=vpPath('plotLayout', 'rootArea', 'titleArea')))
91 if(!is.null(xlab)) { ##reserve xlab space
94 childs <- append(childs, textGrob(xlab, y=unit(1, 'lines'), name='xlab', just=c('center', 'bottom'),
95 vp=vpPath('plotLayout', 'rootArea', 'xlabArea')))
97 if(!is.null(ylab)) { ##reserve ylab space
100 childs <- append(childs, textGrob(ylab, x=unit(1, 'lines'), rot=90, name='ylab',
101 vp=vpPath('plotLayout', 'rootArea', 'ylabArea')))
103 if(axes) { ##add axes to main area
105 mar[1] <- max(2, mar[1])
106 mar[2] <- max(2, mar[2])
107 mar[4] <- max(2, mar[4])
109 childs <- append(childs, xaxisGrob(name='xaxis', vp=vpPath('plotLayout','rootArea','axesArea')))
110 childs <- append(childs, yaxisGrob(name='yaxis',
111 edits=gEdit('labels', rot=90, just=c('center','bottom')),
112 vp=vpPath('plotLayout', 'rootArea', 'axesArea')))
114 if(!is.null(contents)) {
115 contents$vp <- vpPath('plotLayout','rootArea','plotArea')
116 childs <- append(childs, contents)
118 children <- do.call(gList, childs)
119 if(is.null(xlim)) xlim <- getXlim(contents)
120 if(is.null(ylim)) ylim <- getYlim(contents)
121 if(is.null(respect)) respect <- getRespect(contents)
122 viewports <- makePlotGrobViewports(xlim=xlim, ylim=ylim, respect=respect, mar=mar)
123 list(children=children, viewports=viewports)
127 xyGrob <- function(x, y, type='l', name=NULL, gp=NULL, vp=NULL) {
128 lgr <- linesGrob(x, y, name=paste(name, 'lines', sep='.'), default.units='native')
129 pgr <- pointsGrob(x, y, name=paste(name, 'points', sep='.'), default.units='native')
135 comps <- list(lgr, pgr)
136 xlim <- range(x, na.rm=TRUE)
137 ylim <- range(y, na.rm=TRUE)
139 vp <- viewport(xscale=xlim, yscale=ylim)
140 gTree(x=x, y=y, type=type, children=do.call(gList, comps),
141 name=name, gp=gp, vp=vp, cl='xyGrob')
144 tsGrob <- function(x, name=NULL, gp=NULL, vp=NULL) {
146 xyGrob(time(x), x, type='l', name=name, gp=gp, vp=vp)
149 xyPlotGrob <- function(x, y, type='l', name=NULL, gp=NULL, vp=NULL) {
150 xyg <- xyGrob(x, y, type, name=paste(name,'xyGrob', sep='.'))
153 gTree(x=x, y=y, type=type, children=gList(xyg, box))