Skip to content
Browse files

new grid functions grid.reorder() and reorderGrob()

git-svn-id: https://svn.r-project.org/R/trunk@60940 00db46b3-68df-0310-9c12-caf00c1e9a41
  • Loading branch information...
1 parent fb8e36f commit 3b67da9c9e5041ce906994bdf95122c1705ad12c murrell committed Oct 14, 2012
View
3 src/library/grid/NAMESPACE
@@ -26,7 +26,7 @@ export(
"grid.plot.and.legend",
"grid.pretty",
"grid.prompt",
- "grid.refresh",
+ "grid.refresh",
"grid.show.layout", "grid.show.viewport",
"unit",
@@ -66,6 +66,7 @@ export(
"getGrob", "setGrob", "addGrob", "removeGrob", "editGrob",
"gEdit", "gEditList", "applyEdit", "applyEdits",
"grid.grab", "grid.grabExpr",
+ "grid.reorder", "reorderGrob",
"grid.cap",
"setChildren",
"showGrob",
View
59 src/library/grid/R/grob.R
@@ -1945,3 +1945,62 @@ grid.copy <- function(grob) {
grob
}
+###############################
+# Reordering grobs
+
+# Reorder the children of a gTree
+# Order may be specified as a character vector
+# Character vector MUST name existing children
+# Order may be specified as a numeric vector
+# (which makes it easy to say something like
+# "make last child the first child")
+# Numeric vector MUST be within range 1:numChildren
+# Only unique order values used
+# Any children NOT specified by order are appended to
+# front or back of order (depending on 'front' argument)
+# Order is ALWAYS back-to-front
+reorderGrob <- function(x, order, back=TRUE) {
+ if (!inherits(x, "gTree"))
+ stop("can only reorder 'children' for a \"gTree\"")
+ order <- unique(order)
+ oldOrder <- x$childrenOrder
+ N <- length(oldOrder)
+ if (is.character(order)) {
+ # Convert to numeric
+ order <- match(order, x$childrenOrder)
+ }
+ if (is.numeric(order)) {
+ if (any(!is.finite(order)) ||
+ !(all(order %in% 1:N))) {
+ stop("Invalid 'order'")
+ }
+ if (back) {
+ newOrder <- c(x$childrenOrder[order],
+ x$childrenOrder[-order])
+ } else {
+ newOrder <- c(x$childrenOrder[-order],
+ x$childrenOrder[order])
+ }
+ }
+ x$childrenOrder <- newOrder
+ x
+}
+
+# Reorder the children of a gTree on the display list
+# (identified by a gPath)
+# NOTE that it is possible for this operation to produce a grob
+# that no longer draws (because it relies on another grob that
+# used to be drawn before it, e.g., when the width of grob "b"
+# is calculated from the width of grob "a")
+# Do NOT allow reordering of grobs on the display list
+# (it is not even clear what should happen in terms of reordering
+# grobs mixed with viewports PLUS the potential for ending up with
+# something that will not draw is pretty high)
+# IF you want to reorder the grobs on the DL, do a grid.grab()
+# first and then reorder the children of the resulting gTree
+grid.reorder <- function(gPath, order, back=TRUE, redraw=TRUE) {
+ grob <- grid.get(gPath)
+ grid.set(gPath, reorderGrob(grob, order, back=back),
+ redraw=redraw)
+}
+
View
4 src/library/grid/inst/doc/changes.txt
@@ -15,6 +15,10 @@ Changes from grid_2.15.0 to grid_2.16.0:
"vpList", or "vpTree" (i.e., mixing of viewports
and "vpPaths").
+4. New functions grid.reorder() and reorderGrob() to
+ modify the order in which the children of a gTree
+ are drawn.
+
Changes from grid_2.14.0 to grid_2.15.0:
--------------------------------------
View
84 src/library/grid/man/grid.reorder.Rd
@@ -0,0 +1,84 @@
+% File src/library/grid/man/grid.reorder.Rd
+% Part of the R package, http://www.R-project.org
+% Copyright 1995-2007 R Core Team
+% Distributed under GPL 2 or later
+
+\name{grid.reorder}
+\alias{grid.reorder}
+\alias{reorderGrob}
+\title{ Reorder the children of a gTree }
+\description{
+ Change the order in which the children of a gTree get drawn.
+}
+\usage{
+grid.reorder(gPath, order, back=TRUE, redraw=TRUE)
+reorderGrob(x, order, back=TRUE)
+}
+\arguments{
+ \item{gPath}{A gPath object specifying a gTree within the current
+ scene.}
+ \item{x}{A gTree object to be modified.}
+ \item{order}{A character vector or a numeric vector that specifies
+ the new drawing order for the children of the gTree. May not refer
+ to all children of the gTree (see Details).}
+ \item{back}{Controls what happens when the \code{order} does not
+ specify all children of the gTree (see Details).}
+ \item{redraw}{Should the modified scene be redrawn?}
+}
+\details{
+ In the simplest case, \code{order} specifies a new ordering for all of
+ the children of the gTree. The children may be specified either by
+ name or by existing numerical order.
+
+ If the \code{order} does not
+ specify all children of the gTree then, by default, the children
+ specified by \code{order} are drawn first and then all remaining
+ children are drawn. If \code{back=FALSE} then the children not
+ specified in \code{order} are drawn first, followed by the specified
+ children. This makes it easy to specify a send-to-back or
+ bring-to-front reordering. The \code{order} argument is \emph{always}
+ in back-to-front order.
+
+ It is not possible to reorder the grid display list (the top-level
+ grobs in the current scene) because the display list is a mixture of
+ grobs and viewports (so it is not clear what reordering even means and
+ it would be too easy to end up with a scene that would not draw).
+ If you want to reorder the grid display list, try \code{grid.grab()}
+ to create a gTree and then reorder (and redraw) that gTree.
+}
+\section{Warning}{
+ This function may return a gTree that will not draw. For example, a
+ gTree has two children, A and B (in that order),
+ and the width of child B depends on the width of child A (e.g., a box
+ around a piece of text). Switching the order so that B is drawn
+ before A will not allow B to be drawn. If this happens with
+ \code{grid.reorder()}, the modification will not be performed. If
+ this happens with \code{reorderGrob()} it should be possible simply to
+ restore the original order.
+}
+\value{
+ \code{grid.reorder()} is called for its side-effect of modifying the
+ current scene.
+ \code{reorderGrob()} returns the modified gTree.
+}
+\author{ Paul Murrell }
+\examples{
+# gTree with two children, "red-rect" and "blue-rect" (in that order)
+gt <- gTree(children=gList(
+ rectGrob(gp=gpar(col=NA, fill="red"),
+ width=.8, height=.2, name="red-rect"),
+ rectGrob(gp=gpar(col=NA, fill="blue"),
+ width=.2, height=.8, name="blue-rect")),
+ name="gt")
+grid.newpage()
+grid.draw(gt)
+# Spec entire order as numeric (blue-rect, red-rect)
+grid.reorder("gt", 2:1)
+# Spec entire order as character
+grid.reorder("gt", c("red-rect", "blue-rect"))
+# Only spec the one I want behind as character
+grid.reorder("gt", "blue-rect")
+# Only spec the one I want in front as character
+grid.reorder("gt", "blue-rect", back=FALSE)
+}
+\keyword{ dplot }

0 comments on commit 3b67da9

Please sign in to comment.
Something went wrong with that request. Please try again.