pub trait Widget: Any {
// Required methods
fn layout(&mut self, ctx: &mut LayoutCtx<'_>, bc: &BoxConstraints) -> Size;
fn paint(&mut self, ctx: &mut PaintCtx<'_>, scene: &mut dyn PaintScene);
// Provided methods
fn event(
&mut self,
_ctx: &mut EventCtx<'_>,
_event: &InputEvent,
) -> EventResult { ... }
fn semantics(&self, _ctx: &mut SemanticsCtx) { ... }
fn type_name(&self) -> &'static str { ... }
fn visit_children(&self, _visitor: &mut dyn FnMut(&ChildPod)) { ... }
fn as_sliver(&mut self) -> Option<&mut dyn SliverWidget> { ... }
}Expand description
A retained UI element living in the widget tree.
Widget: Any so the render root can downcast a boxed widget back to the
concrete element type its originating view produced (needed during rebuild).
Implementing types get [Widget::downcast_mut] for free — no boilerplate
method to write.
Required Methods§
Sourcefn layout(&mut self, ctx: &mut LayoutCtx<'_>, bc: &BoxConstraints) -> Size
fn layout(&mut self, ctx: &mut LayoutCtx<'_>, bc: &BoxConstraints) -> Size
Choose a size within bc and return it. The chosen size must satisfy
bc (callers may additionally clamp via BoxConstraints::constrain).
§Layout may be skipped
Under a crate::app::RenderRoot a widget sitting in a ChildPod is
not laid out every frame: ChildPod::layout_child returns the size
it recorded last time, without calling this method, when the pod is clean,
its constraints are equal to last time’s, the window insets it sees are
unchanged, and the root’s layout epoch has not moved (see that method for
the full rule). So the result of layout must be a function of bc, the
context’s global inputs, and widget state that only changes through one of
the channels that dirty the pod:
- a rebuild returning
ChangeFlags::LAYOUT; PaintCtx::request_layout(orEventCtx::request_layout);PaintCtx::request_frame(any frame request — an animating subtree is laid out again on the next pass, conservatively; a pacedTickClass::CosmeticLooprequest marks the pod but forces no pass of its own, so a loop that changes layout must not be paced);- an event the widget consumed (
EventResult::Handled) or that asked for a redraw (EventCtx::request_redraw).
A widget must not change layout-affecting state any other way — a change made behind the pod’s back is invisible to the skip and lays out stale until something else dirties the path.
Sourcefn paint(&mut self, ctx: &mut PaintCtx<'_>, scene: &mut dyn PaintScene)
fn paint(&mut self, ctx: &mut PaintCtx<'_>, scene: &mut dyn PaintScene)
Emit draw commands for this widget into scene.
Paint may advance a widget’s own animation state (e.g. a scroll
fling integrated from a monotonic clock) as a v1 seam. A widget that does
so must call PaintCtx::request_frame while the animation is still
running so the shell re-invokes paint absent any external event —
otherwise the desktop ControlFlow::Wait loop idles and the animation
stalls. It must stop signalling once the animation reaches rest.
Provided Methods§
Sourcefn event(&mut self, _ctx: &mut EventCtx<'_>, _event: &InputEvent) -> EventResult
fn event(&mut self, _ctx: &mut EventCtx<'_>, _event: &InputEvent) -> EventResult
Handle an input event, optionally mutating application state through
ctx and reporting whether it was consumed.
Defaulted to EventResult::Ignored so non-interactive widgets are
unaffected. Interactive widgets
(Button/Checkbox/Slider) override this; containers forward to
their ChildPod children via ChildPod::event_child.
Sourcefn semantics(&self, _ctx: &mut SemanticsCtx)
fn semantics(&self, _ctx: &mut SemanticsCtx)
Contribute this widget’s accessibility node(s) into ctx.
Defaulted to a no-op so non-semantic widgets (and every widget written
before this seam) are unaffected — exactly like Widget::event. A leaf
widget overrides it to call SemanticsCtx::push_node with its role and
state; a container overrides it to forward to each child via
ChildPod::semantics_child (a transparent container contributes no node
of its own, only recursion). The pass runs after layout, so
SemanticsCtx::origin/SemanticsCtx::size carry valid absolute
geometry.
Sourcefn type_name(&self) -> &'static str
fn type_name(&self) -> &'static str
This widget’s concrete type name, for read-only tooling.
Defaulted to core::any::type_name of the implementing type, so every
widget reports its own name through the vtable — including one reached
as a dyn Widget, where the concrete type is otherwise unrecoverable.
Asking the live widget beats recording a name when it was built: a
rebuild that swaps a child’s concrete type cannot leave a stale name
behind, not even through wrapper views that re-box an inner AnyView
(docs/LIMITATIONS.md’s focus-wrapper-erasure-swap-blind).
Diagnostic only: type_name’s output is not a stable contract across
compiler versions, so never parse or match on it. Overriding it is
sanctioned only for a transparent wrapper reporting what it wraps (the
Box<dyn Widget> blanket impl is the one in-crate case).
Sourcefn visit_children(&self, _visitor: &mut dyn FnMut(&ChildPod))
fn visit_children(&self, _visitor: &mut dyn FnMut(&ChildPod))
Visit this widget’s owned ChildPods, in declaration (paint) order —
the read-only seam that makes the retained hierarchy enumerable.
Containers own their children as ChildPod fields rather than as arena
nodes (see ChildPod), so nothing outside a container could walk into
its subtree; this is that walk, and
WidgetTree::inspect is its one
in-crate consumer.
Defaulted to visiting nothing, exactly like Widget::event and
Widget::semantics: a leaf widget needs no impl and pays nothing, and
a container that never overrides it simply reads as a leaf to tooling. It
runs behind &self and must not mutate anything a pass depends on — no
build/layout/paint/event behavior may be routed through it.
No cycles by construction. A ChildPod owns its widget (Box<dyn Widget>); ownership is a tree, so a descent through visit_children
terminates without any runtime cycle check. A widget that handed the
visitor a pod it does not own would break that, which is why the visitor
takes &ChildPod — there is no way to publish a shared one.
Sourcefn as_sliver(&mut self) -> Option<&mut dyn SliverWidget>
fn as_sliver(&mut self) -> Option<&mut dyn SliverWidget>
This widget as a sliver, if it speaks the sliver protocol — the opt-in
seam a scrolling viewport lays its children out through (see
crate::sliver and ChildPod::layout_sliver_child).
Defaulted to None, exactly like Widget::visit_children: a box
widget needs no impl and is laid out through Widget::layout as
always. A type implementing SliverWidget overrides it to return
Some(self). A transparent wrapper (a type-erasing box, a component
boundary, an either-arm) forwards it to what it wraps, so a sliver stays
a sliver however it was erased.
Implementations§
Trait Implementations§
Source§impl Widget for Box<dyn Widget>
A boxed widget is itself a Widget, delegating every pass to its contents.
impl Widget for Box<dyn Widget>
A boxed widget is itself a Widget, delegating every pass to its contents.
This blanket impl is what makes type-erased children work: a
crate::view::AnyView’s element is a Box<dyn Widget>, and
View::Element must implement Widget — so the box has to be a widget too.
It also lets a Box<dyn Widget> be stored inside a ChildPod like any
concrete widget. Box<dyn Widget> is 'static (hence Any), so it satisfies
the Widget: Any bound and can be recovered by
[downcast_mut](dyn Widget::downcast_mut) during rebuild.
Source§fn as_sliver(&mut self) -> Option<&mut dyn SliverWidget>
fn as_sliver(&mut self) -> Option<&mut dyn SliverWidget>
The boxed widget’s sliver face, so type erasure never hides a sliver from the viewport laying it out.
Source§fn type_name(&self) -> &'static str
fn type_name(&self) -> &'static str
Report the boxed widget’s name, not Box<dyn Widget> — the box is a
storage detail of type erasure, never a tree element in its own right,
and it nests (a doubly-boxed pod resolves through both layers).
Source§fn layout(&mut self, ctx: &mut LayoutCtx<'_>, bc: &BoxConstraints) -> Size
fn layout(&mut self, ctx: &mut LayoutCtx<'_>, bc: &BoxConstraints) -> Size
bc and return it. The chosen size must satisfy
bc (callers may additionally clamp via BoxConstraints::constrain). Read moreSource§fn paint(&mut self, ctx: &mut PaintCtx<'_>, scene: &mut dyn PaintScene)
fn paint(&mut self, ctx: &mut PaintCtx<'_>, scene: &mut dyn PaintScene)
scene. Read moreSource§fn event(&mut self, ctx: &mut EventCtx<'_>, event: &InputEvent) -> EventResult
fn event(&mut self, ctx: &mut EventCtx<'_>, event: &InputEvent) -> EventResult
ctx and reporting whether it was consumed. Read moreSource§fn semantics(&self, ctx: &mut SemanticsCtx)
fn semantics(&self, ctx: &mut SemanticsCtx)
ctx. Read moreDyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".
Implementations on Foreign Types§
Source§impl Widget for Box<dyn Widget>
A boxed widget is itself a Widget, delegating every pass to its contents.
impl Widget for Box<dyn Widget>
A boxed widget is itself a Widget, delegating every pass to its contents.
This blanket impl is what makes type-erased children work: a
crate::view::AnyView’s element is a Box<dyn Widget>, and
View::Element must implement Widget — so the box has to be a widget too.
It also lets a Box<dyn Widget> be stored inside a ChildPod like any
concrete widget. Box<dyn Widget> is 'static (hence Any), so it satisfies
the Widget: Any bound and can be recovered by
[downcast_mut](dyn Widget::downcast_mut) during rebuild.
Source§fn as_sliver(&mut self) -> Option<&mut dyn SliverWidget>
fn as_sliver(&mut self) -> Option<&mut dyn SliverWidget>
The boxed widget’s sliver face, so type erasure never hides a sliver from the viewport laying it out.
Source§fn type_name(&self) -> &'static str
fn type_name(&self) -> &'static str
Report the boxed widget’s name, not Box<dyn Widget> — the box is a
storage detail of type erasure, never a tree element in its own right,
and it nests (a doubly-boxed pod resolves through both layers).