Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,12 @@ related to plot layering. See "Bug fixes" below.
theme, since the plot margins are resized to fit the rotated labels. Also
settable globally via `tpar(xaxr = <xaxr>, yaxr = <yaxr>)` and thus as part
of a `tinytheme` too. (#717 @grantmcdermott)
- `las` does the same thing, but limited to the four right angles of base R's
`par(las=)` convention, having previously been settable only via `tpar()` or
a theme. Note that this top-level argument applies to a single plot only and
takes precedence over the active theme, so it can also be used to opt _out_
of a theme's `las`, e.g. `tinyplot(..., theme = "clean", las = 0)`.
(#353 @grantmcdermott)
- (Experimental) `record` enables recording plots as replayable objects,
closing another long-standing feature request (#121). Specifically, setting
`record = TRUE` returns a `"recordedtinyplot"` object (see
Expand Down
15 changes: 13 additions & 2 deletions R/sanitize_axes.R
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
sanitize_axes = function(settings) {
env2env(settings, environment(),
c("axes", "xaxt", "yaxt", "frame.plot", "xaxr", "yaxr", "xpad", "ypad"))
c("axes", "xaxt", "yaxt", "frame.plot", "xaxr", "yaxr", "xpad", "ypad",
"las"))
## handle defaults of axes, xaxt, yaxt, frame.plot
## - convert axes to character if necessary
## - set defaults of xaxt/yaxt (if these are NULL) based on axes
Expand Down Expand Up @@ -35,6 +36,16 @@ sanitize_axes = function(settings) {
if (!is.null(xaxr) && (!is.finite(xaxr) || xaxr %% 360 == 0)) xaxr = NULL
if (!is.null(yaxr) && (!is.finite(yaxr) || yaxr %% 360 == 0)) yaxr = NULL

## tick label orientation. Unlike x/yaxr, not resolved against get_tpar():
## that reads the global .tpar, which lacks the active theme's own las (queued
## in a hook), so folding it in would overwrite a theme's las with 0.
## one membership test, so NA/NaN/Inf and fractions all land on the same
## message rather than tripping over a comparison that returns NA
assert_numeric(las, len = 1, null.ok = TRUE, name = "las")
if (!is.null(las) && !(las %in% 0:3)) {
stop("`las` must be one of 0, 1, 2, or 3", call. = FALSE)
}

## axis padding: an explicit x/ypad wins over the theme's tpar setting. This
## has to resolve here, before flip_datapoints() swaps the pair -- resolving
## it later would leave a tpar default attached to the axis rather than to
Expand All @@ -55,6 +66,6 @@ sanitize_axes = function(settings) {
environment(),
settings,
c("axes", "xaxt", "yaxt", "frame.plot", "xaxr", "yaxr", "xpad", "ypad",
"xpad_user", "ypad_user")
"xpad_user", "ypad_user", "las")
)
}
33 changes: 33 additions & 0 deletions R/tinyplot.R
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,14 @@
#' documentation and examples. Note that this is a post-processing step that
#' affects the _appearance_ of the tick labels only; use in conjunction with
#' `x/yaxb` if you would like to adjust the position of the tick marks too.
#' @param las numeric in `0:3` giving the orientation of the axis tick labels,
#' following the base \code{\link[graphics]{par}} convention: `0` (parallel
#' to the axis), `1` (always horizontal), `2` (perpendicular to the axis), or
#' `3` (always vertical). `NULL` (the default) defers to the active theme,
#' then to `par("las")`. Passing it here overrides both, but
#' only for this plot; unlike `tpar(las=)` or `tinytheme(las=)` it does not
#' persist. For rotations other than the four right angles, see `xaxr`/`yaxr`
#' below.
#' @param xaxr,yaxr numeric giving the rotation of the x- or y-axis tick labels,
#' in degrees counter-clockwise; `NULL` (the default) leaves them unrotated.
#' Setting one overrides `las` for that axis alone, leaving the other axis
Expand Down Expand Up @@ -815,6 +823,7 @@ tinyplot.default = function(
yaxl = NULL,
xaxr = NULL,
yaxr = NULL,
las = NULL,
Comment thread
grantmcdermott marked this conversation as resolved.
log = "",
flip = FALSE,
frame.plot = NULL,
Expand Down Expand Up @@ -1009,6 +1018,7 @@ tinyplot.default = function(
yaxr = yaxr,
yaxs = yaxs,
ypad = ypad,
las = las,
frame.plot = frame.plot,
xlim = xlim,
ylim = ylim,
Expand Down Expand Up @@ -1235,6 +1245,27 @@ tinyplot.default = function(

env2env(settings, environment())

#
## per-call tick label orientation -----
#
# A theme sets its own las at plot.new(), so ours is appended after its hook
# (last appended runs last). The direct par() covers add = TRUE, which fires
# no plot.new(). Undone on exit, so the override stays per-call. (#353)
#
if (!is.null(las)) {
.las_old = par("las")
.las_hook = function() par(las = las)
setHook("before.plot.new", .las_hook, action = "append")
on.exit({
.hks = getHook("before.plot.new")
.keep = !vapply(.hks, identical, logical(1), .las_hook)
setHook("before.plot.new", .hks[.keep], action = "replace")
# par() would *open* a device if none is left (e.g. after `file=`)
if (!is.null(dev.list())) par(las = .las_old)
}, add = TRUE)
par(las = las)
}

#
## dynmar: compute margins up front -----
#
Expand Down Expand Up @@ -1267,6 +1298,8 @@ tinyplot.default = function(
.bp = environment(.h)[["base_par"]]
if (is.list(.bp)) .tpars = modifyList(.tpars, .bp)
}
# runs before plot.new(), so the las hook hasn't fired and par() is stale
if (!is.null(las)) .tpars[["las"]] = las
if (!is.null(.tpars[["mar"]])) .theme_mar = .tpars[["mar"]]

# Tick-label cex is per-side (cex.xaxs/cex.yaxs), each falling back to the
Expand Down
73 changes: 73 additions & 0 deletions inst/tinytest/_tinysnapshot/axis_las1.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
83 changes: 83 additions & 0 deletions inst/tinytest/_tinysnapshot/axis_las2_override.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 16 additions & 0 deletions inst/tinytest/test-tinyAxis.R
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,19 @@ f = function() {
plt(disp ~ mpg, data = mtcars, log = "y")
}
expect_silent(f())


#
## las as a per-call argument (#353)
#

# `las` was accepted by tpar()/tinytheme() but ignored as an argument.
f = function() tinyplot(1:10, las = 1)
expect_snapshot_plot(f, label = "axis_las1")

# An explicit `las` must beat a theme's default, but dynmar still has to reserve
# room for the rotated x labels.
f = function() {
tinyplot(bill_len ~ species, data = penguins, las = 2, theme = "dynamic")
}
expect_snapshot_plot(f, label = "axis_las2_override")
10 changes: 10 additions & 0 deletions man/tinyplot.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading