pub struct BuildContext<'a> { /* private fields */ }Expand description
Context available during Widget::build().
Implementations§
Source§impl<'a> BuildContext<'a>
impl<'a> BuildContext<'a>
Sourcepub fn add_boxed(&mut self, widget: Box<dyn Widget>) -> WidgetId
pub fn add_boxed(&mut self, widget: Box<dyn Widget>) -> WidgetId
Add a pre-boxed widget to the tree.
Sourcepub fn add_detached(&mut self, widget: impl Widget + 'static) -> WidgetId
pub fn add_detached(&mut self, widget: impl Widget + 'static) -> WidgetId
Add a parentless widget this one owns: pre-built overlay content (a dropdown menu, a date picker’s calendar, a tooltip’s nested cascade children) that must not be reached by the child walk.
Use this — never a bare add — for anything built ahead of
time and parked with set_dormant to be shown later
through an overlay. The two differ only in bookkeeping: add hands back
a node nothing owns, so the builder’s own teardown cannot reach it and
every rebuild strands another copy in the arena; this records the
ownership edge, so the node dies with its owner and the previous
generation dies with each rebuild.
Content that can be a child should be returned from build() as one
instead. This exists for content that cannot: activation and the paint
walk both descend through children, so a dormant popup parked there
wakes with its host and paints inline at zero size.
Sourcepub fn add_deferred(
&mut self,
reveal: Signal<bool>,
widget: impl Widget + 'static,
) -> WidgetId
pub fn add_deferred( &mut self, reveal: Signal<bool>, widget: impl Widget + 'static, ) -> WidgetId
Insert a child whose subtree is not built until reveal first turns
true, and is retained from then on. Returns the host’s id immediately.
The shape this replaces is ctx.add(panel) followed by
ctx.set_dormant(id) — correct, but it builds content the user may never
open, on every rebuild of the owner. In a virtualized collection the
owner is a per-row delegate, so that cost is multiplied by the row count:
on a 40-row table whose cells each carried a four-item menu, the eager
form cost 325–552 ms per rebuild against 42–46 ms without the column at
all, and ~85% of it was the add rather than constructing the widget
value. See DeferredSubtree
for the full contract.
Pass the same signal the content’s visible_when gate uses. Everything
downstream of the returned id — set_dormant / activate,
visible_when, OverlayRequest::content_id, descendant checks,
dismissal — is unchanged; only when the subtree below it exists moves.
Sourcepub fn add_deferred_boxed(
&mut self,
reveal: Signal<bool>,
widget: Box<dyn Widget>,
) -> WidgetId
pub fn add_deferred_boxed( &mut self, reveal: Signal<bool>, widget: Box<dyn Widget>, ) -> WidgetId
add_deferred for an already-boxed widget.
Sourcepub fn add_deferred_on_demand(
&mut self,
widget: impl Widget + 'static,
) -> WidgetId
pub fn add_deferred_on_demand( &mut self, widget: impl Widget + 'static, ) -> WidgetId
add_deferred for content the framework
materializes, kept as a child of the builder.
The parented twin of
add_detached_deferred_on_demand,
for the two rich-tooltip attach paths: they have always parented their
body on the anchor’s owner, and reparenting them to detached would move
which teardown reaps them. Only when the body is built changes.
Worth the separate entry point because a rich tooltip is not one widget:
RichTooltipWidget::build eagerly pre-creates a nested tooltip for every
:key link in its body, recursively, so one attached tip expands into a
cascade. Built eagerly on a data view’s row delegate, 29 rows of
Skribisto’s Overview carried 1,305 tooltip widgets inside a 22,737-node
subtree, and tearing that down cost 5.3 s per arrow-key press — the
destroy, not the build.
Sourcepub fn add_detached_deferred_on_demand(
&mut self,
widget: impl Widget + 'static,
) -> WidgetId
pub fn add_detached_deferred_on_demand( &mut self, widget: impl Widget + 'static, ) -> WidgetId
add_deferred for content the framework
materializes rather than a widget’s own open signal.
The tooltip case: a tooltip body has no open signal a widget could hand
over — the tree decides, when a dwell matures. WidgetTree forces such
a host just before it consults Widget::tooltip_has_content, so the
body exists by the time anything asks it a question.
Sourcepub fn add_detached_deferred_boxed(
&mut self,
reveal: Signal<bool>,
widget: Box<dyn Widget>,
) -> WidgetId
pub fn add_detached_deferred_boxed( &mut self, reveal: Signal<bool>, widget: Box<dyn Widget>, ) -> WidgetId
add_deferred, inserted detached — the shape
overlay content wants, so it is owned by the builder and dies with it
rather than outliving every menu the user ever opened.
Sourcepub fn add_detached_deferred(
&mut self,
reveal: Signal<bool>,
widget: impl Widget + 'static,
) -> WidgetId
pub fn add_detached_deferred( &mut self, reveal: Signal<bool>, widget: impl Widget + 'static, ) -> WidgetId
add_detached_deferred_boxed for an
unboxed widget.
Sourcepub fn add_detached_boxed(&mut self, widget: Box<dyn Widget>) -> WidgetId
pub fn add_detached_boxed(&mut self, widget: Box<dyn Widget>) -> WidgetId
add_detached for an already-boxed widget.
Sourcepub fn add_child(
&mut self,
parent: WidgetId,
widget: impl Widget + 'static,
) -> WidgetId
pub fn add_child( &mut self, parent: WidgetId, widget: impl Widget + 'static, ) -> WidgetId
Add a Level 2 widget as a child of another widget.
Sourcepub fn animated_signal(&mut self, value: f32) -> Signal<f32>
pub fn animated_signal(&mut self, value: f32) -> Signal<f32>
Create a new Signal<f32> that supports animate_to().
Registered with the animation scheduler automatically. The owning
widget (self_id()) is recorded so that the scheduler can pause
the animation when the widget is offscreen, dormant, or rebuilt.
Sourcepub fn register_animated_signal(&mut self, signal: &Signal<f32>)
pub fn register_animated_signal(&mut self, signal: &Signal<f32>)
Register a pre-existing Signal<f32> for animation support.
Use this when the signal was created outside of build() (e.g. in the
widget constructor) and needs to be registered with the animation scheduler.
Sourcepub fn prefers_reduced_motion(&self) -> bool
pub fn prefers_reduced_motion(&self) -> bool
Read the OS-level prefers-reduced-motion preference. Widgets
that use looping or decorative animations (spinners, sprite
icons, marquee text, etc.) should skip starting them when this
returns true so the UI respects accessibility settings and —
as a bonus — draws no CPU/GPU.
Sourcepub fn animate(&self) -> AnimationSpec
pub fn animate(&self) -> AnimationSpec
Build an AnimationSpec
— the fluent ergonomic façade over Signal<f32>::animate_to.
Captures the theme’s MotionTokens and the platform
reduced-motion preference at build time, returns a clonable
spec that event-handler closures can drive without
re-threading durations and easing.
let knob_anim = ctx.animate().fast().standard();
handlers = handlers.on_tap(move |_, _| {
knob_anim.to_or_snap(&knob_position, target);
});Sourcepub fn animated_quad(&mut self, kind: AnimatedQuadKind) -> AnimatedQuadHandle
pub fn animated_quad(&mut self, kind: AnimatedQuadKind) -> AnimatedQuadHandle
Opt into the shader-driven animated-quad pipeline. The widget
paint() emits ONE canvas.draw_animated_quad(bounds, handle.slot(), class) call; the renderer samples per-slot state from its
uniform buffer each frame and the widget’s paint() does not
re-run for animation ticks — only on layout changes. The
returned handle is stable for the widget-mount lifetime and
should be stashed on self to thread to paint().
For decorative motion that isn’t a quad (scroll-offset tweens,
sidebar slide, toggle knob), keep using ctx.animated_signal +
signal.animate_looping — both paths coexist.
Sourcepub fn frame_tick(&self) -> Signal<f32>
pub fn frame_tick(&self) -> Signal<f32>
The per-frame delta-seconds signal. Observe it via
ctx.effect(&ctx.frame_tick(), |delta| ...) to run code once per
frame the tree was explicitly asked to pump. Merely observing
this signal does not keep the event loop awake — widgets must
call request_frame (typically from an
event handler or from inside the tick closure itself) to schedule
the next wake-up. This preserves Teksilo’s draw-when-needed model.
Sourcepub fn request_frame(&self)
pub fn request_frame(&self)
Ask the tree to pump exactly one more frame. See
frame_tick for the observer side.
Sourcepub fn request_accessibility_update(&self)
pub fn request_accessibility_update(&self)
Request that the AccessKit tree be re-walked after this build pass.
Use when build() restructured its subtree in a way that changes the
accessibility tree (relayout alone no longer re-walks AT). SceneView
calls this each build, since it may have materialised or destroyed
scene widgets or applied a11y-only scene mutations.
Sourcepub fn frame_request_handle(&self) -> Rc<Cell<bool>>
pub fn frame_request_handle(&self) -> Rc<Cell<bool>>
Clone the shared “frame requested” flag. Stash it on widget
state and call .set(true) from inside a frame-tick effect
closure to chain-request another frame without needing
mutable access to the tree. Used by widgets with continuous
frame needs (caret blink, drag auto-scroll, smooth
animations driven from a tick closure).
Prefer subscribe_frame_tick
for visual-only continuous animations (Pulse, Cycle, …): the
scheduler-backed path automatically pauses the chain when the
owner widget is hidden, while this raw handle keeps the event
loop pumping at full frame rate regardless of visibility.
Sourcepub fn subscribe_frame_tick(&self) -> FrameTickSubscription
pub fn subscribe_frame_tick(&self) -> FrameTickSubscription
Subscribe the widget being built to the per-frame-effect
scheduler. The returned RAII guard removes the subscription on
drop — store it on self so its lifetime tracks the widget’s.
While at least one subscriber’s owner is visible, the framework
auto-arms frame_tick_requested after every render. When all
subscribers are hidden (e.g. parked inside a non-selected
Switcher branch), no re-arm happens and the chain dies, so
the event loop sleeps. On a hidden→visible transition the
visible_when binding’s relayout dirty triggers a repaint that
paints the subscriber, which the post-render arm then detects
and resumes the chain.
Replaces the widget-managed frame_request.set(true) re-arm
pattern for visual-only continuous animations. The widget’s
frame_tick effect closure no longer needs to call
frame_request.set(true) itself — the scheduler handles it.
Sourcepub fn subscribe_frame_tick_throttled(
&self,
interval: Duration,
) -> FrameTickSubscription
pub fn subscribe_frame_tick_throttled( &self, interval: Duration, ) -> FrameTickSubscription
Like subscribe_frame_tick, but the
widget only needs to wake at most once per interval while
visible. Same visibility gate and RAII guard; between wakes the
event loop sleeps to the interval deadline rather than rendering
identical 60 fps frames. Use when the widget’s visible output
changes far less often than 60 Hz — e.g. Cycle’s once-per-period
index advance, or a seconds-granular clock.
Sourcepub fn wake_at_handle(&self) -> Rc<Cell<Option<Instant>>>
pub fn wake_at_handle(&self) -> Rc<Cell<Option<Instant>>>
Clone the shared wake-at deadline cell. Stash it on widget
state and set Some(instant) from a frame-tick effect to
schedule a one-shot deadline wake-up without keeping the event
loop in Poll mode. See WidgetTree::wake_at_handle for
the underlying mechanism.
Sourcepub fn effect<T: Clone + 'static>(
&mut self,
signal: &Signal<T>,
f: impl Fn(&T) + 'static,
)
pub fn effect<T: Clone + 'static>( &mut self, signal: &Signal<T>, f: impl Fn(&T) + 'static, )
Register a scoped effect tied to this build cycle. The effect fires whenever the signal changes. It is automatically cleaned up on rebuild or widget destruction.
Sourcepub fn own_handle(&mut self, handle: ObserverHandle)
pub fn own_handle(&mut self, handle: ObserverHandle)
Register a pre-existing observer handle for lifecycle management. The handle will be dropped (and the observer removed) on rebuild or widget destruction.
Sourcepub fn binding_registry(&self) -> &BindingRegistry
pub fn binding_registry(&self) -> &BindingRegistry
Get the binding registry.
Sourcepub fn theme_signal(&self) -> Signal<Theme>
pub fn theme_signal(&self) -> Signal<Theme>
Reactive handle on the current theme. Fires observers when
tree.set_theme(...) is called. Build implementations that want
theme-driven values to update without a rebuild should use this
instead of cloning tokens from self.theme() — for example,
ctx.theme_signal().map(|t| t.colors.primary) or combining with
interaction state via zip(...).
Sourcepub fn text_scale(&self) -> f32
pub fn text_scale(&self) -> f32
Current combined text-scale factor (user × OS, 1.0 = 100 %). One-shot
read for build-time sizing; for a value that updates without a rebuild,
bind text_scale_signal instead.
Sourcepub fn text_scale_signal(&self) -> Signal<f32>
pub fn text_scale_signal(&self) -> Signal<f32>
Reactive handle on the combined text-scale factor. Fires when the user
scale, theme, or OS text-scale preference changes. Build implementations
that derive a build-time dimension from the scale (e.g. Calendar’s
fixed cell sizes) bind this — typically at Rebuild level so the change
recomputes the constants — since a scale change relayouts but does not
rebuild on its own.
Sourcepub fn window_active(&self) -> bool
pub fn window_active(&self) -> bool
Whether the host window is currently active (focused AND not occluded). One-shot read for build-time use; for a value that reacts
to focus changes, bind window_active_signal.
Sourcepub fn window_active_signal(&self) -> Signal<bool>
pub fn window_active_signal(&self) -> Signal<bool>
Reactive handle on window-active state. Fires when the host window gains
or loses active status (focused AND not occluded). Build
implementations that show/hide appearance with window focus — caret
effects, the selection-colour swap in text fields, DimWhenInactive —
bind this, typically at RepaintOnly level (an active-state flip never
affects geometry). Starts true.
Sourcepub fn locale_signal(&self) -> Signal<Option<String>>
pub fn locale_signal(&self) -> Signal<Option<String>>
Reactive handle on the current locale. Fires observers when
tree.set_locale(...) is called.
Sourcepub fn window(&self) -> Option<&WindowState>
pub fn window(&self) -> Option<&WindowState>
The WindowState for the window
hosting this tree. None only for trees built outside of an
app (tests, headless scenarios). Use this to bind widgets to
window-level signals like placement, size, focused.
Sourcepub fn app_state<T: 'static>(&self) -> Option<&T>
pub fn app_state<T: 'static>(&self) -> Option<&T>
Retrieve an application-scoped value of type T registered via
TeksiloAppBuilder::app_state. Returns None if no value of
that type was registered. The returned reference borrows from
the framework for the duration of the build pass.
Sourcepub fn poster(&self) -> Option<&Arc<dyn AppEventPoster>>
pub fn poster(&self) -> Option<&Arc<dyn AppEventPoster>>
Borrow the AppEventPoster installed by the
framework, if any. Mirrors EventContext::poster.
Used by integrations that wire a platform callback (e.g. a native menu
item) to post a typed payload back to the UI loop. Returns None for
trees built outside an app (tests / headless).
Sourcepub fn visible_when(&mut self, id: WidgetId, state: impl Into<Prop<bool>>)
pub fn visible_when(&mut self, id: WidgetId, state: impl Into<Prop<bool>>)
Bind a widget’s visibility to a boolean prop or compatibility state binding.
Sourcepub fn run_after_mount(
&mut self,
f: impl FnOnce(&mut EventContext<'_>) + 'static,
)
pub fn run_after_mount( &mut self, f: impl FnOnce(&mut EventContext<'_>) + 'static, )
Enqueue a one-shot action to run shortly after this build, with a real
EventContext — the only place a widget
can read the OS parent window handle (ctx.parent_window_handle()),
app_state, and poster together, after it is mounted under its
window. The action runs at most once per enqueue (the app loop drains
the queue each iteration); a widget that rebuilds must guard against
enqueuing twice. Built for widgets owning a native OS resource that
needs a window handle to initialise (a WebView’s engine subview);
ordinary widgets never need it.
Sourcepub fn activation_signal(&mut self, id: WidgetId) -> Signal<bool>
pub fn activation_signal(&mut self, id: WidgetId) -> Signal<bool>
Observe a node’s framework activation as a Signal<bool> — true
while active, false while parked dormant by a Switcher /
visible_when gate. Initialised to the node’s current state and
updated only on an actual Active↔Dormant transition.
Ordinary widgets never need this: dormant subtrees are simply not
painted, so they vanish for free. It exists for the one case where
“not painted” ≠ “hidden” — a widget owning a native OS resource
that renders outside the wgpu pass (a WebView’s engine subview).
Such a widget does ctx.effect(&ctx.activation_signal(id), move |a| handle.set_visible(*a)) to hide/show the native surface in lockstep.
Sourcepub fn view_focus_active(&mut self) -> Signal<bool>
pub fn view_focus_active(&mut self) -> Signal<bool>
Reactive Signal<bool> that is true while the focus scope containing
the widget being built — its nearest focusable ancestor, e.g. the
enclosing ListView / TreeView — holds keyboard focus. Items outside
any focusable scope read a constant true.
Drives focus-aware selection: a selected row renders with the active
Selected chrome while its view has focus and the muted
SelectedInactive chrome when focus moves elsewhere — the standard
desktop affordance (Qt SH_ItemView_..., macOS inactive selection) that
shows where the keyboard is. The scope is resolved at build time but the
signal stays live across focus changes.
Sourcepub fn begin_view_focus(&mut self) -> Signal<bool>
pub fn begin_view_focus(&mut self) -> Signal<bool>
Mark the widget being built as a focus scope for the rows/items it
builds next: any descendant’s view_focus_active
(and StandardItem’s focus-aware selection / focus ring) reads this
widget’s keyboard focus. A data view calls this around its row loop, then
end_view_focus. Deterministic — unaffected by
arena parenting, which may not be wired while docked/virtualized rows build.
Sourcepub fn begin_view_focus_for(&mut self, node_id: WidgetId) -> Signal<bool>
pub fn begin_view_focus_for(&mut self, node_id: WidgetId) -> Signal<bool>
Like begin_view_focus but keys the scope on
an explicit node_id rather than the widget being built. A view whose
rows are built by a separate body-pane widget (TableView /
TreeTableView / GridView) passes its own focusable root id so descendant
items resolve the root’s keyboard focus — not the pane’s, which is a
child of the root and so never holds focus itself.
Sourcepub fn end_view_focus(&mut self)
pub fn end_view_focus(&mut self)
End the focus scope opened by begin_view_focus.
Sourcepub fn focus_visible(&self) -> Signal<bool>
pub fn focus_visible(&self) -> Signal<bool>
Input-modality “focus-visible” signal — true after keyboard input,
false after pointer input (the standard :focus-visible rule). Pair
with view_focus_active to draw a focus
ring only during keyboard navigation, not on mouse clicks.
Sourcepub fn set_opacity(&mut self, id: WidgetId, opacity: impl Into<Prop<f32>>)
pub fn set_opacity(&mut self, id: WidgetId, opacity: impl Into<Prop<f32>>)
Bind an opacity multiplier (0..1) to a widget. The render walker
emits SetOpacity(value) before painting the widget’s subtree
and RestoreOpacity afterwards, so the multiplier composes
correctly with ancestor opacity scopes. Bound at RepaintOnly:
opacity changes never trigger relayout. Used by the Fade
wrapper to animate a child between hidden and fully visible.
Sourcepub fn set_transform(
&mut self,
id: WidgetId,
transform: impl Into<Prop<Transform2D>>,
)
pub fn set_transform( &mut self, id: WidgetId, transform: impl Into<Prop<Transform2D>>, )
Bind a 2D affine transform to a widget. The render walker emits
PushTransform(value) before painting the widget’s subtree and
PopTransform afterwards, so the transform composes onto the
renderer’s stack with any ancestor transform scopes and with
the widget’s own canvas-level transforms. Bound at RepaintOnly:
visual-only transforms never trigger relayout. Used by Scale
and Rotate; reflow-driving wrappers (e.g. Scale::reflow(true))
must additionally bind their driver signal to themselves at
Relayout to make layout track the value.
Sourcepub fn set_content_transform(
&mut self,
id: WidgetId,
transform: impl Into<Prop<Transform2D>>,
)
pub fn set_content_transform( &mut self, id: WidgetId, transform: impl Into<Prop<Transform2D>>, )
Bind a 2D affine content transform to a widget — the transform
positions the widget’s content within its fixed parent-space viewport
(its bounds) rather than transforming the widget itself. Renders the
same PushTransform / PopTransform scope as
set_transform, but hit-testing treats the
bounds as a fixed viewport so the whole visible area stays interactive
at any pan / zoom. Used by SceneView for its pan/zoom view transform.
Sourcepub fn set_blur(&mut self, id: WidgetId, radius: impl Into<Prop<f32>>)
pub fn set_blur(&mut self, id: WidgetId, radius: impl Into<Prop<f32>>)
Bind a Gaussian-equivalent blur radius to a widget. The render
walker emits BeginBlurredSubtree { bounds, radius } before
painting the widget’s subtree and EndBlurredSubtree afterwards;
the renderer redirects drawing into an intermediate texture, runs
a dual-Kawase blur chain at the requested radius, and composites
the blurred result back into the parent pass at the widget’s
bounds. Bound at RepaintOnly: blur radius changes never trigger
relayout. Sub-perceptual radii (< 0.5) skip the Begin/End pair
entirely so animated enable/disable patterns have zero per-frame
cost when fully off. Used by the Blur wrapper.
Sourcepub fn enabled_when(&mut self, id: WidgetId, state: impl Into<Prop<bool>>)
pub fn enabled_when(&mut self, id: WidgetId, state: impl Into<Prop<bool>>)
Bind a widget’s enabled state to a boolean prop or compatibility state binding.
Sourcepub fn effective_enabled_signal(&mut self, id: WidgetId) -> Signal<bool>
pub fn effective_enabled_signal(&mut self, id: WidgetId) -> Signal<bool>
Reactive view of “is this widget effectively enabled?” — the AND
of the widget’s own enabled_state and every ancestor’s. The
arena’s crate::arena::WidgetArena::is_enabled is the
non-reactive equivalent; this method gives composite widgets a
Signal<bool> they can .map(...) / .zip(...) against to
derive other reactive UI state (cursor, custom paint, helper
signals).
Leaves like IconWidget / TextWidget / RectWidget do NOT
need this — they get the bool directly via
crate::widget::PaintContext::effective_enabled at paint time.
This method is for composites that need the value at build time
or want to chain signals.
The signal is node-resident and framework-refreshed (install-or-reuse,
like Self::activation_signal), so it tracks ancestors correctly even
though a widget’s parent is not yet wired while its own build() runs.
It is a mutable signal, so — unlike the old derived implementation —
it can be passed to Self::effect.
Returns a signal reading true for any node whose entire ancestor
chain (including itself) has no enabled_state bound.
Sourcepub fn set_tab_stop(&mut self, id: WidgetId, state: impl Into<Prop<bool>>)
pub fn set_tab_stop(&mut self, id: WidgetId, state: impl Into<Prop<bool>>)
Bind a widget’s Tab-key participation to a boolean prop or
compatibility state binding. When false, the widget is removed
from Tab / Shift+Tab traversal but remains reachable via
request_focus and arrow-key navigation. Implements the ARIA
roving-tabindex pattern (HTML tabindex="-1" semantics).
Sourcepub fn set_traversal_scope(&mut self, policy: TraversalScopePolicy)
pub fn set_traversal_scope(&mut self, policy: TraversalScopePolicy)
Declare the widget being built as a traversal-scope boundary for
Tab / Shift+Tab navigation. Descendants’ tab_index values become
scoped to this node — they never collide with sibling scopes — and the
policy controls what happens at the scope’s ends:
TraversalScopePolicy::Continue— Tab flows out into the enclosing scope’s next member (groups numbering only).TraversalScopePolicy::Cycle— Tab wraps within the scope, never exits. For modal dialogs only: a popover or menu is non-modal, and the framework closes one the keyboard walks out of rather than containing focus in it. Trapping such an overlay stops that dismissal from ever firing.
This node is automatically excluded from being a Tab stop itself.
Prefer the FocusScope wrapper widget in teksilo-widgets over
calling this directly.
Sourcepub fn attach_tooltip(
&mut self,
anchor_id: WidgetId,
content_id: WidgetId,
delay: Duration,
)
pub fn attach_tooltip( &mut self, anchor_id: WidgetId, content_id: WidgetId, delay: Duration, )
Attach a tooltip to a widget.
Sourcepub fn attach_tooltip_with_placement(
&mut self,
anchor_id: WidgetId,
content_id: WidgetId,
delay: Duration,
placement: TooltipPlacement,
)
pub fn attach_tooltip_with_placement( &mut self, anchor_id: WidgetId, content_id: WidgetId, delay: Duration, placement: TooltipPlacement, )
Attach a tooltip with an explicit
TooltipPlacement — use Side
for anchors stacked vertically (menu items, a vertical tab strip,
list/tree rows) so the tooltip opens beside the anchor instead of
covering the next sibling.
Sourcepub fn attach_tooltip_with_sticky(
&mut self,
anchor_id: WidgetId,
content_id: WidgetId,
delay: Duration,
sticky_after: Option<Duration>,
)
pub fn attach_tooltip_with_sticky( &mut self, anchor_id: WidgetId, content_id: WidgetId, delay: Duration, sticky_after: Option<Duration>, )
Attach a tooltip that auto-promotes to sticky after a dwell
timer. Non-None sticky_after enables the sticky-on-dwell UX:
once the tooltip has been shown for sticky_after, the tree
flags the entry sticky and swaps the overlay’s dismiss
behavior to EscapeOrClickOutside.
Sourcepub fn attach_tooltip_with_sticky_sink(
&mut self,
anchor_id: WidgetId,
content_id: WidgetId,
delay: Duration,
sticky_after: Option<Duration>,
shown_at_sink: Rc<Cell<Option<Instant>>>,
)
pub fn attach_tooltip_with_sticky_sink( &mut self, anchor_id: WidgetId, content_id: WidgetId, delay: Duration, sticky_after: Option<Duration>, shown_at_sink: Rc<Cell<Option<Instant>>>, )
Variant of attach_tooltip_with_sticky
that takes a shared Rc<Cell<Option<Instant>>> “sink” the
tree updates whenever the tooltip is shown / dismissed. The
tooltip widget reads from this sink to compute its own dwell
progress reliably, without needing a paint-gap heuristic.
Sourcepub fn attach_tooltip_with_sticky_sink_placement(
&mut self,
anchor_id: WidgetId,
content_id: WidgetId,
delay: Duration,
sticky_after: Option<Duration>,
shown_at_sink: Rc<Cell<Option<Instant>>>,
placement: TooltipPlacement,
)
pub fn attach_tooltip_with_sticky_sink_placement( &mut self, anchor_id: WidgetId, content_id: WidgetId, delay: Duration, sticky_after: Option<Duration>, shown_at_sink: Rc<Cell<Option<Instant>>>, placement: TooltipPlacement, )
Variant of attach_tooltip_with_sticky_sink
that also carries a TooltipPlacement.
The full-featured path used by rich + composite tooltips that want
Side placement in a vertical context (menu items, list/tree rows).
Sourcepub fn promote_tooltip_to_sticky(&mut self, content_id: WidgetId)
pub fn promote_tooltip_to_sticky(&mut self, content_id: WidgetId)
Promote a shown tooltip to “sticky”: removes its auto-dismiss
on pointer-leave and swaps the overlay’s dismiss behavior to
EscapeOrClickOutside. Used by rich tooltips that implement a
dwell timer.
Sourcepub fn set_dormant(&mut self, id: WidgetId)
pub fn set_dormant(&mut self, id: WidgetId)
Set a widget as dormant (inactive). Used to pre-create overlay content
that will be activated later via EventContext::activate().
Sourcepub fn destroy_subtree(&mut self, id: WidgetId)
pub fn destroy_subtree(&mut self, id: WidgetId)
Destroy a widget and its entire subtree, removing them from the arena and dropping any per-widget subscription / effect handles.
Use this to clean up dormant subtrees that the current widget
created during a prior build and that live outside its regular
arena children — e.g., a pre-built popup panel inserted via
ctx.add(..) + ctx.set_dormant(..) that becomes stale after a
rebuild. Regular arena children of the composite (i.e. widgets
whose ids are returned from build) are destroyed automatically
by the framework’s rebuild path and do not need this call.
If an overlay currently references id as its content, the
overlay is dismissed first so the manager does not retain a
stale content reference.
Sourcepub fn apply_self_handlers(&mut self, handler_set: HandlerSet)
pub fn apply_self_handlers(&mut self, handler_set: HandlerSet)
Apply a HandlerSet to the composite widget being built (self).
This transfers attached event handlers, focusable flag, cursor, etc.
to the widget’s arena node, replacing event() and is_focusable() overrides.
Sourcepub fn focus(&mut self, id: WidgetId)
pub fn focus(&mut self, id: WidgetId)
Move keyboard focus to id. Mirrors
EventContext::request_focus for use during build() — e.g.
when a composing widget pre-builds an editor and needs focus to
land on it as soon as the subtree is wired in.
Sourcepub fn first_focusable_descendant(&self, root: WidgetId) -> Option<WidgetId>
pub fn first_focusable_descendant(&self, root: WidgetId) -> Option<WidgetId>
Find the first focusable widget within the subtree rooted at
root in depth-first order. Returns None when the subtree has
no focusable descendant or root is not in the arena.
Sourcepub fn focus_into(&mut self, id: WidgetId) -> bool
pub fn focus_into(&mut self, id: WidgetId) -> bool
Move keyboard focus into the subtree rooted at id: its first
focusable descendant in tab order, or id itself when it is the only
focusable thing there. Returns whether focus ended up inside id.
The build-time twin of
EventContext::request_focus_into,
and safe here for the same reason focus is: add builds
a child’s whole subtree synchronously, so by the time a composing widget
holds a child’s id the focusable descendants of that child already exist.
Idempotent, and that is the point. build runs again on every
rebuild, so a bare focus here would drag focus back into this subtree
every time the owner rebuilt for an unrelated reason — a table body pane
rebuilds on selection, on filtering and on scroll. This is a no-op while
focus already sits inside id, so it expresses “focus belongs in here”
rather than “focus here now”.
A subtree with nothing focusable leaves focus exactly where it was: an empty region never traps it.
⚠ Ancestor-chain side effects do not run, and that is a property of
focusing from build at all, not of this method — focus
has it too. A node added during build is not parented until the build
that produced it returns, so at this moment id’s chain stops at
whatever the caller has already inserted: focus_within signals on
enclosing nodes never flip, and scroll_focused_into_view finds no
scroll container to reveal the target in. Everything below id is
linked (children are parented as each is inserted), so the walk that
picks the focusable descendant, and every later key dispatch — which
happens after the pass, on a whole tree — are unaffected.
Reach for EventContext::request_focus_into
where the difference matters: it is queued and drained after dispatch,
against a complete tree.
Sourcepub fn register_action(&mut self, action: Action)
pub fn register_action(&mut self, action: Action)
Attach an Action to the widget being
built. Actions are consulted during intent dispatch as the
framework walks source-widget → root; the first matching,
enabled action wins (subject to the IntentResponse returned
by its handler).
Actions are cleared on rebuild, mirroring event handlers.
Sourcepub fn register_text_surface(&mut self, surface: Rc<dyn TextSurface>)
pub fn register_text_surface(&mut self, surface: Rc<dyn TextSurface>)
Declare that the widget being built edits text.
Every text widget should call this. It is what lets an application take
a text chord — Ctrl+Z, Ctrl+C — for itself without silently breaking
the widget it took it from: the host asks
focused_text_surface
and either drives this surface or steps aside so the widget keeps its own
keys. See crate::text_surface for the whole argument.
Owned by the registering widget and torn down on its rebuild or destroy,
like register_action_global. Calling it
twice from one widget re-points rather than duplicating, so a rebuild
that hands over a fresh handle is correct.
Sourcepub fn text_surfaces(&self) -> TextSurfaces
pub fn text_surfaces(&self) -> TextSurfaces
A cloneable view of this tree’s registered text surfaces.
Take it once, during build, and hold it: a view-model refreshed from a
frame tick has no &WidgetTree to consult, and that is exactly when it
needs to know whether the caret is in a text widget.
Sourcepub fn register_action_global(&mut self, action: Action)
pub fn register_action_global(&mut self, action: Action)
Register a window-global Action, owned by
the widget being built. Unlike register_action
— which only fires when this widget is on the intent’s source→root walk —
a global action is consulted as a dispatch fallback, so it is reachable
no matter where the intent originated: a menu-bar dropdown (which renders
in an overlay, not under the registering widget), deep content, or a
global shortcut anchored at the root when nothing is focused.
This is the action-side counterpart to
register_shortcut_global: use it for
app-wide commands (app.save, view.toggle_sidebar) whose handler lives
at the app root but whose triggers (menu, toolbar, shortcut) are scattered
across the tree and chrome. Ownership applies: the action is torn down
when this widget rebuilds or is destroyed.
Sourcepub fn register_shortcut(&mut self, shortcut: Shortcut)
pub fn register_shortcut(&mut self, shortcut: Shortcut)
Register a Shortcut in the
tree’s registry, owned by the widget being built.
If the shortcut builder left scope at the default
(ShortcutScope::Global),
this method rewrites it to Scoped(self_id) so the shortcut
only fires when focus is inside the registering widget’s
subtree — the ergonomic default for widget-declared shortcuts.
Callers that want an explicit global shortcut should use
BuildContext::register_shortcut_global instead; callers
that want to scope to a specific child should set
.scope_to(child_id) on the builder themselves.
Ownership: the shortcut is removed from the registry when the widget is destroyed or rebuilt. User overrides survive across rebuilds (graveyard semantics).
Sourcepub fn register_shortcut_global(&mut self, shortcut: Shortcut)
pub fn register_shortcut_global(&mut self, shortcut: Shortcut)
Register a Shortcut with
explicit global scope, owned by the widget being built. Unlike
BuildContext::register_shortcut, this does not rewrite the
scope — the shortcut fires regardless of focus position.
Ownership still applies: the shortcut is torn down when this widget goes away.
Sourcepub fn register_pending_shortcuts(
&mut self,
shortcuts: impl IntoIterator<Item = Shortcut>,
)
pub fn register_pending_shortcuts( &mut self, shortcuts: impl IntoIterator<Item = Shortcut>, )
Pre-declare shortcuts on behalf of a not-yet-mounted child
(e.g. a Switcher walking its Pending slots’ static
declarations before they’re inserted). Each shortcut is owned
by the calling widget and its declared scope is preserved
as-is — unlike register_shortcut,
no rewrite from Global to Scoped(self) happens, because
the child intended its own scope.
When the child is eventually mounted, the framework’s
insert-time walk of Widget::declare_shortcuts re-registers
the same ids owned by the child; the registry’s idempotent
upsert moves ownership cleanly. If the child never mounts, the
pre-declared entries stay alive (owned by the parent) so
settings UIs still see them, and they get torn down when the
parent goes away.
Sourcepub fn shortcut_registry(&self) -> &ShortcutRegistry
pub fn shortcut_registry(&self) -> &ShortcutRegistry
Read-through access to the tree’s shortcut registry. Consumers
(menus, tooltips) look up the effective keystroke for a given
id here, and observe
ShortcutRegistry::version
to refresh when the user rebinds.
Sourcepub fn effective_shortcut<'b>(
&'b self,
id: &str,
) -> Option<EffectiveShortcut<'b>>
pub fn effective_shortcut<'b>( &'b self, id: &str, ) -> Option<EffectiveShortcut<'b>>
Effective view of a shortcut by id, merged with any user
override. Returns None when no default has been registered
for id. Typical caller pattern: call from paint() so
late-registered shortcuts are still picked up without a
dedicated build-phase query.
Sourcepub fn shortcut_version(&self) -> &Signal<u64>
pub fn shortcut_version(&self) -> &Signal<u64>
Convenience accessor for the reactive version signal. Widgets that render shortcut-derived state (menu labels, tooltips) observe this so the UI refreshes when the user rebinds or a new shortcut is registered.
Sourcepub fn effective_shortcut_signal(
&mut self,
id: &'static str,
) -> Signal<Option<KeyStroke>>
pub fn effective_shortcut_signal( &mut self, id: &'static str, ) -> Signal<Option<KeyStroke>>
A reactive, per-id handle to a shortcut’s effective primary
keystroke — the granular alternative to Self::shortcut_version.
Bind this to render one shortcut’s accelerator as a leaf value
(a menu item’s trailing label, a tooltip) that refreshes in place
when the user rebinds that id, without observing — and rebuilding
on — every unrelated registry mutation. The signal is created on
first request, seeded with the current value, and kept live by the
registry across register / unregister / rebind of that id.
Sourcepub fn apply_handlers(&mut self, id: WidgetId, handler_set: HandlerSet)
pub fn apply_handlers(&mut self, id: WidgetId, handler_set: HandlerSet)
Apply a HandlerSet to a child widget created during this build.
Use this to attach event handlers to children without wrapping them
in WidgetWithHandlers.
Sourcepub fn access_labelled_by(&mut self, id: WidgetId, label_id: WidgetId)
pub fn access_labelled_by(&mut self, id: WidgetId, label_id: WidgetId)
Wire an accessibility labelled_by relation from an already-mounted
child (id) to its label (label_id), so assistive tech announces the
field by its visible label (WCAG 3.3.2 / EN 301 549 11.5.2.7). Unlike
the .access_labelled_by(..) builder method, this operates after the
child is mounted (so a container like FormLayout can pair a label and
a boxed field once both ids are resolved) and preserves any
accessibility overrides the child already carries.
Sourcepub fn access_described_by(&mut self, id: WidgetId, target_id: WidgetId)
pub fn access_described_by(&mut self, id: WidgetId, target_id: WidgetId)
Wire an accessibility described_by relation from an already-mounted
child (id) to a description/error node (target_id) — the
post-mount, override-preserving counterpart of the
.access_described_by(..) builder method (WCAG 3.3.1).
pub fn subscribe_event<O, E, F>(&mut self, origin: O, callback: F)
Sourcepub fn subscribe_event_with_ctx<O, E, F>(&mut self, origin: O, callback: F)
pub fn subscribe_event_with_ctx<O, E, F>(&mut self, origin: O, callback: F)
Like subscribe_event, but the UI-side
callback additionally receives a fresh
EventContext bound to this widget’s
window. That lets it react to a backend event imperatively — update /
replace / dismiss a toast, present a modal, send_intent, navigate —
none of which a plain (context-free) subscribe_event callback can do
(it can only poke Signals).
This is the supported bridge for long-operation progress: a Qleany
Origin::LongOperation(Progress | Completed | Cancelled | Failed) event
crosses from the operation’s background thread to the UI thread and the
callback drives an evolving progress toast (percentage in the body, a
Cancel action, a success/error replacement on completion) — see the
toast_demo example.
The event is delivered on the UI thread through the same
AppEvent::SubscriptionEvent path as subscribe_event; teksilo-app
mints the EventContext from this widget’s window tree just before the
call (mirroring teksilo-async’s spawn_local_with completion path).
The subscription is torn down with the widget, exactly like
subscribe_event.
The <O, E> type match against the registered event source is a
debug_assert (as in subscribe_event); a
mismatched call site in a release build is not caught here but panics
later at the payload downcast.
Registering from a windowless tree (headless / tests) is allowed but
records None for the window — the app-side router then has no tree to
mint an EventContext from and cannot deliver it, so such a subscription
never fires in a running app. Ordinary application widgets always have a
window; headless code that wants to observe events should use
subscribe_event and drive Signals instead.