blob: 2041fc7272804f283ea06a7c2f36a965361ea553 [file] [log] [blame]
# File src/library/grid/R/layout.R
# Part of the R package, https://www.R-project.org
#
# Copyright (C) 1995-2016 The R Core Team
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# A copy of the GNU General Public License is available at
# https://www.R-project.org/Licenses/
is.layout <- function(l) {
inherits(l, "layout")
}
# FIXME: The internal C code now does a lot of recycling of
# unit values, units, and data. Can some/most/all of the
# recycling stuff below be removed ?
valid.layout <- function(nrow, ncol, widths, heights, respect, just) {
nrow <- as.integer(nrow)
ncol <- as.integer(ncol)
# make sure we're dealing with a unit object
if (!is.logical(respect)) {
respect <- as.matrix(respect)
if (!is.matrix(respect) || any(dim(respect) != c(nrow, ncol)))
stop("'respect' must be logical or an 'nrow' by 'ncol' matrix")
}
if (is.matrix(respect)) {
respect.mat <- matrix(as.integer(respect),
dim(respect)[1L],
dim(respect)[2L])
respect <- 2
}
else respect.mat <- matrix(0L, nrow, ncol)
valid.just <- valid.just(just)
l <- list(nrow = nrow, ncol = ncol,
widths = widths, heights = heights,
respect = respect, valid.respect=as.integer(respect),
respect.mat = respect.mat,
just=just, valid.just=valid.just)
class(l) <- "layout"
l
}
layout.torture <- function() {
top.vp <- viewport(y=0, height=unit(1, "npc") - unit(1.5, "lines"),
just=c("centre", "bottom"))
do.label <- function(label) {
grid.rect(y=1, height=unit(1.5, "lines"),
just=c("center", "top"))
grid.text(label,
y=unit(1, "npc") - unit(1, "lines"),
gp=gpar(font=2))
}
# 1 = all relative widths and heights
grid.show.layout(grid.layout(3,2), vp=top.vp)
do.label("All dimensions relative -- no respect")
# (1) with full respect
grid.show.layout(grid.layout(3,2, respect=TRUE), vp=top.vp)
do.label("All dimensions relative -- full respect")
# (1) with partial respect
grid.show.layout(grid.layout(3,2,respect=matrix(c(1,0,0,0,0,0), 3L, 2L, TRUE)),
vp=top.vp)
do.label("All dimensions relative -- only top-left cell respected")
# (1) with slightly weirder partial respect
grid.show.layout(grid.layout(3,2,respect=matrix(c(1,0,0,0,0,1), 3L, 2L, TRUE)),
vp=top.vp)
do.label("All relative -- top-left, bottom-right respected")
# 2 = combination of absolute and relative widths and heights
grid.show.layout(grid.layout(2, 3,
widths=unit(c(2,4,1), c("null", "cm", "null")),
heights=unit(c(6,4), c("cm", "null"))),
vp=top.vp)
do.label("Absolute and relative -- no respect")
# (2) with full respect
grid.show.layout(grid.layout(2, 3,
widths=unit(c(2,4,1), c("null", "cm", "null")),
heights=unit(c(6,4), c("cm", "null")), respect=TRUE),
vp=top.vp)
do.label("Absolute and relative -- full respect")
# (2) with partial respect
grid.show.layout(grid.layout(2, 3,
widths=unit(c(2,4,1), c("null", "cm", "null")),
heights=unit(c(6,4), c("cm", "null")),
respect=matrix(c(0,0,0,0,0,1), 2L, 3L, TRUE)),
vp=top.vp)
do.label("Absolute and relative -- bottom-right respected")
}
# Return the region allocated by the layout of the current viewport
layoutRegion <- function(layout.pos.row=1, layout.pos.col=1) {
region <- grid.Call(C_layoutRegion,
# This conversion matches the vailidity check in
# valid.viewport()
if (is.null(layout.pos.row)) layout.pos.row
else as.integer(rep(layout.pos.row, length.out=2)),
if (is.null(layout.pos.col)) layout.pos.col
else as.integer(rep(layout.pos.col, length.out=2)))
list(left=unit(region[1L], "npc"),
bottom=unit(region[2L], "npc"),
width=unit(region[3L], "npc"),
height=unit(region[4L], "npc"))
}
####################
# Accessors
####################
layout.nrow <- function(lay) {
lay$nrow
}
layout.ncol <- function(lay) {
lay$ncol
}
layout.widths <- function(lay) {
lay$widths
}
layout.heights <- function(lay) {
lay$heights
}
layout.respect <- function(lay) {
switch(lay$respect + 1,
FALSE,
TRUE,
lay$respect.mat)
}
####################
# Public constructor function
####################
grid.layout <- function (nrow = 1, ncol = 1,
widths = unit(rep_len(1, ncol), "null"),
heights = unit(rep_len(1, nrow), "null"),
default.units = "null",
respect = FALSE,
just="centre")
{
if (!is.unit(widths))
widths <- unit(widths, default.units)
if (!is.unit(heights))
heights <- unit(heights, default.units)
valid.layout(nrow, ncol, widths, heights, respect, just)
}
####################
# Utility Functions
####################
dim.layout <- function(x) {
c(x$nrow, x$ncol)
}