Skip to main content

Module decorator

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: draw and handle_event are 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 blanket Widget impl, so each such type gets a concrete one, compiled once into the toolkit. Through the blanket impl a decorator’s Widget methods are generic, and every app that boxes one compiled them again, with the inner widget they forward to.

Traits§

AsDynWidget
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 Widget methods and forwarding the rest. See the module docs.

Functions§

register_node
Point node at widget in the host’s node map, replacing the inner widget’s own registration. For a Decorator that overrides a hook the host reaches through the node map (a cursor shape, a tooltip, undo status); call it from build_layout after the inner widget built its node.