File: sizing.R

package info (click to toggle)
r-cran-htmlwidgets 1.3%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 456 kB
  • sloc: makefile: 2
file content (230 lines) | stat: -rw-r--r-- 9,983 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
#' Create a widget sizing policy
#'
#' Define the policy by which HTML widgets will be sized in various containers
#' (e.g. Browser, RStudio Viewer, R Markdown, Shiny). Note that typically
#' widgets can accept the default sizing policy (or override only one or two
#' aspects of it) and get satisfactory sizing behavior via the automatic sizing
#' logic built into the htmlwidgets framework (see the notes below for the most
#' typical exceptions to this).
#'
#' @param defaultWidth The default width used to display the widget. This
#'   parameter specifies the default width for viewing in all contexts (browser,
#'   viewer, and knitr) unless it is specifically overridden with e.g.
#'   \code{browser.defaultWidth}.
#' @param viewer.defaultWidth The default width used to display the widget
#'   within the RStudio Viewer.
#' @param browser.defaultWidth The default width used to display the widget
#'   within a standalone web browser.
#' @param knitr.defaultWidth The default width used to display the widget within
#'   documents generated by knitr (e.g. R Markdown).
#' @param defaultHeight The default height used to display the widget. This
#'   parameter specifies the default height for viewing in all contexts
#'   (browser, viewer, and knitr) unless it is specifically overridden with e.g.
#'   \code{browser.defaultHeight}.
#' @param viewer.defaultHeight The default height used to display the widget
#'   within the RStudio Viewer.
#' @param browser.defaultHeight The default height used to display the widget
#'   within a standalone web browser.
#' @param knitr.defaultHeight The default height used to display the widget
#'   within documents generated by knitr (e.g. R Markdown).
#' @param padding Padding around the widget (in pixels). This parameter
#'   specifies the padding for viewing in all contexts (browser and viewer)
#'   unless it is specifically overriden by e.g. \code{browser.padding}.
#' @param browser.padding Padding around the widget when displayed in a
#'   standalone browser (defaults to 40 pixels).
#' @param viewer.padding Padding around the widget when displayed in the RStudio
#'   Viewer (defaults to 15 pixels).
#' @param viewer.fill When displayed in the RStudio Viewer, automatically size
#'   the widget to the viewer dimensions (note that \code{viewer.padding} is
#'   still applied). Default to \code{TRUE}.
#' @param browser.fill When displayed in a standalone web browser, automatically
#'   size the widget to the browser dimensions (note that \code{browser.padding}
#'   is still applied). Defaults to \code{FALSE}.
#' @param browser.external When displaying in a browser, always use an external
#'   browser (via \code{browseURL()}). Defaults to \code{FALSE}, which will
#'   result in the use of an internal browser within RStudio v1.1 and higher.
#' @param viewer.paneHeight Request that the RStudio Viewer be forced to a
#'   specific height when displaying this widget.
#' @param viewer.suppress Never display the widget within the RStudio Viewer
#'   (useful for widgets that require a large amount of space for rendering).
#'   Defaults to \code{FALSE}.
#' @param knitr.figure Apply the default knitr fig.width and fig.height to the
#'   widget when it's rendered within R Markdown documents. Defaults to
#'   \code{TRUE}.
#'
#' @return A widget sizing policy
#'
#' @details
#'
#' The default HTML widget sizing policy treats the widget with the same sizing
#' semantics as an R plot. When printed at the R console the widget is displayed
#' within the RStudio Viewer and sized to fill the Viewer pane (modulo any
#' padding). When rendered inside an R Markdown document the widget is sized
#' based on the default size of figures in the document.
#'
#' You might need to change the default behavior if your widget is extremely
#' large. In this case you might specify \code{viewer.suppress = TRUE} and
#' \code{knitr.figure = FALSE} as well provide for a larger default width and
#' height for knitr.
#'
#' You also might need to change the default behavior if you widget already
#' incorporates padding. In this case you might specify \code{viewer.padding =
#' 0}.
#'
#' For additional details on widget sizing:
#'
#' \code{vignette("develop_sizing", package = "htmlwidgets")}
#'
#'
#' @export
sizingPolicy <- function(
  defaultWidth = NULL, defaultHeight = NULL, padding = NULL,
  viewer.defaultWidth = NULL, viewer.defaultHeight = NULL,
  viewer.padding = NULL, viewer.fill = TRUE, viewer.suppress = FALSE,
  viewer.paneHeight = NULL,
  browser.defaultWidth = NULL, browser.defaultHeight = NULL,
  browser.padding = NULL, browser.fill = FALSE, browser.external = FALSE,
  knitr.defaultWidth = NULL, knitr.defaultHeight = NULL,
  knitr.figure = TRUE) {

  list(
    defaultWidth = defaultWidth,
    defaultHeight = defaultHeight,
    padding = padding,
    viewer = list(
      defaultWidth = viewer.defaultWidth,
      defaultHeight = viewer.defaultHeight,
      padding = viewer.padding,
      fill = viewer.fill,
      suppress = viewer.suppress,
      paneHeight = viewer.paneHeight
    ),
    browser = list(
      defaultWidth = browser.defaultWidth,
      defaultHeight = browser.defaultHeight,
      padding = browser.padding,
      fill = browser.fill,
      external = browser.external
    ),
    knitr = list(
      defaultWidth = knitr.defaultWidth,
      defaultHeight = knitr.defaultHeight,
      figure = knitr.figure
    )
  )
}


DEFAULT_WIDTH <- 960
DEFAULT_HEIGHT <- 500
DEFAULT_PADDING <- 40
DEFAULT_WIDTH_VIEWER <- 450
DEFAULT_HEIGHT_VIEWER <- 350
DEFAULT_PADDING_VIEWER <- 15

#' Resolve widget sizing policy
#'
#' Take a widget object and sizing policy, and some other contextual details,
#' and figure out what width/height to use, if possible. Some decisions may need
#' to be deferred until runtime; include any metadata that's needed for that
#' decision in the result as well.
#'
#' @param x The widget object whose size is to be determined. It may have $width
#'   and $height directly on it, which means we should obey those.
#' @param sp The sizing policy to use.
#' @param standalone Logical value indicating whether the widget is being
#'   rendered in a standalone context (where it's the only thing on the page;
#'   this is usually via `print.htmlwidget()`).
#' @param knitrOptions Object representing the knitr options passed to us via
#'   `knit_print`. If we're not doing a `knit_print` right now, then the value
#'   should be `NULL`.
#' @return A list that is guaranteed to have `width` and `height` values, each of
#'   which is either a number or CSS unit string. If `standalone=TRUE` then the
#'   list will also have a `runtime` value that is a list, that contains two
#'   nested lists `viewer` and `browser`. Each of those in turn has `width`,
#'   `height`, `padding` (between 1 and 4 numbers), and `fill` (`TRUE`/`FALSE`).
#' @keywords internal
#' @examples
#' x <- list(
#'   sizingPolicy = list(
#'     defaultWidth = 800,
#'     defaultHeight = 500,
#'     padding = 15,
#'     viewer = list(
#'       fill = TRUE,
#'       padding = 0
#'     ),
#'     browser = list(
#'       fill = FALSE,
#'       defaultWidth = 960,
#'       defaultHeight = 600,
#'       padding = 20
#'     ),
#'     knitr = list(
#'       # Actually knitr$defaultWidth and knitr$defaultHeight
#'       # are ignored if figure = TRUE
#'       defaultWidth = 800,
#'       defaultHeight = 600,
#'       figure = TRUE
#'     )
#'   )
#' )
#'
#' # Sizing for standalone mode
#' str(resolveSizing(x, x$sizingPolicy, TRUE, NULL))
#' # Sizing for knitr
#' str(resolveSizing(x, x$sizingPolicy, FALSE,
#'   list(out.width.px = 150, out.height.px = 100)))
#'
#' # Explicit width/height provided by user--overrides any
#' # default width/height
#' x$width <- 300
#' x$height <- 250
#' str(resolveSizing(x, x$sizingPolicy, FALSE,
#'   list(out.width.px = 150, out.height.px = 100)))
#' @keywords internal
#' @noRd
resolveSizing <- function(x, sp, standalone, knitrOptions = NULL) {
  if (isTRUE(standalone)) {
    userSized <- !is.null(x$width) || !is.null(x$height)
    viewerScopes <- list(sp$viewer, sp)
    browserScopes <- list(sp$browser, sp)
    # Precompute the width, height, padding, and fill for each scenario.
    return(list(
      runtime = list(
        viewer = list(
          width = x$width %||% any_prop(viewerScopes, "defaultWidth") %||% DEFAULT_WIDTH_VIEWER,
          height = x$height %||% any_prop(viewerScopes, "defaultHeight") %||% DEFAULT_HEIGHT_VIEWER,
          padding = any_prop(viewerScopes, "padding") %||% DEFAULT_PADDING_VIEWER,
          fill = !userSized && any_prop(viewerScopes, "fill") %||% TRUE
        ),
        browser = list(
          width = x$width %||% any_prop(browserScopes, "defaultWidth") %||% DEFAULT_WIDTH,
          height = x$height %||% any_prop(browserScopes, "defaultHeight") %||% DEFAULT_HEIGHT,
          padding = any_prop(browserScopes, "padding") %||% DEFAULT_PADDING,
          fill = !userSized && any_prop(browserScopes, "fill") %||% FALSE
        )
      ),
      width = x$width %||% prop(sp, "defaultWidth") %||% DEFAULT_WIDTH,
      height = x$height %||% prop(sp, "defaultHeight") %||% DEFAULT_HEIGHT
    ))
  } else if (!is.null(knitrOptions)) {
    knitrScopes <- list(sp$knitr, sp)
    isFigure <- any_prop(knitrScopes, "figure")
    figWidth <- if (isFigure) knitrOptions$out.width.px else NULL
    figHeight <- if (isFigure) knitrOptions$out.height.px else NULL
    # Compute the width and height
    return(list(
      width = x$width %||% figWidth %||% any_prop(knitrScopes, "defaultWidth") %||% DEFAULT_WIDTH,
      height = x$height %||% figHeight %||% any_prop(knitrScopes, "defaultHeight") %||% DEFAULT_HEIGHT
    ))
  } else {
    # Some non-knitr, non-print scenario.
    # Just resolve the width/height vs. defaultWidth/defaultHeight
    return(list(
      width = x$width %||% prop(sp, "defaultWidth") %||% DEFAULT_WIDTH,
      height = x$height %||% prop(sp, "defaultHeight") %||% DEFAULT_HEIGHT
    ))
  }
}