Skip to content

Remove ellipsis from theme #1762

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Sep 23, 2016
3 changes: 3 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@
* Themes are more homogeneous visually, and match `theme_grey` better.
(@jiho, #1679)

* The `theme()` constructor now has named arguments rather than ellipsis. This
should make autocomplete substantially more useful.

* `position_stack()` and `position_fill()` now sorts the stacking order so it
matches the order of the grouping. Use level reordering to alter the stacking
order. The default legend and stacking order is now also in line. The default
Expand Down
317 changes: 158 additions & 159 deletions R/theme.r
Original file line number Diff line number Diff line change
Expand Up @@ -80,163 +80,143 @@ print.theme <- function(x, ...) utils::str(x)
#' To see a graphical representation of the inheritance tree, see the
#' last example below.
#'
#' @section Theme elements:
#' The individual theme elements are:
#'
#' \tabular{ll}{
#' line \tab all line elements
#' (\code{element_line}) \cr
#' rect \tab all rectangular elements
#' (\code{element_rect}) \cr
#' text \tab all text elements
#' (\code{element_text}) \cr
#' title \tab all title elements: plot, axes, legends
#' (\code{element_text}; inherits from \code{text}) \cr
#' aspect.ratio \tab aspect ratio of the panel \cr
#'
#' axis.title \tab label of axes
#' (\code{element_text}; inherits from \code{text}) \cr
#' axis.title.x \tab x axis label
#' (\code{element_text}; inherits from \code{axis.title}) \cr
#' axis.title.x.top \tab x axis label on top axis
#' (\code{element_text}; inherits from \code{axis.title.x}) \cr
#' axis.title.y \tab y axis label
#' (\code{element_text}; inherits from \code{axis.title}) \cr
#' axis.title.y.right \tab y axis label on right axis
#' (\code{element_text}; inherits from \code{axis.title.y}) \cr
#' axis.text \tab tick labels along axes
#' (\code{element_text}; inherits from \code{text}) \cr
#' axis.text.x \tab x axis tick labels
#' (\code{element_text}; inherits from \code{axis.text}) \cr
#' axis.text.x.top \tab x axis tick labels on top axis
#' (\code{element_text}; inherits from \code{axis.text.x}) \cr
#' axis.text.y \tab y axis tick labels
#' (\code{element_text}; inherits from \code{axis.text}) \cr
#' axis.text.y.right \tab y axis tick labels on right axis
#' (\code{element_text}; inherits from \code{axis.text.y}) \cr
#' axis.ticks \tab tick marks along axes
#' (\code{element_line}; inherits from \code{line}) \cr
#' axis.ticks.x \tab x axis tick marks
#' (\code{element_line}; inherits from \code{axis.ticks}) \cr
#' axis.ticks.y \tab y axis tick marks
#' (\code{element_line}; inherits from \code{axis.ticks}) \cr
#' axis.ticks.length \tab length of tick marks
#' (\code{unit}) \cr
#' axis.line \tab lines along axes
#' (\code{element_line}; inherits from \code{line}) \cr
#' axis.line.x \tab line along x axis
#' (\code{element_line}; inherits from \code{axis.line}) \cr
#' axis.line.y \tab line along y axis
#' (\code{element_line}; inherits from \code{axis.line}) \cr
#'
#' legend.background \tab background of legend
#' (\code{element_rect}; inherits from \code{rect}) \cr
#' legend.margin \tab the margin around each legend
#' (\code{margin}) \cr
#' legend.spacing \tab the spacing between legends
#' (\code{unit}) \cr
#' legend.spacing.x \tab the horizontal spacing between legends
#' (\code{unit}); inherits from \code{legend.spacing} \cr
#' legend.spacing.y \tab the horizontal spacing between legends
#' (\code{unit}); inherits from \code{legend.spacing} \cr
#' legend.key \tab background underneath legend keys
#' (\code{element_rect}; inherits from \code{rect}) \cr
#' legend.key.size \tab size of legend keys
#' (\code{unit}) \cr
#' legend.key.height \tab key background height
#' (\code{unit}; inherits from \code{legend.key.size}) \cr
#' legend.key.width \tab key background width
#' (\code{unit}; inherits from \code{legend.key.size}) \cr
#' legend.text \tab legend item labels
#' (\code{element_text}; inherits from \code{text}) \cr
#' legend.text.align \tab alignment of legend labels
#' (number from 0 (left) to 1 (right)) \cr
#' legend.title \tab title of legend
#' (\code{element_text}; inherits from \code{title}) \cr
#' legend.title.align \tab alignment of legend title
#' (number from 0 (left) to 1 (right)) \cr
#' legend.position \tab the position of legends
#' ("none", "left", "right", "bottom", "top", or two-element
#' numeric vector) \cr
#' legend.direction \tab layout of items in legends
#' ("horizontal" or "vertical") \cr
#' legend.justification \tab anchor point for positioning legend inside plot
#' ("center" or two-element numeric vector) or the
#' justification according to the plot area when positioned
#' outside the plot \cr
#' legend.box \tab arrangement of multiple legends
#' ("horizontal" or "vertical") \cr
#' legend.box.just \tab justification of each legend within the overall
#' bounding box, when there are multiple legends
#' ("top", "bottom", "left", or "right")\cr
#' legend.box.margin \tab margins around the full legend area, as specified
#' using \code{\link{margin}} \cr
#' legend.box.background \tab background of legend area
#' (\code{element_rect}; inherits from \code{rect}) \cr
#' legend.box.spacing \tab The spacing between the plotting area and the
#' legend box (\code{unit}) \cr
#'
#' panel.background \tab background of plotting area, drawn underneath plot
#' (\code{element_rect}; inherits from \code{rect}) \cr
#' panel.border \tab border around plotting area, drawn on top of plot
#' so that it covers tick marks and grid lines. This should
#' be used with \code{fill=NA}
#' (\code{element_rect}; inherits from \code{rect}) \cr
#' panel.spacing \tab spacing between facet panels
#' (\code{unit}) \cr
#' panel.spacing.x \tab horizontal spacing between facet panels
#' (\code{unit}; inherits from \code{panel.spacing}) \cr
#' panel.spacing.y \tab vertical spacing between facet panels
#' (\code{unit}; inherits from \code{panel.spacing}) \cr
#' panel.grid \tab grid lines
#' (\code{element_line}; inherits from \code{line}) \cr
#' panel.grid.major \tab major grid lines
#' (\code{element_line}; inherits from \code{panel.grid}) \cr
#' panel.grid.minor \tab minor grid lines
#' (\code{element_line}; inherits from \code{panel.grid}) \cr
#' panel.grid.major.x \tab vertical major grid lines
#' (\code{element_line}; inherits from \code{panel.grid.major}) \cr
#' panel.grid.major.y \tab horizontal major grid lines
#' (\code{element_line}; inherits from \code{panel.grid.major}) \cr
#' panel.grid.minor.x \tab vertical minor grid lines
#' (\code{element_line}; inherits from \code{panel.grid.minor}) \cr
#' panel.grid.minor.y \tab horizontal minor grid lines
#' (\code{element_line}; inherits from \code{panel.grid.minor}) \cr
#' panel.ontop \tab option to place the panel (background, gridlines)
#' over the data layers. Usually used with a transparent
#' or blank \code{panel.background}. (\code{logical}) \cr
#'
#' plot.background \tab background of the entire plot
#' (\code{element_rect}; inherits from \code{rect}) \cr
#' plot.title \tab plot title (text appearance)
#' (\code{element_text}; inherits from \code{title})
#' left-aligned by default\cr
#' plot.subtitle \tab plot subtitle (text appearance)
#' (\code{element_text}; inherits from \code{title})
#' left-aligned by default\cr
#' plot.caption \tab caption below the plot (text appearance)
#' (\code{element_text}; inherits from \code{title})
#' right-aligned by default\cr
#' plot.margin \tab margin around entire plot
#' (\code{unit} with the sizes of the top, right, bottom, and
#' left margins) \cr
#'
#' strip.background \tab background of facet labels
#' (\code{element_rect}; inherits from \code{rect}) \cr
#' strip.text \tab facet labels
#' (\code{element_text}; inherits from \code{text}) \cr
#' strip.text.x \tab facet labels along horizontal direction
#' (\code{element_text}; inherits from \code{strip.text}) \cr
#' strip.text.y \tab facet labels along vertical direction
#' (\code{element_text}; inherits from \code{strip.text}) \cr
#' strip.switch.pad.grid \tab space between strips and axes when strips are switched
#' (\code{unit}) \cr
#' strip.switch.pad.wrap \tab space between strips and axes when strips are switched
#' (\code{unit}) \cr
#' }
#'
#' @param ... a list of element name, element pairings that modify the
#' existing theme.
#' @param line all line elements (\code{element_line})
#' @param rect all rectangular elements (\code{element_rect})
#' @param text all text elements (\code{element_text})
#' @param title all title elements: plot, axes, legends (\code{element_text};
#' inherits from \code{text})
#' @param aspect.ratio aspect ratio of the panel
#'
#' @param axis.title label of axes (\code{element_text}; inherits from
#' \code{text})
#' @param axis.title.x x axis label (\code{element_text}; inherits from
#' \code{axis.title})
#' @param axis.title.x.top x axis label on top axis (\code{element_text};
#' inherits from \code{axis.title.x})
#' @param axis.title.y y axis label (\code{element_text}; inherits from
#' \code{axis.title})
#' @param axis.title.y.right y axis label on right axis (\code{element_text};
#' inherits from \code{axis.title.y})
#' @param axis.text tick labels along axes (\code{element_text}; inherits from
#' \code{text})
#' @param axis.text.x x axis tick labels (\code{element_text}; inherits from
#' \code{axis.text})
#' @param axis.text.x.top x axis tick labels on top axis (\code{element_text};
#' inherits from \code{axis.text.x})
#' @param axis.text.y y axis tick labels (\code{element_text}; inherits from
#' \code{axis.text})
#' @param axis.text.y.right y axis tick labels on right axis
#' (\code{element_text}; inherits from \code{axis.text.y})
#' @param axis.ticks tick marks along axes (\code{element_line}; inherits from
#' \code{line})
#' @param axis.ticks.x x axis tick marks (\code{element_line}; inherits from
#' \code{axis.ticks})
#' @param axis.ticks.y y axis tick marks (\code{element_line}; inherits from
#' \code{axis.ticks})
#' @param axis.ticks.length length of tick marks (\code{unit})
#' @param axis.line lines along axes (\code{element_line}; inherits from
#' \code{line})
#' @param axis.line.x line along x axis (\code{element_line}; inherits from
#' \code{axis.line})
#' @param axis.line.y line along y axis (\code{element_line}; inherits from
#' \code{axis.line})
#'
#' @param legend.background background of legend (\code{element_rect}; inherits
#' from \code{rect})
#' @param legend.margin the margin around each legend (\code{margin})
#' @param legend.spacing the spacing between legends (\code{unit})
#' @param legend.spacing.x the horizontal spacing between legends (\code{unit});
#' inherits from \code{legend.spacing}
#' @param legend.spacing.y the horizontal spacing between legends (\code{unit});
#' inherits from \code{legend.spacing}
#' @param legend.key background underneath legend keys (\code{element_rect};
#' inherits from \code{rect})
#' @param legend.key.size size of legend keys (\code{unit})
#' @param legend.key.height key background height (\code{unit}; inherits from
#' \code{legend.key.size})
#' @param legend.key.width key background width (\code{unit}; inherits from
#' \code{legend.key.size})
#' @param legend.text legend item labels (\code{element_text}; inherits from
#' \code{text})
#' @param legend.text.align alignment of legend labels (number from 0 (left) to
#' 1 (right))
#' @param legend.title title of legend (\code{element_text}; inherits from
#' \code{title})
#' @param legend.title.align alignment of legend title (number from 0 (left) to
#' 1 (right))
#' @param legend.position the position of legends ("none", "left", "right",
#' "bottom", "top", or two-element numeric vector)
#' @param legend.direction layout of items in legends ("horizontal" or
#' "vertical")
#' @param legend.justification anchor point for positioning legend inside plot
#' ("center" or two-element numeric vector) or the justification according to
#' the plot area when positioned outside the plot
#' @param legend.box arrangement of multiple legends ("horizontal" or
#' "vertical")
#' @param legend.box.just justification of each legend within the overall
#' bounding box, when there are multiple legends ("top", "bottom", "left", or
#' "right")
#' @param legend.box.margin margins around the full legend area, as specified
#' using \code{\link{margin}}
#' @param legend.box.background background of legend area (\code{element_rect};
#' inherits from \code{rect})
#' @param legend.box.spacing The spacing between the plotting area and the
#' legend box (\code{unit})
#'
#' @param panel.background background of plotting area, drawn underneath plot
#' (\code{element_rect}; inherits from \code{rect})
#' @param panel.border border around plotting area, drawn on top of plot so that
#' it covers tick marks and grid lines. This should be used with
#' \code{fill=NA}
#' (\code{element_rect}; inherits from \code{rect})
#' @param panel.spacing spacing between facet panels (\code{unit})
#' @param panel.spacing.x horizontal spacing between facet panels (\code{unit};
#' inherits from \code{panel.spacing})
#' @param panel.spacing.y vertical spacing between facet panels (\code{unit};
#' inherits from \code{panel.spacing})
#' @param panel.grid grid lines (\code{element_line}; inherits from \code{line})
#' @param panel.grid.major major grid lines (\code{element_line}; inherits from
#' \code{panel.grid})
#' @param panel.grid.minor minor grid lines (\code{element_line}; inherits from
#' \code{panel.grid})
#' @param panel.grid.major.x vertical major grid lines (\code{element_line};
#' inherits from \code{panel.grid.major})
#' @param panel.grid.major.y horizontal major grid lines (\code{element_line};
#' inherits from \code{panel.grid.major})
#' @param panel.grid.minor.x vertical minor grid lines (\code{element_line};
#' inherits from \code{panel.grid.minor})
#' @param panel.grid.minor.y horizontal minor grid lines (\code{element_line};
#' inherits from \code{panel.grid.minor})
#' @param panel.ontop option to place the panel (background, gridlines) over
#' the data layers. Usually used with a transparent or blank
#' \code{panel.background}. (\code{logical})
#'
#' @param plot.background background of the entire plot (\code{element_rect};
#' inherits from \code{rect})
#' @param plot.title plot title (text appearance) (\code{element_text}; inherits
#' from \code{title}) left-aligned by default
#' @param plot.subtitle plot subtitle (text appearance) (\code{element_text};
#' inherits from \code{title}) left-aligned by default
#' @param plot.caption caption below the plot (text appearance)
#' (\code{element_text}; inherits from \code{title}) right-aligned by default
#' @param plot.margin margin around entire plot (\code{unit} with the sizes of
#' the top, right, bottom, and left margins)
#'
#' @param strip.background background of facet labels (\code{element_rect};
#' inherits from \code{rect})
#' @param strip.text facet labels (\code{element_text}; inherits from
#' \code{text})
#' @param strip.text.x facet labels along horizontal direction
#' (\code{element_text}; inherits from \code{strip.text})
#' @param strip.text.y facet labels along vertical direction
#' (\code{element_text}; inherits from \code{strip.text})
#' @param strip.switch.pad.grid space between strips and axes when strips are
#' switched (\code{unit})
#' @param strip.switch.pad.wrap space between strips and axes when strips are
#' switched (\code{unit})
#'
#' @param ... additional element specifications not part of base ggplot2. If
#' supplied \code{validate} needs to be set to \code{FALSE}.
#' @param complete set this to TRUE if this is a complete theme, such as
#' the one returned \code{by theme_grey()}. Complete themes behave
#' differently when added to a ggplot object. Also, when setting
Expand Down Expand Up @@ -387,8 +367,27 @@ print.theme <- function(x, ...) utils::str(x)
#' p + mytheme
#'
#' }
theme <- function(..., complete = FALSE, validate = TRUE) {
elements <- list(...)
theme <- function(line, rect, text, title, aspect.ratio, axis.title,
axis.title.x, axis.title.x.top, axis.title.y,
axis.title.y.right, axis.text, axis.text.x, axis.text.x.top,
axis.text.y, axis.text.y.right, axis.ticks, axis.ticks.x,
axis.ticks.y, axis.ticks.length, axis.line, axis.line.x,
axis.line.y, legend.background, legend.margin, legend.spacing,
legend.spacing.x, legend.spacing.y, legend.key,
legend.key.size, legend.key.height, legend.key.width,
legend.text, legend.text.align, legend.title,
legend.title.align, legend.position, legend.direction,
legend.justification, legend.box, legend.box.just,
legend.box.margin, legend.box.background, legend.box.spacing,
panel.background, panel.border, panel.spacing,
panel.spacing.x, panel.spacing.y, panel.grid,
panel.grid.major, panel.grid.minor, panel.grid.major.x,
panel.grid.major.y, panel.grid.minor.x, panel.grid.minor.y,
panel.ontop, plot.background, plot.title, plot.subtitle,
plot.caption, plot.margin, strip.background, strip.text,
strip.text.x, strip.text.y, strip.switch.pad.grid,
strip.switch.pad.wrap, ..., complete = FALSE, validate = TRUE) {
elements <- find_args(..., complete = NULL, validate = NULL)

if (!is.null(elements$axis.ticks.margin)) {
warning("`axis.ticks.margin` is deprecated. Please set `margin` property ",
Expand Down
14 changes: 14 additions & 0 deletions R/utilities.r
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,20 @@ dispatch_args <- function(f, ...) {
f
}

is_missing_arg <- function(x) identical(x, quote(expr = ))
# Get all arguments in a function as a list. Will fail if an ellipsis argument
# named .ignore
# @param ... passed on in case enclosing function uses ellipsis in argument list
find_args <- function(...) {
env <- parent.frame()
args <- names(formals(sys.function(sys.parent(1))))

vals <- mget(args, envir = env)
vals <- vals[!vapply(vals, is_missing_arg, logical(1))]

modifyList(vals, list(..., `...` = NULL))
}

# Used in annotations to ensure printed even when no
# global data
dummy_data <- function() data.frame(x = NA)
Expand Down
Loading