pub struct PaintCtx<'a> {
pub recorder: &'a mut PictureRecorder,
pub rect: Rect,
pub font: &'a FontCache,
pub theme: ThemeData,
pub tree: Rc<RefCell<RenderTree>>,
pub node: NodeId,
pub owner: ComponentId,
pub clip_rect: Option<Rect>,
}Expand description
Context passed to every widget’s Widget::paint call.
Widgets push DrawCommands via the helper methods here. Nothing writes
pixels during paint — the commands are replayed by the compositor after
the full tree has been walked.
Fields§
§recorder: &'a mut PictureRecorder§rect: Rect§font: &'a FontCache§theme: ThemeData§tree: Rc<RefCell<RenderTree>>The persistent render tree (D091) — sole owner of retained per-node
state. Widgets declare hit/scroll regions, focus nodes, overlays,
and transform layers onto node; the frame pipeline derives dispatch
order and the overlay stack from the tree.
node: NodeIdThe tree node this widget declares onto.
owner: ComponentIdThe component that owns this paint subtree — node-created state (default scroll controllers, D101) subscribes it so writes repaint.
clip_rect: Option<Rect>Current clip viewport in world-space logical pixels. None means no clip.
Set by ScrollView so that register_hit ignores targets outside the
visible area, preventing phantom clicks in other panels below the fold.
Implementations§
Source§impl<'a> PaintCtx<'a>
impl<'a> PaintCtx<'a>
Sourcepub fn root(
recorder: &'a mut PictureRecorder,
rect: Rect,
font: &'a FontCache,
theme: ThemeData,
tree: Rc<RefCell<RenderTree>>,
) -> PaintCtx<'a>
pub fn root( recorder: &'a mut PictureRecorder, rect: Rect, font: &'a FontCache, theme: ThemeData, tree: Rc<RefCell<RenderTree>>, ) -> PaintCtx<'a>
Root context for a standalone paint pass (golden tests, overlay pass).
Starts a frame on tree and paints into the root node. Windowed frame
loops that interleave cached subtrees manage the tree explicitly instead.
Sourcepub fn child(&mut self, rect: Rect) -> PaintCtx<'_>
pub fn child(&mut self, rect: Rect) -> PaintCtx<'_>
Derive a child context with a different rect (reborrowing the recorder).
Consumes the next child slot of this node — the child’s previously
declared regions are cleared for re-declaration. clip_rect propagates.
Sourcepub fn child_keyed(&mut self, rect: Rect, key: u64) -> PaintCtx<'_>
pub fn child_keyed(&mut self, rect: Rect, key: u64) -> PaintCtx<'_>
Like Self::child, but the child’s node is found by an explicit
stable key (RenderTree::keyed_slot) instead of positional call
order — used ONLY by ScreenTransitionView so a screen keeps its
own scroll position/animation state across navigation instead of
aliasing onto whatever screen last occupied that tree position. See
render_tree.rs’s module doc (“Identity” section) for the full story.
Sourcepub fn register_scroll_target(
&self,
rect: Rect,
axes: ScrollAxes,
callback: Arc<dyn Fn(f32, f32) + Send + Sync>,
)
pub fn register_scroll_target( &self, rect: Rect, axes: ScrollAxes, callback: Arc<dyn Fn(f32, f32) + Send + Sync>, )
Register a scroll viewport so the event router can dispatch wheel events
to the correct ScrollView. Called from ScrollView::paint. The
callback receives (delta_x, delta_y) in logical pixels.
Sourcepub fn register_zoom_target(
&self,
rect: Rect,
callback: Arc<dyn Fn(f32) + Send + Sync>,
)
pub fn register_zoom_target( &self, rect: Rect, callback: Arc<dyn Fn(f32) + Send + Sync>, )
Register a trackpad pinch-to-zoom region (InteractiveViewer, Phase
32) — the callback receives the gesture’s raw delta (see
render_tree::ZoomRegion’s doc: an increment, not a multiplier).
Sourcepub fn register_focus(&self, node: FocusNode)
pub fn register_focus(&self, node: FocusNode)
Register a focus node for Tab-cycle inclusion (called from WithFocus<W>::paint).
Sourcepub fn register_hit(&self, callback: Arc<dyn Fn() + Send + Sync>)
pub fn register_hit(&self, callback: Arc<dyn Fn() + Send + Sync>)
Register a click callback for self.rect.
If a clip_rect is active (set by ScrollView), the hit target is
intersected with it. Targets fully outside the clip are silently dropped
so they cannot intercept clicks in other panels below the fold.
Sourcepub fn on_press(&self, f: impl Fn() + Send + Sync + 'static)
pub fn on_press(&self, f: impl Fn() + Send + Sync + 'static)
Declare that this widget’s rect responds to left-click (D099).
Sugar over PaintCtx::register_hit — clip-aware, z-order and
persistence handled by the render tree.
Sourcepub fn scroll_controller(&self) -> ScrollController
pub fn scroll_controller(&self) -> ScrollController
The implicit scroll controller for this widget’s tree node (D101):
created on first use, persists across rebuilds, subscribed to the
owning component so scroll writes repaint. This is why
ScrollView::new(child) scrolls with zero wiring.
Sourcepub fn hovered(&self) -> bool
pub fn hovered(&self) -> bool
True while the cursor is over this widget’s interactive region — paint hover feedback with it. Hover changes repaint automatically.
Sourcepub fn pressed(&self) -> bool
pub fn pressed(&self) -> bool
True from MouseDown until MouseUp while this widget is the pressed
target — pair with Self::animate_to for press/tap feedback
(D108/Phase 26 Step 1).
Sourcepub fn hoverable(&self)
pub fn hoverable(&self)
Declare a hover-only region (tooltips): participates in hover tracking without swallowing clicks.
Sourcepub fn on_long_press(&self, f: impl Fn() + Send + Sync + 'static)
pub fn on_long_press(&self, f: impl Fn() + Send + Sync + 'static)
Declare a long-press callback for this widget’s rect (fires after ~500 ms of press without movement).
Sourcepub fn set_pointer_mode(&self, mode: u8)
pub fn set_pointer_mode(&self, mode: u8)
Pointer interception for this subtree: IgnorePointer /
AbsorbPointer widgets call this — 1 = transparent, 2 = absorb.
Sourcepub fn on_press_at(&self, f: impl Fn(f32, f32) + Send + Sync + 'static)
pub fn on_press_at(&self, f: impl Fn(f32, f32) + Send + Sync + 'static)
Declare a POSITIONAL press region for this widget’s rect — the callback receives the click point in window-space logical pixels (sliders, pickers, canvases). Clip-aware like register_hit.
Sourcepub fn register_nested_scroll(
&mut self,
f: impl Fn(f32, f32) -> bool + Send + Sync + 'static,
)
pub fn register_nested_scroll( &mut self, f: impl Fn(f32, f32) -> bool + Send + Sync + 'static, )
Declares a nested-scroll chain link over this widget’s rect (see
render_tree::ScrollHandler’s doc for the full contract) — what
ScrollView’s own drag-to-pan registers instead of
Self::on_press_at, so a gesture that starts on a plain-hit
child inside it (or on an inner nested ScrollView) can still
reach it, and it in turn can hand off to whatever encloses IT once
exhausted.
Sourcepub fn on_scroll(&self, f: impl Fn(f32, f32) + Send + Sync + 'static)
pub fn on_scroll(&self, f: impl Fn(f32, f32) + Send + Sync + 'static)
Declare that this widget’s rect responds to scroll wheel/trackpad.
The callback receives (delta_x, delta_y) in logical pixels.
Sourcepub fn semantics(&self, s: Semantics)
pub fn semantics(&self, s: Semantics)
Declare semantics for this widget (D099): role, label, value. Written to the render-tree node — persists on clean frames, cleared on repaint, like every other declaration. The a11y tree is derived from the render tree each frame.
Sourcepub fn focus_node(&self) -> FocusNode
pub fn focus_node(&self) -> FocusNode
The rosace_a11y::FocusNode for this widget’s tree position —
created lazily on first paint and persists across rebuilds, the
same “zero wiring by default” precedent as Self::scroll_controller
(D101: “this is why ScrollView::new(child) scrolls with zero
wiring”). Powers TextInput’s built-in click-to-focus/Tab-cycling
(D112/Phase 28) without requiring every app to construct and wire
an explicit FocusNode for the common single-field case — apps
that DO want explicit neighbor wiring can still layer
FocusApi::focus_node on top; the two are independent focus-graph
nodes if both are used on the same widget.
Sourcepub fn focus_node_seeded(&self, seed: bool) -> FocusNode
pub fn focus_node_seeded(&self, seed: bool) -> FocusNode
Same as Self::focus_node, but if this is the FIRST paint of
this render-tree node (no focus node existed yet) and seed is
true, requests focus immediately. Backs TextInput::focused()’s
“start focused” behavior: a one-shot seed, not a per-frame
re-request — a later paint with seed == true on an
already-focus-noded position does NOT steal focus back after the
user has tabbed away.
Sourcepub fn register_editable(&self, decl: EditableDecl)
pub fn register_editable(&self, decl: EditableDecl)
Declare this widget’s rect as editable text content (D112/Phase 28
Step 1). The engine’s key/click dispatch (rosace/src/engine.rs)
finds it via the render tree, not a captured closure — see
text_edit::EditableDecl’s doc comment for why a plain
Arc<dyn Fn + Send + Sync> hit callback can’t do this job.
Sourcepub fn text_edit(&self) -> TextEditState
pub fn text_edit(&self) -> TextEditState
This widget’s persistent cursor/selection state (D091) — read
during paint to draw the caret/selection highlight. Mutated by the
engine’s key/click dispatch, never by the widget itself (paint
takes &self) — with one deliberate exception: the VIEW-state
field scrolled_cursor, written through Self::set_scrolled_cursor.
Sourcepub fn set_scrolled_cursor(&self, cursor: Option<usize>)
pub fn set_scrolled_cursor(&self, cursor: Option<usize>)
Record the caret position scroll-into-view has chased (see
TextEditState::scrolled_cursor). View state, so paint-written —
the one sanctioned widget-side write into text_edit.
Sourcepub fn set_scroll_x(&self, scroll_x: f32)
pub fn set_scroll_x(&self, scroll_x: f32)
Record the horizontal scroll-into-view offset (see
TextEditState::scroll_x) — the single-line counterpart to
set_scrolled_cursor. View state, so paint-written: TextInput
computes how far the content must shift left to keep the caret
visible when the value overflows the field, and stores it here so
it persists across repaints instead of resetting to 0.
Sourcepub fn capture(
&mut self,
rect: Rect,
paint: impl FnOnce(&mut PaintCtx<'_>),
) -> Picture
pub fn capture( &mut self, rect: Rect, paint: impl FnOnce(&mut PaintCtx<'_>), ) -> Picture
Record paint into a standalone Picture at rect, returning it —
used by RepaintBoundary to cache an expensive subtree. Runs on a fresh
child slot so interactive regions declared inside still register.
Sourcepub fn keep_child_slot(&mut self)
pub fn keep_child_slot(&mut self)
Consume the next child slot WITHOUT resetting it — preserves the subtree’s declared interactive regions across a cache-replay frame.
Sourcepub fn replay_offset(&mut self, picture: &Picture, dx: f32, dy: f32)
pub fn replay_offset(&mut self, picture: &Picture, dx: f32, dy: f32)
Replay an already-recorded Picture into this context, translating
every command by (dx, dy).
Sourcepub fn replay_morphed(&mut self, picture: &Picture, src: Rect, dst: Rect)
pub fn replay_morphed(&mut self, picture: &Picture, src: Rect, dst: Rect)
Replay a Picture captured at src instead at dst — translates
AND scales every command’s geometry, unlike Self::replay_offset’s
translate-only. Backs Hero/shared-element transitions (D108/Phase 26
Step 5): a widget’s captured appearance on one screen re-painted at a
different-sized rect on the other screen’s tagged match.
Sourcepub fn attach_overlay(&self, entry: OverlayEntry)
pub fn attach_overlay(&self, entry: OverlayEntry)
Attach an overlay entry to this node (called from WithOverlay::paint).
The entry persists on the node across cache-hit frames and is cleared
when the node repaints — open overlays cannot vanish on clean frames.
Sourcepub fn attach_transform(&self, entry: TransformLayerEntry)
pub fn attach_transform(&self, entry: TransformLayerEntry)
Attach a transform-layer entry to this node (called from
TransformLayer::paint). Persists like overlays (D087/D091).
Sourcepub fn tc(&self, c: Color) -> Color
pub fn tc(&self, c: Color) -> Color
Convert a theme color (f32 0.0–1.0) to a render color (u8 0–255).
Sourcepub fn stroke_rect(&mut self, rect: Rect, color: Color, width: f32)
pub fn stroke_rect(&mut self, rect: Rect, color: Color, width: f32)
Stroke an arbitrary rectangle.
Sourcepub fn fill_rrect(&mut self, rect: Rect, radius: f32, color: Color)
pub fn fill_rrect(&mut self, rect: Rect, radius: f32, color: Color)
Fill a rounded rectangle with corner radius radius.
Sourcepub fn fill_circle(&mut self, center: Point, radius: f32, color: Color)
pub fn fill_circle(&mut self, center: Point, radius: f32, color: Color)
Fill a circle.
Sourcepub fn backdrop_blur(&mut self, rect: Rect, radius: f32, blur: f32, tint: Color)
pub fn backdrop_blur(&mut self, rect: Rect, radius: f32, blur: f32, tint: Color)
Frosted-glass panel (D-DEF-012): blurs and tints everything already
painted beneath rect behind a rounded panel — real backdrop
glassmorphism on GPU-composited targets (CPU fallback: translucent
tint, no blur). blur is the Gaussian strength in logical px;
tint.a controls how strongly the tint mixes over the blur.
Sourcepub fn shader_fill(
&mut self,
rect: Rect,
pipeline: PipelineId,
uniforms: Vec<u8>,
)
pub fn shader_fill( &mut self, rect: Rect, pipeline: PipelineId, uniforms: Vec<u8>, )
Fill rect with a registered GPU shader pipeline (D109/Phase 27).
uniforms come from a #[derive(ShaderUniforms)] struct’s
to_bytes(). The pipeline must have been registered via
rosace_shader::register_shader (compiled eagerly at the next frame
boundary). Executes on the GPU at present time — this records a
command, like every other helper here, and never touches pixels.
Renders on GPU-composited targets only (desktop/mobile); web and the
softbuffer fallback drop it (Phase 27’s documented scope).
Sourcepub fn shader_fill_animated(
&mut self,
rect: Rect,
pipeline: PipelineId,
uniforms: Vec<u8>,
)
pub fn shader_fill_animated( &mut self, rect: Rect, pipeline: PipelineId, uniforms: Vec<u8>, )
Self::shader_fill with the D109-maturity animation flag: the
PLATFORM patches the first 4 uniform bytes (the time-first
convention) with a live clock at every present, so continuous
animation costs a GPU buffer write per frame — record once, never
repaint, no request_animation loop.
Sourcepub fn draw_text_at(&mut self, text: &str, origin: Point, color: Color, px: f32)
pub fn draw_text_at(&mut self, text: &str, origin: Point, color: Color, px: f32)
Draw text at an absolute position (not relative to self.rect).
Sourcepub fn text(&mut self, s: &str, dx: f32, dy: f32, color: Color, px: f32)
pub fn text(&mut self, s: &str, dx: f32, dy: f32, color: Color, px: f32)
Draw text at (self.rect.origin + (dx, dy)).
Sourcepub fn text_styled(
&mut self,
s: &str,
dx: f32,
dy: f32,
color: Color,
px: f32,
weight: FontWeight,
)
pub fn text_styled( &mut self, s: &str, dx: f32, dy: f32, color: Color, px: f32, weight: FontWeight, )
Draw text at (self.rect.origin + (dx, dy)) with an explicit weight —
SemiBold/Bold route to the real bold face.
Sourcepub fn fill_shadow(&mut self, rect: Rect, color: Color, blur: f32)
pub fn fill_shadow(&mut self, rect: Rect, color: Color, blur: f32)
Emit a blurred drop shadow behind a square-cornered rect.
Sourcepub fn fill_shadow_rrect(
&mut self,
rect: Rect,
radius: f32,
color: Color,
blur: f32,
)
pub fn fill_shadow_rrect( &mut self, rect: Rect, radius: f32, color: Color, blur: f32, )
Emit a blurred drop shadow behind a rounded rect. radius must match
the widget’s corner radius so the shadow hugs the rounded shape.
Sourcepub fn stroke_rrect(
&mut self,
rect: Rect,
radius: f32,
color: Color,
width: f32,
)
pub fn stroke_rrect( &mut self, rect: Rect, radius: f32, color: Color, width: f32, )
Stroke a rounded-rect outline matching PaintCtx::fill_rrect geometry.
Sourcepub fn fill_gradient(
&mut self,
rect: Rect,
radius: f32,
from: Color,
to: Color,
vertical: bool,
)
pub fn fill_gradient( &mut self, rect: Rect, radius: f32, from: Color, to: Color, vertical: bool, )
Fill a (rounded) rect with a two-stop linear gradient.
Sourcepub fn fill_arc(
&mut self,
center: Point,
radius: f32,
thickness: f32,
start_deg: f32,
sweep_deg: f32,
color: Color,
)
pub fn fill_arc( &mut self, center: Point, radius: f32, thickness: f32, start_deg: f32, sweep_deg: f32, color: Color, )
Draw a ring segment (progress arc / spinner).
Sourcepub fn request_animation(&self)
pub fn request_animation(&self)
Request another frame — self-animating widgets (spinner, shimmer) call this each paint so the frame loop keeps repainting them.
Sourcepub fn animate_to(&self, target: f32, duration_ms: f32) -> f32
pub fn animate_to(&self, target: f32, duration_ms: f32) -> f32
Ease this node’s persistent scalar toward target and return the
current value. Honors the theme’s global [AnimationConfig]: when
disabled it snaps; otherwise it exponentially eases over the theme’s
duration (or duration_ms if > 0) and keeps requesting frames until
settled. This is how Switch/Checkbox/Radio animate WITHOUT any per-
widget state — the animation policy is global (theme), the value is
per-node. First observation snaps (no appear-animation).
Sourcepub fn seed_anim_if_unset(&self, value: f32)
pub fn seed_anim_if_unset(&self, value: f32)
Seeds this node’s persistent animated scalar to value — but ONLY
if it has never been observed before (None). An already-set value
is left untouched. Pairs with animate_to to opt OUT of its “first
observation snaps straight to target” behavior for a genuine
appear-animation: call this with the START value (e.g. 0.0)
before the first animate_to call on a node that should visibly
ease in rather than pop in fully-formed — e.g. an image fading in
from 0 opacity the first frame it has real decoded content
(D108/Phase 26 Step 4), not fully-formed from frame one.
Sourcepub fn set_anim(&self, value: f32)
pub fn set_anim(&self, value: f32)
Unconditionally sets this node’s persistent animated scalar (the same
one animate_to eases) to value — unlike seed_anim_if_unset, this
always overwrites. For a widget that renders its OWN live value
alongside animate_to’s eased one (a drag gesture’s raw finger
offset, summed with the eased snap-to-page position — see
Carousel): call this right before switching animate_to’s target
so the eased value starts from wherever the combined visual position
actually was, instead of jumping from the stale pre-drag value and
losing the live offset in the same frame (found live: released a
carousel drag past the swipe threshold and the page visibly popped
before easing, instead of continuing smoothly from the finger).
Sourcepub fn animate_channel(
&self,
channel: usize,
target: f32,
duration_ms: f32,
) -> f32
pub fn animate_channel( &self, channel: usize, target: f32, duration_ms: f32, ) -> f32
Ease the channel-th independent animated scalar of this node toward
target and return the current value. This is the multi-value sibling
of Self::animate_to: a widget that must animate more than one thing
at once (a Switch’s thumb position AND its hover/press state-layer,
a Slider’s fill AND its thumb halo) gives each its own channel.
Channels are independent persistent scalars keyed by the explicit
channel index — no call-order coupling, so branches that skip a
channel some frames don’t shift the others. Identical easing policy to
animate_to: honors the theme’s global AnimationConfig (snaps when
disabled), exponentially eases over the theme duration (or duration_ms
if > 0), first observation snaps (no appear-pop), and keeps requesting
frames until settled.
Sourcepub fn seed_channel_if_unset(&self, channel: usize, value: f32)
pub fn seed_channel_if_unset(&self, channel: usize, value: f32)
Seed an animate_channel channel to value
ONLY if it has never been observed — the multi-channel sibling of
seed_anim_if_unset. Use it to opt a
channel OUT of animate_channel’s “first observation snaps” behaviour so
it visibly eases FROM value on the first frame (e.g. a clock hand
starting at 12:00 and sweeping to the current time).
Sourcepub fn anim_channel(&self, channel: usize) -> Option<f32>
pub fn anim_channel(&self, channel: usize) -> Option<f32>
Read an animation channel’s current value (see animate_channel),
without advancing it — for widgets that need the settled position to
compute a shortest-path target (e.g. a clock hand crossing 12).
Sourcepub fn pointer(&self) -> Point
pub fn pointer(&self) -> Point
The latest pointer position (window-space logical px) — for a widget
that follows the finger during a drag (e.g. a clock hand). Combine with
Self::pressed: while pressed, draw at the raw pointer angle (smooth);
on release, snap to the nearest value.
Sourcepub fn set_anim_channel(&self, channel: usize, value: f32)
pub fn set_anim_channel(&self, channel: usize, value: f32)
Snap an animation channel to value immediately (no easing) — for
obeying a live drag: the hand tracks the finger exactly instead of
lagging behind an ease.
Sourcepub fn record(&mut self, cmd: DrawCommand)
pub fn record(&mut self, cmd: DrawCommand)
Push a raw DrawCommand for advanced use.
Sourcepub fn layout_ctx(&self, constraints: Constraints) -> LayoutCtx<'_>
pub fn layout_ctx(&self, constraints: Constraints) -> LayoutCtx<'_>
Create a LayoutCtx from this paint context.
Needed when a widget measures children inside paint() (e.g. to position
them). Uses the available rect as tight constraints.