Module decorator
Expand description
Extending a widget without re-implementing it: the Decorator trait.
A widget that adds one behaviour to another (a diagnostic probe, an app root that indexes
its content for search) should cost the hook it adds, not a hundred lines of forwarding
that go stale whenever Widget grows. Implement Decorator instead: name the wrapped
widget, give the two accessors, override only what changes, and a blanket impl makes it a
Widget that can be boxed as an Element or implement further traits
requiring Widget.
struct Probe { content: Column }
impl ui::widget::Decorator for Probe {
type Inner = Column;
fn inner(&self) -> &Column { &self.content }
fn inner_mut(&mut self) -> &mut Column { &mut self.content }
fn native_input_snapshot(&self, doc: &AutoCommit, path: &ObjId) -> Option<serde_json::Value> {
Some(serde_json::json!({ "rect": format!("{:?}", self.content.get_rect()) }))
}
}§A decorator is its inner widget plus overrides
Nothing is forwarded “partly”: children forwards too, so a host
traversal meets the decorator in the inner widget’s place and visits every node once. Only
the identity methods describe the decorator itself (concrete_type_name,
as_any, as_any_mut). A boxed
Element is wrapped with type Inner = dyn Widget;.
Four consequences are worth knowing:
- An override replaces the inner widget’s answer, so one that adds to a collecting hook
(
resources,search_providers,take_control_invocation) includes the inner answer. - Override the host’s entry point:
drawandhandle_eventare what the host calls, not the methods they derive from (tooltip_target_at,collect_damage). - The decorator stands in for its inner widget’s layout node, so a host reaching a
widget through the node map meets the decorator, and a node the inner widget handed to a
widget of its own stays that widget’s. A decorator that builds its own node around the
inner one registers itself with
register_node. - Method calls are ambiguous with both traits imported, so implement by path (
impl ui::widget::Decorator for ..); the prelude deliberately does not export it.
Modules§
- concrete
- The same trait for the toolkit’s own decorators that apps box
(
concrete_decorator_widget): it has no blanketWidgetimpl, so each such type gets a concrete one, compiled once into the toolkit. Through the blanket impl a decorator’sWidgetmethods are generic, and every app that boxes one compiled them again, with the inner widget they forward to.
Traits§
- AsDyn
Widget - A widget as
&dyn Widget, also one that already is a trait object: a decorator’s inner widget may be either, and its layout walk hands the inner widget on (Widget::for_each_layout_child). - Decorator
- A widget that extends another by overriding a few
Widgetmethods and forwarding the rest. See the module docs.
Functions§
- register_
node - Point
nodeatwidgetin the host’s node map, replacing the inner widget’s own registration. For aDecoratorthat overrides a hook the host reaches through the node map (a cursor shape, a tooltip, undo status); call it frombuild_layoutafter the inner widget built its node.