Skip to main content

teksilo_core/
widget.rs

1// SPDX-License-Identifier: MPL-2.0
2// SPDX-FileCopyrightText: 2026 FernTech
3
4use teksilo_canvas::{Canvas, Point, Rect, Size, SizeProposal};
5
6use crate::accessibility::AccessNodeBuilder;
7use crate::widget_id::WidgetId;
8
9mod cursor;
10mod event_context;
11mod layout_context;
12mod paint_context;
13
14pub use cursor::CursorIcon;
15pub use event_context::EventContext;
16pub(crate) use event_context::{CursorRequest, GestureAct};
17pub use layout_context::{LayoutContext, StackAxis};
18pub(crate) use paint_context::OverlayRects;
19pub use paint_context::{PaintContext, WidgetPlacement, WidgetTreeView};
20
21pub(crate) use event_context::{DismissScope, ShortcutMutation, TreeMutation};
22pub(crate) use layout_context::LayoutExtras;
23
24/// A child that is either pre-registered (ID) or waiting to be inserted.
25/// Used by the inline `child()` builder pattern: deferred children are stored
26/// inside the container and resolved recursively when `BuildContext::add()`
27/// inserts the container into the arena.
28pub enum PendingChild {
29    /// Already in the arena — use this ID directly.
30    Id(WidgetId),
31    /// Not yet in the arena — insert during resolution.
32    Deferred(Box<dyn Widget>),
33}
34
35impl std::fmt::Debug for PendingChild {
36    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
37        match self {
38            PendingChild::Id(id) => write!(f, "PendingChild::Id({:?})", id),
39            PendingChild::Deferred(_) => f.write_str("PendingChild::Deferred(..)"),
40        }
41    }
42}
43
44/// A widget's reply to a parent's layout query.
45///
46/// Carries four quantities that together describe how the widget participates
47/// in a stack's space distribution along the layout's main axis:
48///
49/// - `size` — the widget's wanted/ideal size; the floor for **growth**.
50/// - `flex` — positive-slack **grow** weight. `0.0` = rigid (no claim on
51///   surplus); `> 0.0` = wants a share of surplus proportional to its weight.
52/// - `min` — the hard floor for **compression**. A parent must never shrink
53///   the widget below this. Defaults to `size` (i.e. "I do not shrink").
54/// - `shrink` — negative-slack **shrink** weight. `0.0` = will not compress
55///   (the widget overflows before it shrinks); `> 0.0` = absorbs a share of an
56///   over-constraint deficit proportional to its weight, down to `min`. The
57///   stack distributes iteratively: a child that reaches `min` is frozen there
58///   and hands its remaining share on to the other shrinkable children; a
59///   rigid sibling never shrinks. Weights are proportional, so to shrink A fully
60///   before B starts give A a much larger weight (for example 1000 times B's).
61///
62/// `flex` and `shrink` are independent — as in CSS flexbox (`flex-grow` vs
63/// `flex-shrink`), a widget may grow but not shrink, or shrink but not grow.
64/// Most widgets just return a `Size`; the `From<Size>` impl wraps it as fully
65/// rigid (`flex = 0`, `shrink = 0`, `min = size`). Grow-bearing widgets
66/// (`Spacer`, `Expand`) use [`LayoutResponse::flexible`]; shrink-bearing ones
67/// (`Shrinkable`, single-line `TextWidget`) use [`LayoutResponse::shrinkable`].
68#[derive(Debug, Clone, Copy, PartialEq)]
69pub struct LayoutResponse {
70    pub size: Size,
71    pub flex: f32,
72    pub min: Size,
73    pub shrink: f32,
74}
75
76impl LayoutResponse {
77    pub const ZERO: Self = Self {
78        size: Size::ZERO,
79        flex: 0.0,
80        min: Size::ZERO,
81        shrink: 0.0,
82    };
83
84    /// A fully rigid response: wanted `size`, no growth, no compression
85    /// (`min == size`).
86    pub fn rigid(size: Size) -> Self {
87        Self {
88            size,
89            flex: 0.0,
90            min: size,
91            shrink: 0.0,
92        }
93    }
94
95    /// A grow-bearing response: wanted `size` with grow weight `flex`. Does
96    /// not shrink (`min == size`).
97    pub fn flexible(size: Size, flex: f32) -> Self {
98        Self {
99            size,
100            flex: flex.max(0.0),
101            min: size,
102            shrink: 0.0,
103        }
104    }
105
106    /// A shrink-bearing response: wanted `size`, compressible down to `min`
107    /// with shrink weight `shrink`. Does not grow (`flex == 0`). `min` is
108    /// clamped componentwise to be no larger than `size`.
109    pub fn shrinkable(size: Size, min: Size, shrink: f32) -> Self {
110        Self {
111            size,
112            flex: 0.0,
113            min: Size::new(min.width.min(size.width), min.height.min(size.height)),
114            shrink: shrink.max(0.0),
115        }
116    }
117
118    /// Builder: set the grow weight on an existing response.
119    pub fn with_flex(mut self, flex: f32) -> Self {
120        self.flex = flex.max(0.0);
121        self
122    }
123
124    /// Builder: set the shrink weight on an existing response.
125    pub fn with_shrink(mut self, shrink: f32) -> Self {
126        self.shrink = shrink.max(0.0);
127        self
128    }
129
130    /// Builder: set the compression floor (clamped componentwise ≤ `size`).
131    pub fn with_min(mut self, min: Size) -> Self {
132        self.min = Size::new(
133            min.width.min(self.size.width),
134            min.height.min(self.size.height),
135        );
136        self
137    }
138}
139
140impl From<Size> for LayoutResponse {
141    fn from(size: Size) -> Self {
142        Self {
143            size,
144            flex: 0.0,
145            min: size,
146            shrink: 0.0,
147        }
148    }
149}
150
151/// The full Widget trait for Level 2 (custom rendering) widgets.
152///
153/// # Adding a method here
154///
155/// A defaulted method added to this trait is **inert for every widget a builder
156/// method has touched** until the framework's same-node wrappers forward it.
157/// [`WidgetWithHandlers`](crate::widget_builder::WidgetWithHandlers) and the
158/// `TeksiBranch{,3,4}` sum types replace the widget at its own arena node, so an
159/// unforwarded method answers this default and the widget loses the behaviour
160/// silently — no compile error, and no test that drives the hook on a bare
161/// struct can see it. Those impls deny `clippy::missing_trait_methods` so the
162/// omission surfaces as a lint on them rather than as a defect in an app.
163pub trait Widget: std::fmt::Debug + std::any::Any {
164    /// Concrete type name of this widget (e.g.
165    /// `"teksilo_widgets::button::Button"`). The default implementation
166    /// resolves at the impl site via `std::any::type_name::<Self>()`,
167    /// so calls through `&dyn Widget` correctly dispatch to the
168    /// monomorphized fn for the concrete type — getting the
169    /// concrete name through the vtable without per-impl boilerplate.
170    ///
171    /// Used by [`crate::widget_tree::WidgetTree::widget_type_histogram`]
172    /// for the `widget.census` telemetry event. Custom
173    /// widgets that wrap their state in a generic struct may
174    /// override to give analytics a stable name independent of the
175    /// generic parameter.
176    fn type_name(&self) -> &'static str {
177        std::any::type_name::<Self>()
178    }
179
180    /// Compose child widgets. Called once after the widget is placed in the
181    /// arena, and again whenever the widget is marked for rebuild — a
182    /// `BindingLevel::Rebuild` binding, `rebuild_single_widget`, or a density
183    /// switch. A theme or locale switch does **not** rebuild: `set_theme` and
184    /// `set_locale` mark layout + paint dirty and leave the built subtree
185    /// standing, so anything derived from the theme or the locale must be read
186    /// per pass or bound to a signal rather than captured here.
187    /// Takes `&mut self` — store child IDs, signal handles, any state needed later.
188    /// Returns the list of root child IDs (empty for leaf widgets).
189    fn build(
190        &mut self,
191        _ctx: &mut crate::build_context::BuildContext,
192    ) -> Vec<crate::widget_id::WidgetId> {
193        Vec::new()
194    }
195
196    /// Respond to the parent's size proposal with this widget's wanted size,
197    /// grow/shrink weights, and compression floor (see [`LayoutResponse`]).
198    ///
199    /// Most widgets just return a `Size` (auto-converts via `From<Size>` to a
200    /// fully rigid response). Grow-bearing widgets (`Spacer`, `Expand`) return
201    /// a non-zero `flex`; shrink-bearing widgets (`Shrinkable`, single-line
202    /// `TextWidget`) return a non-zero `shrink` with a `min` floor.
203    ///
204    /// The parent honors `size` as a floor for growth and distributes positive
205    /// slack proportional to `flex`; when over-constrained it distributes the
206    /// deficit proportional to `shrink`, never below `min`.
207    ///
208    /// **Determinism / height-for-width contract.** This must be a *deterministic
209    /// function of the widget's state and the `proposal`*: two calls with the
210    /// same proposal in one layout pass must return the same value. The result
211    /// must be correct *for the proposal given* — in particular a
212    /// height-for-width widget queried with `{width: Some(w), height: None}`
213    /// must return its height *at width `w`*. The framework memoizes results per
214    /// `(widget, proposal)` within a pass (see
215    /// [`cacheable_layout`](Self::cacheable_layout)) to keep negotiation O(n).
216    ///
217    /// Side effects are permitted **as long as they are idempotent** — the cache
218    /// may skip them on a repeat query, so a side effect (e.g. snapshotting
219    /// measured state into a `Signal`) must be safe to run any number of times
220    /// ≥ 1 per pass and leave the same final state. Most measuring widgets
221    /// (`Collapse`, `SceneView`, inspector tabs) satisfy this with a guarded or
222    /// overwriting set. A side effect that must run on *every* call (e.g. a call
223    /// counter) is non-idempotent — opt out via `cacheable_layout`.
224    fn layout_response(&self, proposal: SizeProposal, ctx: &LayoutContext) -> LayoutResponse;
225
226    /// Whether this widget's [`layout_response`](Self::layout_response) may be
227    /// memoized by the per-pass layout cache. Defaults to `true`.
228    ///
229    /// Override to `false` only when `layout_response` has a **non-idempotent**
230    /// side effect that must run on every call (a call counter, a one-shot
231    /// trigger). Idempotent side effects — the common case, e.g. overwriting a
232    /// measured size into a `Signal` — do **not** need to opt out: the cache may
233    /// skip a redundant identical-proposal repeat, but the value was already
234    /// written and the final state is correct. The debug inspector's
235    /// `BoundsTracker` opts out defensively (its whole-tree snapshot is the
236    /// payload, not a by-product of sizing).
237    fn cacheable_layout(&self) -> bool {
238        true
239    }
240
241    /// Position children within the allocated bounds.
242    ///
243    /// Called for **every active widget on every layout pass** — including
244    /// leaves, which receive an empty `children` slice. It is therefore also the
245    /// canonical *"here are your final, parent-assigned bounds"* hook, and the
246    /// only one that runs during layout: `layout_response` sees a *proposal*, not
247    /// the outcome, and `paint` runs too late for anything the renderer consumes
248    /// before it (a node-level transform scope, a text engine's viewport).
249    ///
250    /// A widget whose bounds feed such a thing must read them here, not in
251    /// `paint`. `SceneView` is the motivating case: it folds `bounds.origin` into
252    /// the view transform the render walker pushes *around* its subtree, so a
253    /// scene that learned its origin only at paint time drew its content offset
254    /// by `-bounds.origin` — an error that then scaled with zoom.
255    ///
256    /// **If you mutate interior state here, keep the write and its consequences
257    /// together.** This hook runs *before* `paint`, so writing a field that
258    /// `paint` later uses as a compare-then-act change detector will silently
259    /// blind that detector. (Both text engines were bitten: `place_children` set
260    /// the `viewport_width` that `paint` compared against, so `paint` concluded
261    /// "unchanged" and skipped the `engine.set_viewport` + relayout it owed.)
262    /// Route such writes through one idempotent helper that both hooks call.
263    ///
264    /// **Do not `Signal::set` here at [`BindingLevel::Relayout`] or
265    /// [`Rebuild`](crate::binding::BindingLevel::Rebuild).** This runs inside the
266    /// layout pass, so dirtying the tree from it re-enters layout. A plain
267    /// `Cell`/`RefCell` (what the colour-picker leaves use to cache their bounds
268    /// for hit-testing) or a `RepaintOnly` signal is fine.
269    ///
270    /// [`BindingLevel::Relayout`]: crate::binding::BindingLevel::Relayout
271    fn place_children(
272        &self,
273        _bounds: Rect,
274        _proposal: SizeProposal,
275        _children: &mut [WidgetPlacement],
276        _ctx: &LayoutContext,
277    ) {
278        // Leaf widgets have no children to place.
279    }
280
281    /// Draw the widget's visual representation.
282    fn paint(&self, _bounds: Rect, _canvas: &mut Canvas, _ctx: &PaintContext) {
283        // Default: nothing to paint (layout-only containers).
284    }
285
286    /// Whether this widget wants its [`after_paint`](Self::after_paint)
287    /// hook to fire each frame. Returning `false` (the default) saves
288    /// a virtual call per widget per frame for the vast majority of
289    /// widgets that don't aggregate descendant geometry.
290    ///
291    /// Same opt-in pattern as
292    /// [`wants_descendant_redirects`](Self::wants_descendant_redirects).
293    fn wants_after_paint(&self) -> bool {
294        false
295    }
296
297    /// Called once per frame after this widget's subtree has finished
298    /// painting. Receives a read-only view of the layout-resolved
299    /// arena so a parent can read its descendants' final bounds —
300    /// e.g. `TitleBar` aggregates its drag region and control-button
301    /// rects into a single `HitRegions` payload for the Windows
302    /// backend's `WM_NCHITTEST`.
303    ///
304    /// Walk order is depth-first **post**-order: a parent's
305    /// `after_paint` runs after every descendant's `paint` has
306    /// committed.
307    ///
308    /// Default: empty. Only widgets that override
309    /// [`wants_after_paint`](Self::wants_after_paint) and return `true`
310    /// see this called.
311    fn after_paint(&self, _view: &WidgetTreeView<'_>, _ctx: &PaintContext) {}
312
313    /// Whether this widget wants its [`post_paint`](Self::post_paint)
314    /// hook to fire each frame. Returning `false` (the default) saves a
315    /// virtual call per widget per frame for the vast majority of widgets
316    /// that don't draw a foreground over their children.
317    ///
318    /// Same opt-in pattern as [`wants_after_paint`](Self::wants_after_paint).
319    fn wants_post_paint(&self) -> bool {
320        false
321    }
322
323    /// Draw a foreground layer *over* this widget's children.
324    ///
325    /// The normal [`paint`](Self::paint) emits a widget's draws *before*
326    /// its children — a backdrop. `post_paint` emits *after* the entire
327    /// child subtree, so its draws land on top. This is the supported way
328    /// for a composing widget to paint over its own descendants:
329    /// inset shadows, a focus ring that must overlay content, a scrim, or
330    /// `SceneView`'s "over" lightweight band (selection lasso, highlighted
331    /// connectors).
332    ///
333    /// Runs inside the same clip / transform / opacity / blur scopes as
334    /// the widget and its children, so a foreground decoration pans,
335    /// scales and clips consistently with the subtree it covers. It is
336    /// paint-only — no hit-testing and no accessibility node; for
337    /// interactive overlays that must escape the widget's bounds, use the
338    /// overlay system instead.
339    ///
340    /// Default: empty. Only widgets that override
341    /// [`wants_post_paint`](Self::wants_post_paint) and return `true` see
342    /// this called.
343    fn post_paint(&self, _bounds: Rect, _canvas: &mut Canvas, _ctx: &PaintContext) {}
344
345    /// Declare this widget's accessibility identity.
346    fn accessibility(&self, _builder: &mut AccessNodeBuilder) {}
347
348    /// Whether this widget wants the AT walker to consult its
349    /// [`a11y_redirect_descendant`](Self::a11y_redirect_descendant)
350    /// hook for *every* descendant during AT tree emission, not
351    /// just its direct arena children.
352    ///
353    /// Returning `true` opts this widget into ancestor-chain
354    /// queries: as the walker iterates each descendant's parent
355    /// to decide where the descendant's `NodeId` lands in the AT
356    /// tree, it walks up the arena from that parent and asks
357    /// every ancestor with this flag set. First `Some(_)` wins
358    /// (closest ancestor takes priority — same precedence as a
359    /// CSS-like cascade).
360    ///
361    /// Returning `false` (the default) makes the walker pay the
362    /// O(depth) ancestor walk only for trees that genuinely need
363    /// it. Only opt in if your widget actively places
364    /// non-direct-child descendant `NodeId`s in its own
365    /// `accessibility()` emission — `teksilo_scene::SceneView` is
366    /// the canonical example.
367    ///
368    /// Default: `false`.
369    fn wants_descendant_redirects(&self) -> bool {
370        false
371    }
372
373    /// Whether this widget decides, on every layout pass, which of its
374    /// children exist at all.
375    ///
376    /// Opting in changes what [`place_children`](Self::place_children)
377    /// receives and what the framework does with it:
378    ///
379    /// * the `children` slice carries **every** child, dormant ones included,
380    ///   rather than only the active ones — otherwise a container could never
381    ///   ask for a child back, having parked it;
382    /// * each [`WidgetPlacement::dormant`] arrives pre-set to that child's
383    ///   current state, and whatever the widget leaves there is applied: a
384    ///   child newly cleared is woken and laid out **in the same pass**, a
385    ///   child newly set is parked after the pass, with focus revalidated
386    ///   behind it.
387    ///
388    /// The cost of opting in is one iteration per child per pass, which is why
389    /// it is a choice rather than the rule: an ordinary container pays for its
390    /// active children only.
391    ///
392    /// This exists for containers that hold far more content than they show —
393    /// a scene viewport, a canvas, a map — where the off-screen half is not
394    /// merely invisible but should not be *reachable*: a card 90 000 px away
395    /// is a Tab stop between two visible ones and a node an assistive client
396    /// is offered. Collapsing its `size` to zero answers neither, because a
397    /// zero-size widget is still alive.
398    ///
399    /// A container that only ever hides one branch at a time wants
400    /// [`BuildContext::visible_when`](crate::build_context::BuildContext::visible_when)
401    /// instead: a gate per branch is cheaper than a pass per child, and that
402    /// is the shape of `Switcher`, a popover or a collapsed panel.
403    ///
404    /// Default: `false`.
405    fn culls_children(&self) -> bool {
406        false
407    }
408
409    /// Optional redirection hook for AT-tree placement of a child.
410    ///
411    /// The accessibility walker consults every ancestor that opts
412    /// in via
413    /// [`wants_descendant_redirects`](Self::wants_descendant_redirects),
414    /// starting at the child's immediate arena parent and walking
415    /// up to the root. An ancestor whose flag is `false` is
416    /// skipped without its hook ever being called, the immediate
417    /// parent included, and the walk carries on past it. First
418    /// `Some(_)` wins, scanned bottom-up (closest opted-in
419    /// ancestor takes priority). Returning
420    /// `Some(_)` tells the walker that this widget has *already*
421    /// placed `descendant`'s `NodeId` somewhere else (typically
422    /// under a synthetic node it emitted in its own
423    /// `accessibility()` call), and the walker should NOT add it
424    /// to its arena parent's children list.
425    ///
426    /// The returned `NodeId` is informational — it identifies the
427    /// new logical parent in case the walker wants to bookkeep
428    /// (e.g., dedupe). The walker does not validate that
429    /// `descendant`'s NodeId is actually in that target's children
430    /// list; it is the implementing widget's responsibility to
431    /// have placed it there during its `accessibility()` emission
432    /// (e.g. via `AccessNodeBuilder::attach_scene_child_under`).
433    ///
434    /// Used by `teksilo_scene::SceneView` to graft heavyweight
435    /// `Widget` items into an app-declared logical AT tree.
436    /// Other layered containers can adopt the same pattern.
437    ///
438    /// Default: `None` — no redirection.
439    fn a11y_redirect_descendant(
440        &self,
441        _self_id: WidgetId,
442        _descendant: WidgetId,
443    ) -> Option<accesskit::NodeId> {
444        None
445    }
446
447    /// Suggest an accessible title to an enclosing container that
448    /// wraps this widget as content — typically a modal / dialog
449    /// shell that wants to propagate the inner content's visible
450    /// title as the shell's own accessible name.
451    ///
452    /// Example: `ModalContainer` wraps a `DialogContent`. The
453    /// container owns the `Role::Dialog` node and needs a name;
454    /// `DialogContent` overrides this method to return its own
455    /// `title` string. The container queries this on its pending
456    /// content at build time and uses the result if set.
457    ///
458    /// Default: `None` — widgets that don't carry a natural
459    /// title don't need to override.
460    fn accessible_title_hint(&self) -> Option<String> {
461        None
462    }
463
464    /// The widget that *paints* this one's title, when it has one.
465    ///
466    /// Preferred over [`accessible_title_hint`](Self::accessible_title_hint)
467    /// where both are available: an enclosing container points at the
468    /// title node through a `labelled_by` relation instead of copying
469    /// its string, so the title keeps its own node and stays reviewable
470    /// by character rather than being announced only as part of the
471    /// container's name.
472    ///
473    /// Queried right after the content is mounted — `build()` runs
474    /// eagerly on insertion, so the title node already exists by then.
475    ///
476    /// Default: `None`.
477    fn accessible_title_node(&self) -> Option<crate::widget_id::WidgetId> {
478        None
479    }
480
481    /// Optional hint that directs initial focus to a specific
482    /// descendant when this widget is the root of a deferred-built
483    /// modal surface.
484    ///
485    /// The modal presentation pipeline consults this after building
486    /// the content subtree, in priority order: the caller's
487    /// `ModalRequest::focus_target` → the content widget's
488    /// `initial_focus_hint` → `first_focusable_descendant`.
489    /// `MessageBox` overrides this to return the widget id of its
490    /// configured default button, so platform-native button orderings
491    /// (Cancel-left + Default-right-but-focused) work without
492    /// forcing the default button to be the first focusable
493    /// descendant in tree-walk order.
494    ///
495    /// Default: `None` — widgets that don't need to direct initial
496    /// focus to a non-first-focusable descendant don't override.
497    fn initial_focus_hint(&self) -> Option<WidgetId> {
498        None
499    }
500
501    /// Where F6 lands in this widget's region when the region remembers no
502    /// focus, on a node marked as a
503    /// [focus region](crate::widget_builder::WidgetBuilder::focus_region):
504    /// the first of the region's Tab stops inside the subtree this names,
505    /// when it holds one, else the region's first Tab stop. A `DockingLayout`
506    /// side names its panel, so F6 lands in the panel and not on the activity
507    /// rail Tab meets first.
508    ///
509    /// Read by region landing only. Unlike
510    /// [`initial_focus_hint`](Self::initial_focus_hint) it is never a
511    /// window's or a modal's first focus, and it does not change Tab order.
512    ///
513    /// Default: `None`.
514    #[doc(hidden)]
515    fn focus_region_landing(&self) -> Option<WidgetId> {
516        None
517    }
518
519    /// The descendant whose accessibility node stands for this widget.
520    ///
521    /// Some composites keep everything an assistive technology reads on one
522    /// inner widget. A `SpinBox`'s editing field holds the focus, the caret,
523    /// the text and the value, so the field is the node a screen reader lands
524    /// on, and it is the node that has to carry the spin box's name and its
525    /// spin semantics. The composite's own node is then structure, and says
526    /// so with `Role::GenericContainer`, which the presentational pass
527    /// collapses.
528    ///
529    /// What remains is that an application can only reach the composite. A
530    /// `FormLayout` names it with `labelled_by`, an application gives it
531    /// `.access_label(..)`, `access_described_by` or a tooltip, all on the
532    /// composite's id, and all of that would land on a node no platform
533    /// adapter exposes. Returning `Some(inner)` makes the walker apply
534    /// everything attached to this widget (its builder overrides, its
535    /// relations, the tooltip it owns) to `inner`'s node instead, after
536    /// `inner`'s own, so the application keeps the last word. A relation that
537    /// names this widget is pointed at `inner`.
538    ///
539    /// Focus follows the same rule. An editor takes focus and the keys on its
540    /// own widget and keeps its text on a body inside it that is not
541    /// focusable; a reader reads the node an update names as focus when it
542    /// arrives, and the Linux adapter reports a caret move only on that node.
543    /// So while this widget holds keyboard focus, the update names `inner`'s
544    /// node as the focus, and an assistive `Focus` on `inner`, when `inner` is
545    /// not focusable, gives the keyboard to this widget.
546    ///
547    /// Only a live, strict descendant counts, and only while the walk reaches
548    /// it: this widget and every widget between the two walked normally,
549    /// neither excluded nor merged. Anything else is ignored and the overrides
550    /// stay where they were attached.
551    ///
552    /// Default: `None`.
553    fn accessibility_proxy(&self) -> Option<WidgetId> {
554        None
555    }
556
557    /// Which descendant a keyboard request for a context menu should target.
558    ///
559    /// The context-menu key (and Shift+F10) opens the menu of the **focused**
560    /// widget. For a data view that is the wrong node: `ListView`, `TreeView`,
561    /// `TableView`, `TreeTableView` and `GridView` are focusable as a whole and
562    /// their rows deliberately are not — the container owns focus and
563    /// `set_selected` is what tells assistive technology which row is current
564    /// (see `list_item_a11y`). Without this hook the chord would open the
565    /// *list's* menu rather than the selected row's, in exactly the widget
566    /// family where a per-row menu matters most.
567    ///
568    /// Return the widget id of the row (or cell, or tile) the menu should be
569    /// about. The dispatcher then walks up from there, so a view whose rows
570    /// carry no factory of their own still finds the container's.
571    ///
572    /// Followed from hop to hop, so each widget names only its next one: a
573    /// view names its current row, the row names the delegate inside it (a
574    /// table's row its cell, the cell its delegate). The keyboard then reaches
575    /// the factory a right click on the row reaches when it is on the widget
576    /// the delegate returns; one on a deeper descendant is reached by a right
577    /// click only. A screen reader's `ShowContextMenu` on any of these nodes
578    /// starts at the same place.
579    ///
580    /// Default: `None` — the focused widget is the target, which is right for
581    /// every widget that is itself the thing the user is pointing at.
582    fn context_menu_key_target(&self) -> Option<WidgetId> {
583        None
584    }
585
586    /// Take a section another node adds to this context menu (see
587    /// [`ContextMenuContribution`](crate::widget_builder::ContextMenuContribution)),
588    /// appending it after this menu's own rows. Called once per section,
589    /// before the menu is built, innermost contributor first.
590    ///
591    /// `MenuList` takes any section. The default refuses it and hands it back,
592    /// and the menu opens without it.
593    fn append_context_menu_section(
594        &mut self,
595        section: Box<dyn Widget>,
596    ) -> Result<(), Box<dyn Widget>> {
597        Err(section)
598    }
599
600    /// Return the child widget IDs that this widget manages.
601    fn children(&self) -> Vec<WidgetId> {
602        Vec::new()
603    }
604
605    /// Optional override for the child ORDER presented to assistive
606    /// technology, when it must differ from the paint / z-order child
607    /// order returned by [`children`](Self::children).
608    ///
609    /// Return `None` (the default) to let the accessibility walker use the
610    /// arena's child order — correct for almost every widget. Return
611    /// `Some(ids)` to reorder (or restrict) how children appear in the AT
612    /// tree and in the linear Tab reading order, WITHOUT affecting layout or
613    /// paint. `TableView` / `TreeTableView` use this to read the header
614    /// before the body rows even though they build the body first so it
615    /// paints beneath the header (WCAG 1.3.2 Meaningful Sequence).
616    ///
617    /// The ids need not be children: any active widget other than an ancestor
618    /// of this one may be named (a descendant, or a sibling's subtree as
619    /// `GridView` names its detail band). That places it elsewhere in the AT
620    /// tree than in the arena; layout and paint stay on the arena. `TreeView`
621    /// nests each row under its parent row this way, so a screen reader
622    /// counts the row's level from its ancestors. The rules that come with
623    /// it:
624    ///
625    /// * each id must appear in the AT tree exactly once: the widget the
626    ///   arena would otherwise emit it under must leave it out of its own
627    ///   list (return a list without it), or its claim is a second one, which
628    ///   is skipped with a "duplicate accessibility child" report and not
629    ///   built again;
630    /// * the widget that names an id owns its placement;
631    /// * an arena node between this widget and a named descendant that no
632    ///   list names (a `DragSurface` around a tree row) is not visited, so it
633    ///   emits no node, and an `access_*` override, a tooltip claim or a
634    ///   proxy on it has nowhere to go;
635    /// * a named widget's bounds are still its arena bounds, so a node
636    ///   visited through a parent that is not its arena parent reads the same
637    ///   rectangle. The space they are declared in is the AT parent's, so do
638    ///   not move a widget out from under a content transform (`SceneView`)
639    ///   or into one.
640    fn accessibility_children(&self) -> Option<Vec<WidgetId>> {
641        None
642    }
643
644    /// Downcast hook. Default implementation returns `None`; concrete
645    /// widgets override with `Some(self)` when they want to expose
646    /// their concrete type to test-level introspection or reflection.
647    /// The trait already bounds on `std::any::Any` so concrete types
648    /// satisfy the `'static` requirement.
649    fn as_any(&self) -> Option<&dyn std::any::Any> {
650        None
651    }
652
653    /// Mutable counterpart of [`as_any`](Self::as_any). Default
654    /// returns `None`; widgets that want to expose mutable state to
655    /// tests (e.g. so a test can mutate a `Scene` inside a
656    /// `SceneView` post-layout) override with `Some(self)`. Should
657    /// follow the same opt-in pattern as `as_any`: only widgets
658    /// that opt into `&` introspection should opt into `&mut`.
659    fn as_any_mut(&mut self) -> Option<&mut dyn std::any::Any> {
660        None
661    }
662
663    /// Whether this widget clips its children to its bounds.
664    fn clips_children(&self) -> bool {
665        false
666    }
667
668    /// The rectangle (in **absolute tree coordinates**) that best *represents*
669    /// this widget when the framework reveals it into an ancestor scroll area on
670    /// focus gain. Returning `None` (the default) reveals the widget's whole
671    /// bounds — correct for most controls.
672    ///
673    /// A widget that can be much taller than a viewport — a `RichTextEditor`
674    /// grown inside a page `ScrollArea`, a `ListView` / `TreeView` taller than
675    /// its scroller — should override this to return the sub-rectangle the user
676    /// actually cares about (the caret line, the selected row). Otherwise
677    /// [`scroll_focused_into_view`](crate::widget_tree::WidgetTree) reveals the
678    /// *entire* box, which for a tall widget scrolls the page to its bottom on a
679    /// click that only meant to place the caret near the top. The returned rect
680    /// feeds the same ancestor-only `scroll_rect_into_view` engine the caret /
681    /// selection follow uses (the focused widget itself is excluded), so it
682    /// never double-scrolls against the widget's own internal follow.
683    ///
684    /// `bounds` is this widget's current absolute rectangle as the arena stores
685    /// it, so an override can place its interior rect without depending on a
686    /// paint-set origin.
687    fn focus_reveal_rect(&self, _bounds: Rect) -> Option<Rect> {
688        None
689    }
690
691    /// Whether the point lies inside this widget's *actual* shape, not
692    /// just its rectangular bounds. Consulted by hit-testing right after
693    /// the bounds check: returning `false` for a point that *is* inside
694    /// the bounding box makes the widget transparent to the click there,
695    /// so it **falls through** to whatever sibling is painted underneath
696    /// (the same machinery as a fully pass-through node, but shape-aware).
697    ///
698    /// Both arguments are in the widget's bounds space: `local_point` is
699    /// the point being tested and `bounds` is this widget's rectangle, so
700    /// a non-rectangular widget can test the point against its silhouette.
701    ///
702    /// The default returns `true` for any in-bounds point (a plain
703    /// rectangle), so every existing widget is unaffected. Override for
704    /// irregular shapes — an ellipse / cloud scene node, a circular
705    /// handle — so a click lands on the shape you see, not its bounding
706    /// box, and clicks in the transparent corners reach the node beneath.
707    /// The lightweight tier answers the same question from a *value* —
708    /// `SceneItem::shape` returns an `ItemShape` that every query in
709    /// `teksilo-scene` derives from — rather than from a predicate. The two
710    /// are deliberately not the same shape of API and deliberately not the
711    /// same name: a widget is hit-tested by the arena, one point at a time,
712    /// with its bounds already in hand.
713    fn hit_shape(&self, _local_point: Point, _bounds: Rect) -> bool {
714        true
715    }
716
717    /// Veto a hit on one of this widget's **direct children**, per point.
718    ///
719    /// Called during the arena's reverse-sibling walk, once per child, before
720    /// the recursion descends into it. Returning `false` makes the walk fall
721    /// through to the next sibling exactly as a [`hit_shape`](Self::hit_shape)
722    /// rejection on that child would, so the point can land on a lower sibling
723    /// or, finally, on this widget itself.
724    ///
725    /// `point` is in the space this widget's
726    /// [`place_children`](Self::place_children) writes — for an ordinary node
727    /// that is the same absolute space its own bounds are in; for a
728    /// content-transform node (a `SceneView`) it is content coordinates, the
729    /// point already mapped through the inverse of the content transform.
730    ///
731    /// # What this is for
732    ///
733    /// A widget that owns a **second picking system over the same area** — a
734    /// `SceneView`'s lightweight items, a chart's overlay marks, a terminal's
735    /// link layer. Without it the two systems answer independently: the widget
736    /// can paper over the disagreement inside one handler, but press feedback,
737    /// focus-on-release, the touch hold route, the cursor and drag all resolve
738    /// from the arena's answer, so five of the six stay wrong.
739    ///
740    /// It is **not** a replacement for
741    /// [`hit_transparent`](crate::widget_builder::HandlerSet::hit_transparent),
742    /// which is the right tool for a decorative overlay: that is a per-*node*
743    /// declaration ("I never absorb a press"), set from the outside by whoever
744    /// builds the node, and it cannot express "reject this child here and
745    /// accept it one pixel over". This is the per-*point* question, answered by
746    /// the parent that knows why.
747    ///
748    /// # Contract
749    ///
750    /// Must be **pure and cheap**: it runs once per child per hit test, and a
751    /// hit test runs on every pointer sample. It must not mutate anything the
752    /// walk can observe, and — because it runs inside the router — it must not
753    /// re-enter any `RefCell` a handler might already hold. A widget that
754    /// answers from a per-layout snapshot should memoise per walk; the default
755    /// returns `true`, so a widget that does not override it pays one
756    /// devirtualizable call per child.
757    fn accepts_child_hit(&self, _child: WidgetId, _point: Point) -> bool {
758        true
759    }
760
761    /// How far **outside** its own bounds this widget still absorbs a press,
762    /// per edge, for the pointer that is asking.
763    ///
764    /// Consulted **inside** the exact hit test: within one parent, children
765    /// that declare an outset are tested against their outset bounds *before*
766    /// the ordinary reverse-sibling walk, so a 6 dp splitter gutter wins over
767    /// the panes it overlaps instead of losing to whichever pane is painted on
768    /// top. This is the mechanism for a thin **grip**, and the only one of the
769    /// three that can beat a competing target.
770    ///
771    /// Three rules make it safe to add to a widget that already works:
772    ///
773    /// * **Hit-only.** No layout moves, nothing repaints differently, and a
774    ///   Compact build renders byte for byte as it did. The outset exists
775    ///   between the pointer and the arena and nowhere else.
776    /// * **It never escapes the parent.** The recursion has already tested the
777    ///   parent's own bounds before it looks at any child, so an outset can
778    ///   only ever claim space the parent already owns — including through a
779    ///   `clips_children` ancestor, whose rectangle gated the descent.
780    /// * **Zero for a precise pointer** unless the widget deliberately says
781    ///   otherwise. A mouse cursor's hot-spot is exact and occludes nothing, so
782    ///   widening its targets steals clicks. Check
783    ///   `kind.is_direct()` (or accept every kind explicitly, as a control with
784    ///   a genuinely undersized mouse grip may) before returning anything
785    ///   non-zero.
786    ///
787    /// The insets are **reading-order**: `leading` is the left edge in an LTR
788    /// UI and the right edge in an RTL one. The default returns
789    /// [`EdgeInsets::ZERO`](teksilo_canvas::EdgeInsets::ZERO), so every existing
790    /// widget is unaffected.
791    ///
792    /// A grip's conventional value is `9 dp` for a direct pointer and `0 dp`
793    /// for a precise one — enough to lift a 6 dp gutter to a 24 dp target.
794    fn hit_outset(
795        &self,
796        _kind: teksilo_tokens::PointerKind,
797        _tokens: &teksilo_tokens::InputTokens,
798    ) -> teksilo_canvas::EdgeInsets {
799        teksilo_canvas::EdgeInsets::ZERO
800    }
801
802    /// This widget's own say in the *miss-only* slop pass, overriding the
803    /// density default for its node.
804    ///
805    /// Third link of the precedence chain — `no_hit_slop` beats a node-level
806    /// `.hit_slop(..)`, which beats this, which beats
807    /// [`HitSlop::for_pointer`]. Return [`HitSlop::NONE`] to opt a widget out
808    /// of re-attribution entirely, or a larger `up_to` to say that a control
809    /// deserves topping up further than the density asks.
810    ///
811    /// `None` (the default) means "no opinion — use the density default".
812    ///
813    /// [`HitSlop::for_pointer`]: crate::pointer::hit_slop::HitSlop::for_pointer
814    /// [`HitSlop::NONE`]: crate::pointer::hit_slop::HitSlop::NONE
815    fn hit_slop(
816        &self,
817        _kind: teksilo_tokens::PointerKind,
818        _tokens: &teksilo_tokens::InputTokens,
819    ) -> Option<crate::pointer::hit_slop::HitSlop> {
820        None
821    }
822
823    /// How far a *missed* press is from this widget's actual silhouette, in the
824    /// widget's own bounds space.
825    ///
826    /// The key to the miss-only slop pass: once the exact pass has found
827    /// nothing eligible, the framework asks every nearby node how far away it
828    /// really is and re-attributes the press to the closest one still inside
829    /// its earned outset.
830    ///
831    /// The default measures to the bounding rectangle, which is right for the
832    /// rectangular majority. A **round or wedge** control overrides it beside
833    /// its existing [`hit_shape`](Self::hit_shape) so the slop follows the
834    /// shape the user aimed at rather than the box it was laid out in — a
835    /// press past the corner of a radio dot's box is further from the dot than
836    /// a press past its edge, and should lose to a neighbour that is nearer.
837    ///
838    /// Returning `None` withdraws the widget from the pass altogether, which is
839    /// the shape-level equivalent of `no_hit_slop`.
840    ///
841    /// This is **never** consulted by the exact pass, so overriding it cannot
842    /// change where an ordinary click lands.
843    fn hit_distance(&self, local_point: Point, bounds: Rect) -> Option<f32> {
844        Some(crate::pointer::hit_slop::rect_distance(bounds, local_point))
845    }
846
847    /// The interactive sub-regions this widget **paints inside its own single
848    /// node** — a scroll bar's thumb, a slider's knob, a header cell's filter
849    /// affordance.
850    ///
851    /// Reporting only: implementing it changes no layout and no hit test by
852    /// itself. It exists because a control that draws several targets on one
853    /// canvas is otherwise opaque — the router cannot route a coarse press to
854    /// the nearest one, and the target-conformance audit cannot see that any of
855    /// them exists, let alone that it clears the floor.
856    ///
857    /// `bounds` is this widget's current rectangle, and the returned rects are
858    /// in the same space. Build them with
859    /// [`partition_targets`](crate::partition::partition_targets) where the
860    /// split is a horizontal division, so the geometry the widget paints and
861    /// the geometry it reports cannot drift apart.
862    ///
863    /// The default returns an empty list: a widget whose node *is* its target
864    /// has nothing to add.
865    fn target_regions(&self, _bounds: Rect) -> Vec<crate::partition::TargetRegion> {
866        Vec::new()
867    }
868
869    /// How `rebuild_single_widget` treats this widget's existing children
870    /// when re-running its `build()`.
871    ///
872    /// **`false` (default) — re-derive.** Rebuild is "tear down and
873    /// reconstruct": every old child subtree is destroyed up front, then
874    /// `build()` produces a fresh set. The right semantic for data-driven
875    /// widgets like `Repeater` / `ListView` that rebuild their children from
876    /// current model state with fresh `WidgetId`s. A `false` widget must NOT
877    /// re-attach an old child id — it has already been destroyed.
878    ///
879    /// **`true` — reconcile.** `build()` re-attaches (by id) the children it
880    /// keeps and drops the rest. The framework keeps every re-attached child's
881    /// subtree intact — focus, scroll offset, text contents, signal
882    /// subscriptions all survive — and destroys only the old children the new
883    /// build dropped *and* did not re-parent elsewhere. This is the mode for
884    /// widgets that memoize stateful children across rebuilds:
885    ///
886    /// * `Switcher` keeps every mounted page alive so switching tabs doesn't
887    ///   wipe the inactive pages' state.
888    /// * `SceneView` re-pushes the same heavyweight scene-widget ids each
889    ///   rebuild (draining drag-to-move / marquee commits) — they must stay
890    ///   attached or the cards "disappear" on every drag end.
891    /// * `TabWidget` / `DockingLayout` / `CompositeTooltip` re-attach memoized
892    ///   panes / a one-shot body widget that cannot be reconstructed.
893    /// * `MenuBar` re-derives its menu triggers fresh each build (the model may
894    ///   have changed — the reconcile reaps the superseded ones) while keeping
895    ///   its memoized leading/trailing slot widgets, so a stateful slot control
896    ///   survives a model-version rebuild.
897    ///
898    /// The reconcile follows **authoritative parent pointers**, so a kept
899    /// subtree that `build()` re-parents *out* of a dropped sibling and into
900    /// the new tree survives — it is not swept via the dropped sibling's now
901    /// stale `children` list. Dropped children are genuinely destroyed (state
902    /// unmounted, arena slots freed), not left as stranded, still-active
903    /// orphans.
904    fn preserves_children_on_rebuild(&self) -> bool {
905        false
906    }
907
908    /// Whether this widget, used as tooltip content, currently has anything
909    /// worth showing.
910    ///
911    /// Consulted by `WidgetTree` just before a dwell matures into an overlay.
912    /// Returning `false` cancels the show — the anchor simply has no tooltip
913    /// this time — so a blank or unresolved string does not pop an empty
914    /// chromed bubble, which reads as a rendering fault rather than as
915    /// "nothing to say here".
916    ///
917    /// Defaults to `true`: content that hosts an arbitrary widget tree (a
918    /// chart, a progress row) is meaningful without any text, and a custom
919    /// content widget must never be suppressed by a check it did not opt into.
920    /// Only widgets whose *whole* payload is a string — `TooltipWidget` — have
921    /// a well-defined notion of being empty.
922    fn tooltip_has_content(&self) -> bool {
923        true
924    }
925
926    /// Declare the rebindable keyboard shortcuts this widget exposes,
927    /// *without* installing handlers. The framework calls this at
928    /// arena insertion time (before `build()`) and at certain lazy
929    /// boundaries (e.g. `Switcher` walks declarations on its
930    /// not-yet-mounted `Pending` slots), so settings UIs and the
931    /// `ShortcutRegistry` see the keystrokes the moment the owning
932    /// container mounts — even if `build()` hasn't run.
933    ///
934    /// Pair this with `BuildContext::register_shortcut` in `build()`
935    /// to install the matching `on_activate` handler: the build-time
936    /// registration *upserts* the declared entry, preserving any user
937    /// override and the declared keystrokes while attaching the
938    /// closure that actually fires.
939    ///
940    /// The returned shortcuts may omit `on_activate` (a metadata-only
941    /// declaration). When matched at dispatch time without a
942    /// registered handler, the framework synthesizes a no-parameter
943    /// intent from the shortcut's id — same path as a build-time
944    /// registration with `on_activate: None`.
945    ///
946    /// Default: empty (no declared shortcuts).
947    fn declare_shortcuts(&self) -> Vec<crate::shortcut::Shortcut> {
948        Vec::new()
949    }
950
951    /// Extract attached handler set from a `WidgetWithHandlers` wrapper.
952    /// Called during arena insertion to transfer handlers to the `WidgetNode`.
953    /// Default: returns `None` (no attached handlers).
954    fn take_handler_set(&mut self) -> Option<crate::widget_builder::HandlerSet> {
955        None
956    }
957}
958
959/// A boxed widget is a widget.
960///
961/// Without this, `Box<dyn Widget>` is the one widget-shaped value that cannot
962/// go where a widget goes: `.child(..)`, a `Vec` of children, a `match` arm.
963/// 238 functions in `teksilo-widgets` alone return it, the `teksu!` macro's own
964/// over-four-arms advice recommends it, and only two containers in the whole
965/// catalog (`Switcher`, `Cycle`) shipped a `child_boxed` to take it. Every
966/// other call site had to invent an adapter widget, which costs a real arena
967/// node per use.
968///
969/// Every method forwards to the inner widget, so the box is invisible to the
970/// arena: it adds no node, no layout pass and no AT element. In particular
971/// `as_any` / `as_any_mut` forward, so `EventContext::with_widget_mut::<W>`
972/// downcasts to the widget that was boxed rather than to the box.
973/// `#[deny(clippy::missing_trait_methods)]` for the reason the trait's own
974/// header gives: the arena holds `Box<dyn Widget>`, so a call on a node
975/// resolves to *this* impl and not to the vtable. A method left out here
976/// answers with the trait default for every widget in the tree, the
977/// widget's own override is never reached, and nothing fails to compile —
978/// which is exactly how `accepts_child_hit` and `culls_children` went
979/// missing when this impl and those two methods were written on separate
980/// branches and merged cleanly.
981#[deny(clippy::missing_trait_methods)]
982impl<W: Widget + ?Sized> Widget for Box<W> {
983    fn type_name(&self) -> &'static str {
984        (**self).type_name()
985    }
986
987    fn build(
988        &mut self,
989        ctx: &mut crate::build_context::BuildContext,
990    ) -> Vec<crate::widget_id::WidgetId> {
991        (**self).build(ctx)
992    }
993
994    fn layout_response(&self, proposal: SizeProposal, ctx: &LayoutContext) -> LayoutResponse {
995        (**self).layout_response(proposal, ctx)
996    }
997
998    fn cacheable_layout(&self) -> bool {
999        (**self).cacheable_layout()
1000    }
1001
1002    fn place_children(
1003        &self,
1004        bounds: Rect,
1005        proposal: SizeProposal,
1006        children: &mut [WidgetPlacement],
1007        ctx: &LayoutContext,
1008    ) {
1009        (**self).place_children(bounds, proposal, children, ctx)
1010    }
1011
1012    fn paint(&self, bounds: Rect, canvas: &mut Canvas, ctx: &PaintContext) {
1013        (**self).paint(bounds, canvas, ctx)
1014    }
1015
1016    fn wants_after_paint(&self) -> bool {
1017        (**self).wants_after_paint()
1018    }
1019
1020    fn after_paint(&self, view: &WidgetTreeView<'_>, ctx: &PaintContext) {
1021        (**self).after_paint(view, ctx)
1022    }
1023
1024    fn wants_post_paint(&self) -> bool {
1025        (**self).wants_post_paint()
1026    }
1027
1028    fn post_paint(&self, bounds: Rect, canvas: &mut Canvas, ctx: &PaintContext) {
1029        (**self).post_paint(bounds, canvas, ctx)
1030    }
1031
1032    fn accessibility(&self, builder: &mut AccessNodeBuilder) {
1033        (**self).accessibility(builder)
1034    }
1035
1036    fn wants_descendant_redirects(&self) -> bool {
1037        (**self).wants_descendant_redirects()
1038    }
1039
1040    fn a11y_redirect_descendant(
1041        &self,
1042        self_id: WidgetId,
1043        descendant: WidgetId,
1044    ) -> Option<accesskit::NodeId> {
1045        (**self).a11y_redirect_descendant(self_id, descendant)
1046    }
1047
1048    fn accessible_title_hint(&self) -> Option<String> {
1049        (**self).accessible_title_hint()
1050    }
1051
1052    fn accessible_title_node(&self) -> Option<crate::widget_id::WidgetId> {
1053        (**self).accessible_title_node()
1054    }
1055
1056    fn initial_focus_hint(&self) -> Option<WidgetId> {
1057        (**self).initial_focus_hint()
1058    }
1059
1060    fn focus_region_landing(&self) -> Option<WidgetId> {
1061        (**self).focus_region_landing()
1062    }
1063
1064    fn accessibility_proxy(&self) -> Option<WidgetId> {
1065        (**self).accessibility_proxy()
1066    }
1067
1068    fn context_menu_key_target(&self) -> Option<WidgetId> {
1069        (**self).context_menu_key_target()
1070    }
1071
1072    fn append_context_menu_section(
1073        &mut self,
1074        section: Box<dyn Widget>,
1075    ) -> Result<(), Box<dyn Widget>> {
1076        (**self).append_context_menu_section(section)
1077    }
1078
1079    fn children(&self) -> Vec<WidgetId> {
1080        (**self).children()
1081    }
1082
1083    fn accessibility_children(&self) -> Option<Vec<WidgetId>> {
1084        (**self).accessibility_children()
1085    }
1086
1087    fn as_any(&self) -> Option<&dyn std::any::Any> {
1088        (**self).as_any()
1089    }
1090
1091    fn as_any_mut(&mut self) -> Option<&mut dyn std::any::Any> {
1092        (**self).as_any_mut()
1093    }
1094
1095    fn clips_children(&self) -> bool {
1096        (**self).clips_children()
1097    }
1098
1099    fn focus_reveal_rect(&self, bounds: Rect) -> Option<Rect> {
1100        (**self).focus_reveal_rect(bounds)
1101    }
1102
1103    fn hit_shape(&self, local_point: Point, bounds: Rect) -> bool {
1104        (**self).hit_shape(local_point, bounds)
1105    }
1106
1107    fn hit_outset(
1108        &self,
1109        kind: teksilo_tokens::PointerKind,
1110        tokens: &teksilo_tokens::InputTokens,
1111    ) -> teksilo_canvas::EdgeInsets {
1112        (**self).hit_outset(kind, tokens)
1113    }
1114
1115    fn hit_slop(
1116        &self,
1117        kind: teksilo_tokens::PointerKind,
1118        tokens: &teksilo_tokens::InputTokens,
1119    ) -> Option<crate::pointer::hit_slop::HitSlop> {
1120        (**self).hit_slop(kind, tokens)
1121    }
1122
1123    fn hit_distance(&self, local_point: Point, bounds: Rect) -> Option<f32> {
1124        (**self).hit_distance(local_point, bounds)
1125    }
1126
1127    fn accepts_child_hit(&self, child: crate::widget_id::WidgetId, point: Point) -> bool {
1128        (**self).accepts_child_hit(child, point)
1129    }
1130
1131    fn culls_children(&self) -> bool {
1132        (**self).culls_children()
1133    }
1134
1135    fn target_regions(&self, bounds: Rect) -> Vec<crate::partition::TargetRegion> {
1136        (**self).target_regions(bounds)
1137    }
1138
1139    fn preserves_children_on_rebuild(&self) -> bool {
1140        (**self).preserves_children_on_rebuild()
1141    }
1142
1143    fn tooltip_has_content(&self) -> bool {
1144        (**self).tooltip_has_content()
1145    }
1146
1147    fn declare_shortcuts(&self) -> Vec<crate::shortcut::Shortcut> {
1148        (**self).declare_shortcuts()
1149    }
1150
1151    fn take_handler_set(&mut self) -> Option<crate::widget_builder::HandlerSet> {
1152        (**self).take_handler_set()
1153    }
1154}