Skip to main content

PaintCtx

Struct PaintCtx 

Source
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: NodeId

The tree node this widget declares onto.

§owner: ComponentId

The 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>

Source

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.

Source

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.

Source

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.

Source

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.

Source

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).

Source

pub fn register_focus(&self, node: FocusNode)

Register a focus node for Tab-cycle inclusion (called from WithFocus<W>::paint).

Source

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.

Source

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.

Source

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.

Source

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.

Source

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).

Source

pub fn hoverable(&self)

Declare a hover-only region (tooltips): participates in hover tracking without swallowing clicks.

Source

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).

Source

pub fn set_pointer_mode(&self, mode: u8)

Pointer interception for this subtree: IgnorePointer / AbsorbPointer widgets call this — 1 = transparent, 2 = absorb.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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).

Source

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.

Source

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.

Source

pub fn attach_transform(&self, entry: TransformLayerEntry)

Attach a transform-layer entry to this node (called from TransformLayer::paint). Persists like overlays (D087/D091).

Source

pub fn tc(&self, c: Color) -> Color

Convert a theme color (f32 0.0–1.0) to a render color (u8 0–255).

Source

pub fn fill(&mut self, color: Color)

Fill self.rect with a solid color.

Source

pub fn stroke(&mut self, color: Color, width: f32)

Stroke the outline of self.rect.

Source

pub fn fill_rect(&mut self, rect: Rect, color: Color)

Fill an arbitrary rectangle.

Source

pub fn stroke_rect(&mut self, rect: Rect, color: Color, width: f32)

Stroke an arbitrary rectangle.

Source

pub fn fill_rrect(&mut self, rect: Rect, radius: f32, color: Color)

Fill a rounded rectangle with corner radius radius.

Source

pub fn fill_circle(&mut self, center: Point, radius: f32, color: Color)

Fill a circle.

Source

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.

Source

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).

Source

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.

Source

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).

Source

pub fn text(&mut self, s: &str, dx: f32, dy: f32, color: Color, px: f32)

Draw text at (self.rect.origin + (dx, dy)).

Source

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.

Source

pub fn fill_shadow(&mut self, rect: Rect, color: Color, blur: f32)

Emit a blurred drop shadow behind a square-cornered rect.

Source

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.

Source

pub fn stroke_rrect( &mut self, rect: Rect, radius: f32, color: Color, width: f32, )

Stroke a rounded-rect outline matching PaintCtx::fill_rrect geometry.

Source

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.

Source

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).

Source

pub fn request_animation(&self)

Request another frame — self-animating widgets (spinner, shimmer) call this each paint so the frame loop keeps repainting them.

Source

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).

Source

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.

Source

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).

Source

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.

Source

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).

Source

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).

Source

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.

Source

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.

Source

pub fn record(&mut self, cmd: DrawCommand)

Push a raw DrawCommand for advanced use.

Source

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.

Auto Trait Implementations§

§

impl<'a> !RefUnwindSafe for PaintCtx<'a>

§

impl<'a> !Send for PaintCtx<'a>

§

impl<'a> !Sync for PaintCtx<'a>

§

impl<'a> !UnwindSafe for PaintCtx<'a>

§

impl<'a> Freeze for PaintCtx<'a>

§

impl<'a> Unpin for PaintCtx<'a>

§

impl<'a> UnsafeUnpin for PaintCtx<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.