Skip to contents

The single public server-side entry point for a ggpaintr formula, used identically at L2 (default layout via ptr_ui()) and L3 (your own hand-composed layout from the bare ptr_ui_* pieces). It namespaces and wires the whole reactive engine, registers the built-in ptr_plot / ptr_error / ptr_code outputs (a piece you never place in the UI is a harmless no-op), and returns the ptr_state so you can drive a custom renderer. Additional arguments are forwarded to ptr_init_state() (e.g. shared, draw_trigger, expr_check, safe_to_remove, ui_text).

Usage

ptr_server(
  formula,
  id = NULL,
  envir = parent.frame(),
  ...,
  shared_state = NULL,
  spec = NULL
)

Arguments

formula

Either a single character scalar containing a ggplot expression with ggpaintr placeholders, or an unquoted ggplot expression supplied directly. See ptr_app() for the full contract (expression capture via rlang::enexpr(), symbol resolution, wrapper unwrap, and the native-pipe caveat in expression mode).

id

Optional module id; must match the id passed to ptr_ui() or to the bare L3 pieces. Defaults to NULL (identity namespace, single-instance use).

envir

Environment used to resolve local data objects.

...

Forwarded to ptr_init_state().

shared_state

Optional ptr_shared_state returned by ptr_shared_server(). When supplied, populates shared, draw_trigger, and shared_resolutions defaults. Required when the formula declares a shared = "..." placeholder driven by a cross-formula ptr_shared_panel() and the equivalent ... arguments are not supplied directly.

spec

An optional named list of fully-qualified Shiny input id -> value, used to override widget defaults at session boot.

Value

The ptr_state list from ptr_init_state(). This is the supported L3 custom-render handle: state$runtime()$plot / $code / $error. (Its server_ns_fn / ui_ns_fn slots are internal plumbing — not a public escape hatch.)

Custom render (L3)

Custom rendering is UI-side: place your own output widget (e.g. plotly::plotlyOutput()) at shiny::NS(id)("my_plot"), never place ptr_ui_plot(), and read the live plot off the returned state — there is no user-authored moduleServer wrapping any ggpaintr engine and no lower-level server function to reach for:

# server:
state <- ptr_server(formula, "p")
output$my_plot <- plotly::renderPlotly(state$runtime()$plot)
# ui: plotly::plotlyOutput(shiny::NS("p")("my_plot"))

state$runtime() is reactive; $plot is the built ggplot/ggplot-like object, $code the generated source string, $error any inline error. See vignette("ggpaintr-tutorial").

For cross-formula coordination — multiple ggpaintr instances driven by one widget — build the coordinator with ptr_shared_server() and pass the returned ptr_shared_state as shared_state =. The state's shared / draw_trigger / shared_resolutions slots are unpacked and forwarded to ptr_init_state(); if an explicit shared = ... / draw_trigger = ... / shared_resolutions = ... is also passed via ..., that explicit value wins. A single formula with shared = "..." placeholders needs no shared_stateptr_server() self-binds every declared key under its own namespace, matching what ptr_app() does.

Examples

if (interactive()) {
  f <- rlang::expr(ggplot(mtcars, aes(x = ppVar, y = ppVar)) + geom_point())
  # L2: default layout
  shiny::shinyApp(
    ui = shiny::fluidPage(ptr_ui(!!f, "p")),
    server = function(input, output, session) {
      ptr_server(!!f, "p")
    }
  )
  # L3: own the render path off the returned state
  shiny::shinyApp(
    ui = ptr_ui_page(
      ptr_ui_controls(formula = !!f, id = "p"),
      plotly::plotlyOutput(shiny::NS("p")("my_plot"))
    ),
    server = function(input, output, session) {
      state <- ptr_server(!!f, "p")
      output[[shiny::NS("p")("my_plot")]] <-
        plotly::renderPlotly(state$runtime()$plot)
    }
  )
}