GPU-accelerated UI toolkit (Vulkan)
git clone https://git.lucas.co/cce-ui.git
refactor(widget): WidgetHost 38 -> 31; the legacy tuple views are WidgetHostExt
extra_quads, extra_arcs, extra_circles, all_quads, all_rounded_quads,
highlight_quad and corner_style -- what a widget paints projected onto the
pre-display-list surface -- moved to WidgetHostExt, computed from
paint_model().paint(content_rect()) exactly as Adapted computed them; Adapted's
private content_rect / painted_prims / visible_children / own_plain_quads went
with them, and Owned no longer forwards them. The hosts that still draw a
widget through these (the designer's render loop, the gallery, the display
manager's greeter, the settings app's flat collector, cce-secrets, the
flat-host bridge) call them as before; no app changed. The trait default
paint_self, which serves only model-less hosts, draws its rounded background
from its colour and corner style directly.
Checked: the workspace builds, every reader's tests pass, and the designer,
the demo, the gallery, cce-files, cce-secrets, the greeter and the settings
app drew identically to the pixel before and after (scale-2 shadow).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CLAUDE.md | 12 +-
docs/rfc-core-rebuild.md | 7 +
src/scene/painter.rs | 6 +-
src/widget/container/menu.rs | 5 +-
src/widget/container/paginator.rs | 9 +-
src/widget/container/parameters_bg.rs | 10 +-
src/widget/display/graph.rs | 6 +-
src/widget/display/progress_bar.rs | 8 +-
src/widget/display/separator.rs | 2 +-
src/widget/display/status_bar.rs | 4 +-
src/widget/display/status_dot.rs | 4 +-
src/widget/display/usage_bar.rs | 6 +-
src/widget/input/button.rs | 4 +-
src/widget/input/checkbox.rs | 2 +-
src/widget/input/color_selector.rs | 2 +-
src/widget/input/slider.rs | 4 +-
src/widget/input/text_box.rs | 2 +-
src/widget/mod.rs | 248 ++++++++++++++++++++++++++--------
src/widget/model.rs | 194 +-------------------------
src/widget/owned.rs | 9 --
20 files changed, 241 insertions(+), 303 deletions(-)
diff --git a/CLAUDE.md b/CLAUDE.md
index af4bf1e..6b20c7c 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -1671,7 +1671,7 @@ Modules:
### `WidgetHost` (formerly the `Element` god-trait)
-`WidgetHost` (`src/widget/mod.rs`) is the single 38-method host surface the machinery
+`WidgetHost` (`src/widget/mod.rs`) is the single 31-method host surface the machinery
(context routing, paint walk, render loop, app dyn broadcasts) sees, produced by the RFC's 6bd
shrink-then-rename of the old ~125-method `Element` god-trait. Its ONE production implementor
is `Adapted<W>`; concrete widget behavior lives on the narrow `Layout`/`Paint`/`Input` traits
@@ -1681,7 +1681,7 @@ are GONE from the trait — events route through `handle_event`, and apps drain
through the concrete inherent `Adapted<W>` methods. See the RFC's blueprint notes before
adding anything to this trait.
-**What a host's widget model answers is not a trait slot** (since 2026-10-08, 57 → 38).
+**What a host's widget model answers is not a trait slot** (since 2026-10-08, 57 → 31).
The host hands out its widget as its narrow traits — `layout_model()`, `paint_model()`,
`input_model()` / `input_model_mut()` (`Adapted` returns its inner widget; a test shim that
implements `WidgetHost` directly gets `NoModel`'s defaults, or returns itself after
@@ -1690,7 +1690,13 @@ host, `dyn` included, carries what used to be one-line forwards: `focus_role`, `
`blocks_root_plate_drag`, `wants_tick`, `is_scrollable`, the `a11y_*` reads and acts,
`set_modifiers`, `context_action`, `color`, `solid_border`, `widget_font`,
`clips_children`, `renders_own_subtree`, `z_index`, `preferred_height`, plus the pure
-derivations `label`, `corner_radii`, `mark_dirty`. Call them as before, with
+derivations `label`, `corner_radii`, `mark_dirty` — and the legacy tuple views
+(`extra_quads`, `extra_arcs`, `extra_circles`, `all_quads`, `all_rounded_quads`,
+`highlight_quad`, `corner_style`): what a widget paints projected onto the
+pre-display-list surface, computed from `paint_model().paint(content_rect())` the way
+`Adapted` computed them, for the hosts that still draw a widget through them rather than
+`paint_self` (the designer's render loop, the gallery, the display manager's greeter, the
+settings app's flat collector, cce-secrets, the flat-host bridge). Call them as before, with
`cce_ui::widget::WidgetHostExt` in scope. A method stays ON the trait only when the host
adds something the model cannot (visibility gating, the content rect, child recursion,
registry state). `plate_bevel` is gone: nothing overrode it, so it was always `None`.
diff --git a/docs/rfc-core-rebuild.md b/docs/rfc-core-rebuild.md
index e215d0e..540983b 100644
--- a/docs/rfc-core-rebuild.md
+++ b/docs/rfc-core-rebuild.md
@@ -2073,6 +2073,13 @@ Constraint respected: **each crate still builds standalone** — the new core is
radius, is-Ramp flag) at re-parent time instead of the pointer —
same refresh cadence, no deref of potentially-dead memory; watch
the one-frame rect lag on resize if reads move to snapshots.
+ - **WidgetHost 38 → 31 (the same day).** The legacy tuple views (`extra_quads`,
+ `extra_arcs`, `extra_circles`, `all_quads`, `all_rounded_quads`, `highlight_quad`,
+ `corner_style`) moved to `WidgetHostExt` too, computed from the paint model exactly as
+ `Adapted` did (its private `content_rect` / `painted_prims` / `visible_children` went
+ with them). Five apps still draw through them; moving those to `paint_self` is what
+ retires the views themselves, and it changes how some look (cce-secrets draws its
+ controls flat through them). Every app that reads them drew identically to the pixel.
- **WidgetHost 57 → 38 (2026-10-08).** The trait had grown back past the blueprint's ~55
with the keyboard and accessibility hooks, and most of what `Adapted` implemented was a
one-line forward to a narrow trait. The narrow traits are dyn-compatible, so the host now
diff --git a/src/scene/painter.rs b/src/scene/painter.rs
index cae6c02..b2b8aea 100644
--- a/src/scene/painter.rs
+++ b/src/scene/painter.rs
@@ -369,15 +369,15 @@ mod tests {
fn color(&self) -> [f32; 4] {
[0.2, 0.4, 0.6, 1.0]
}
+ fn corner_style(&self, _rect: Rect) -> Option<(f32, (bool, bool, bool, bool))> {
+ Some((4.0, (true, true, true, true)))
+ }
}
impl WidgetHost for Rounded {
crate::impl_widget_base!(Rounded);
fn paint_model(&self) -> &dyn crate::widget::Paint {
self
}
- fn corner_style(&self) -> (f32, (bool, bool, bool, bool)) {
- (4.0, (true, true, true, true))
- }
}
let mut ctx = UiContext::new();
let mut w = Rounded { base: Widget::new() };
diff --git a/src/widget/container/menu.rs b/src/widget/container/menu.rs
index efa942b..3ab1262 100644
--- a/src/widget/container/menu.rs
+++ b/src/widget/container/menu.rs
@@ -22,10 +22,7 @@ use crate::colors;
use crate::scene::layout::Rect;
use crate::scene::paint::PaintCtx;
use crate::widget::display::TextLabel;
-use crate::widget::{
- Adapted, ButtonStrip, WidgetHost, ElementState, Event, EventCtx, Input, Key, Layout,
- MenuController, MouseButton, NamedKey, PageSelector, Paint, DROPDOWN_ITEM_H,
-};
+use crate::widget::{Adapted, ButtonStrip, WidgetHost, ElementState, Event, EventCtx, Input, Key, Layout, MenuController, MouseButton, NamedKey, PageSelector, Paint, DROPDOWN_ITEM_H, WidgetHostExt};
pub struct MenuBar {
pub visible: bool,
diff --git a/src/widget/container/paginator.rs b/src/widget/container/paginator.rs
index 8a1fba3..ab27673 100644
--- a/src/widget/container/paginator.rs
+++ b/src/widget/container/paginator.rs
@@ -19,10 +19,7 @@ use crate::colors;
use crate::scene::layout::Rect;
use crate::scene::paint::PaintCtx;
use crate::widget::input::ButtonStrip;
-use crate::widget::{
- Adapted, WidgetHost, Event, EventCtx, Input, Layout, MenuController, PageSelector, Paint,
- UiContext, WidgetId,
-};
+use crate::widget::{Adapted, WidgetHost, Event, EventCtx, Input, Layout, MenuController, PageSelector, Paint, UiContext, WidgetId, WidgetHostExt};
pub struct Paginator {
/// In an [`Owned`](crate::widget::Owned) box of its own, so the registry points at a
@@ -321,7 +318,7 @@ mod tests {
// Legacy split: `extra_quads` is the children's chrome only; the sidebar background
// (a rounded rect) lives in `all_rounded_quads` alone (layout-interface draws its
// own backgrounds under `extra_quads`).
- let extra = WidgetHost::extra_quads(&p);
+ let extra = crate::widget::WidgetHostExt::extra_quads(&p);
let strip_extra = p.sidebar_menu.extra_quads();
assert_eq!(extra.len(), strip_extra.len(), "children-only plain view (pages emit none)");
let bg = colors::sidebar_bg_color();
@@ -329,7 +326,7 @@ mod tests {
let r = crate::layout::plate_corner_radius();
let bg_quad = (0.0, 0.0, 400.0, 300.0, r, bg, (true, true, true, true));
assert!(!extra.iter().any(|q| q.4 == bg && q.2 == 400.0), "no own bg in extra_quads");
- assert!(WidgetHost::all_rounded_quads(&p, &ctx).contains(&bg_quad), "own bg in all_rounded_quads");
+ assert!(crate::widget::WidgetHostExt::all_rounded_quads(&p, &ctx).contains(&bg_quad), "own bg in all_rounded_quads");
}
// The embedded strip + pages land in the registry on tick (the spatial grid feeds off
diff --git a/src/widget/container/parameters_bg.rs b/src/widget/container/parameters_bg.rs
index 670f38a..b1b51d8 100644
--- a/src/widget/container/parameters_bg.rs
+++ b/src/widget/container/parameters_bg.rs
@@ -38,10 +38,8 @@ use crate::scene::paint::PaintCtx;
use crate::widget::display::{Float3, TextLabel};
use crate::scene::paint::Field;
use crate::widget::input::{Button, ColorSelector, Dropdown, Ramp, Slider, Spinbox, TextBox, Toggle};
-use crate::widget::{
- Adapted, WidgetHost, ElementState, Event, EventCtx, Input, Key, Layout, MouseButton,
- MouseScrollDelta, NamedKey, Paint, ParamController, TextEditorState, UiContext,
-};
+use crate::widget::{Adapted, WidgetHost, ElementState, Event, EventCtx, Input, Key, Layout, MouseButton,
+ MouseScrollDelta, NamedKey, Paint, ParamController, TextEditorState, UiContext, WidgetHostExt};
/// A text row, in either variant: plain (`"text"`), or with a completion
/// picker (`"textpick:a,b,c"` — the Houdini-style attribute/group chooser: a
@@ -4728,7 +4726,7 @@ mod tests {
let p = panel_with(&[("Size", "1.00", "slider:0:2")]);
// The designer's plain path: extra_quads carries the row chrome (clipped), including
// the slider background it reads via rect()+color()...
- let extra = WidgetHost::extra_quads(&p);
+ let extra = crate::widget::WidgetHostExt::extra_quads(&p);
assert!(!extra.is_empty(), "row chrome served through extra_quads");
// ...but NOT the panel's own PARAM_BG plate (the host draws that from color()).
let (x, y, w, h) = WidgetHost::rect(&p);
@@ -4737,7 +4735,7 @@ mod tests {
"panel bg plate is the host's, not extra_quads'"
);
// The no-double-draw contract of the plain-quad hatch.
- assert!(WidgetHost::all_quads(&p, &ctx).is_empty());
+ assert!(crate::widget::WidgetHostExt::all_quads(&p, &ctx).is_empty());
// Per-label hatch: the walk's text prims carry the widget font and viewport bounds.
let mut scratch = crate::scene::paint::PaintCtx::new();
crate::scene::painter::append_widget_text(&ctx, &p, &mut scratch);
diff --git a/src/widget/display/graph.rs b/src/widget/display/graph.rs
index 1810af6..55560a3 100644
--- a/src/widget/display/graph.rs
+++ b/src/widget/display/graph.rs
@@ -2271,8 +2271,8 @@ mod tests {
// The plain view (designer path) and the rounded view (render_widget path) describe
// the same quads: the rounded view adds only the widget background entry up front.
- let plain = WidgetHost::extra_quads(&g);
- let rounded = WidgetHost::all_rounded_quads(&g, &ctx);
+ let plain = crate::widget::WidgetHostExt::extra_quads(&g);
+ let rounded = crate::widget::WidgetHostExt::all_rounded_quads(&g, &ctx);
assert!(!plain.is_empty());
assert_eq!(rounded.len(), plain.len() + 1);
for ((px, py, pw, ph, pc), (rx, ry, rw, rh, _, rc, _)) in plain.iter().zip(rounded.iter().skip(1)) {
@@ -2293,6 +2293,6 @@ mod tests {
// And `all_quads` stays empty so render_widget hosts (reading BOTH getters) never
// draw the geometry twice — the legacy Graph override's contract.
- assert!(WidgetHost::all_quads(&g, &ctx).is_empty());
+ assert!(crate::widget::WidgetHostExt::all_quads(&g, &ctx).is_empty());
}
}
diff --git a/src/widget/display/progress_bar.rs b/src/widget/display/progress_bar.rs
index 06a01ba..9c8ba89 100644
--- a/src/widget/display/progress_bar.rs
+++ b/src/widget/display/progress_bar.rs
@@ -106,7 +106,7 @@ mod tests {
let mut bar = ProgressBar::new(0.5).with_recessed(false);
WidgetHost::set_rect(&mut bar, 10.0, 20.0, 100.0, 8.0);
- let quads = WidgetHost::all_rounded_quads(&bar, &ctx);
+ let quads = crate::widget::WidgetHostExt::all_rounded_quads(&bar, &ctx);
let radius = crate::layout::slider_corner_radius();
assert_eq!(quads.len(), 2, "track + fill");
assert_eq!(quads[0], (10.0, 20.0, 100.0, 8.0, radius, colors::progress_bg(), (true, true, true, true)));
@@ -122,12 +122,12 @@ mod tests {
let ctx = UiContext::new();
let mut over = ProgressBar::new(2.0).with_recessed(false);
WidgetHost::set_rect(&mut over, 0.0, 0.0, 100.0, 8.0);
- let quads = WidgetHost::all_rounded_quads(&over, &ctx);
+ let quads = crate::widget::WidgetHostExt::all_rounded_quads(&over, &ctx);
assert_eq!(quads[1].2, 100.0, "over-1 value fills the whole track");
let mut empty = ProgressBar::new(0.0).with_recessed(false);
WidgetHost::set_rect(&mut empty, 0.0, 0.0, 100.0, 8.0);
- assert_eq!(WidgetHost::all_rounded_quads(&empty, &ctx).len(), 1, "zero value emits track only");
+ assert_eq!(crate::widget::WidgetHostExt::all_rounded_quads(&empty, &ctx).len(), 1, "zero value emits track only");
}
/// The recessed style draws no track of its own: the fill on the well floor, then
@@ -162,7 +162,7 @@ mod tests {
assert_eq!(h, 8.0 + offset, "the rect is the block it was given");
assert_eq!(y, 10.0, "origin is unchanged");
- let quads = WidgetHost::all_rounded_quads(&bar, &ctx);
+ let quads = crate::widget::WidgetHostExt::all_rounded_quads(&bar, &ctx);
assert_eq!(quads[0].1, 10.0 + offset, "track is painted below the label region");
assert_eq!(quads[0].3, 8.0, "track keeps the assigned height");
diff --git a/src/widget/display/separator.rs b/src/widget/display/separator.rs
index 62d3f59..520ca7f 100644
--- a/src/widget/display/separator.rs
+++ b/src/widget/display/separator.rs
@@ -89,7 +89,7 @@ mod tests {
assert!(!crate::widget::WidgetHostExt::blocks_root_plate_drag(&sep));
if !crate::layout::control_relief() {
assert_eq!(crate::widget::WidgetHostExt::color(&sep), [0.3, 0.3, 0.3, 1.0]);
- assert_eq!(WidgetHost::extra_quads(&sep), vec![(100.0, 0.0, 1.0, 24.0, [0.3, 0.3, 0.3, 1.0])]);
+ assert_eq!(crate::widget::WidgetHostExt::extra_quads(&sep), vec![(100.0, 0.0, 1.0, 24.0, [0.3, 0.3, 0.3, 1.0])]);
}
}
diff --git a/src/widget/display/status_bar.rs b/src/widget/display/status_bar.rs
index b97a3a0..947199f 100644
--- a/src/widget/display/status_bar.rs
+++ b/src/widget/display/status_bar.rs
@@ -232,9 +232,9 @@ mod tests {
assert_eq!(bar.text, "world");
// Parentless: cornerless plain bg through the plain-quad bridge, at STATUS_BG.
- let extra = WidgetHost::extra_quads(&bar);
+ let extra = crate::widget::WidgetHostExt::extra_quads(&bar);
assert_eq!(extra.len(), 1, "cornerless bg quad");
- assert_eq!(WidgetHost::corner_style(&bar).1, (false, false, false, false));
+ assert_eq!(crate::widget::WidgetHostExt::corner_style(&bar).1, (false, false, false, false));
assert!(!crate::widget::WidgetHostExt::blocks_root_plate_drag(&bar));
}
diff --git a/src/widget/display/status_dot.rs b/src/widget/display/status_dot.rs
index 8c0370e..dfa5526 100644
--- a/src/widget/display/status_dot.rs
+++ b/src/widget/display/status_dot.rs
@@ -79,11 +79,11 @@ mod tests {
let mut dot = StatusDot::new(DotStatus::Warning);
WidgetHost::set_rect(&mut dot, 5.0, 6.0, 10.0, 10.0);
assert_eq!(
- WidgetHost::all_rounded_quads(&dot, &UiContext::new()),
+ crate::widget::WidgetHostExt::all_rounded_quads(&dot, &UiContext::new()),
vec![(5.0, 6.0, 10.0, 10.0, 5.0, [0.90, 0.60, 0.10, 1.0], (true, true, true, true))],
"a disc: the rect at half-side radius",
);
- assert!(WidgetHost::extra_quads(&dot).is_empty(), "nothing on the plain path (apps read both)");
+ assert!(crate::widget::WidgetHostExt::extra_quads(&dot).is_empty(), "nothing on the plain path (apps read both)");
// Drags pass through, as legacy declared.
assert!(!crate::widget::WidgetHostExt::blocks_root_plate_drag(&dot));
// State mutation through Deref, as call sites write it.
diff --git a/src/widget/display/usage_bar.rs b/src/widget/display/usage_bar.rs
index 46ab580..4becbcb 100644
--- a/src/widget/display/usage_bar.rs
+++ b/src/widget/display/usage_bar.rs
@@ -110,13 +110,13 @@ mod tests {
let radius = crate::layout::slider_corner_radius();
let all = (true, true, true, true);
assert_eq!(
- WidgetHost::all_rounded_quads(&bar, &crate::widget::UiContext::new()),
+ crate::widget::WidgetHostExt::all_rounded_quads(&bar, &crate::widget::UiContext::new()),
vec![
(12.0, 30.0, 200.0, 8.0, radius, [0.4, 0.5, 0.6, 1.0], all),
(12.0, 30.0, 100.0, 8.0, radius.min(4.0), [0.1, 0.2, 0.3, 1.0], all),
],
);
- assert!(WidgetHost::extra_quads(&bar).is_empty(), "no plain quad leaks to flat hosts");
+ assert!(crate::widget::WidgetHostExt::extra_quads(&bar).is_empty(), "no plain quad leaks to flat hosts");
}
/// Recessed: no bg quad at all — the fill on the floor, then the carve.
@@ -130,7 +130,7 @@ mod tests {
assert_eq!(prims.len(), 2, "{prims:?}");
assert!(matches!(prims[0], Prim::RoundedRect { .. }));
assert!(matches!(prims[1], Prim::Recess { .. }));
- assert!(WidgetHost::extra_quads(&bar).is_empty(), "no plain bg quad leaks to flat hosts");
+ assert!(crate::widget::WidgetHostExt::extra_quads(&bar).is_empty(), "no plain bg quad leaks to flat hosts");
}
#[test]
diff --git a/src/widget/input/button.rs b/src/widget/input/button.rs
index 50b17bc..8413391 100644
--- a/src/widget/input/button.rs
+++ b/src/widget/input/button.rs
@@ -846,8 +846,8 @@ mod tests {
let b = Button::new(0.0, 0.0, 100.0, 24.0).with_label("Go").with_raised(false);
let radius = crate::layout::button_corner_radius();
- let rounded = WidgetHost::all_rounded_quads(&b, &ctx);
- let plain = WidgetHost::extra_quads(&b);
+ let rounded = crate::widget::WidgetHostExt::all_rounded_quads(&b, &ctx);
+ let plain = crate::widget::WidgetHostExt::extra_quads(&b);
if radius > 0.0 {
assert!(!rounded.is_empty() && plain.is_empty(), "rounded config -> rounded path only");
assert_eq!(rounded[0].4, radius);
diff --git a/src/widget/input/checkbox.rs b/src/widget/input/checkbox.rs
index f980aea..d6362f8 100644
--- a/src/widget/input/checkbox.rs
+++ b/src/widget/input/checkbox.rs
@@ -707,7 +707,7 @@ mod tests {
let (fcx, fcy) = (f.rect.x + f.rect.width * 0.5, f.rect.y + f.rect.height * 0.5);
assert!((pcx - fcx).abs() < 1e-3 && (pcy - fcy).abs() < 1e-3, "centred");
assert!(!p.has_well(), "the plate is all run");
- assert!(WidgetHost::extra_circles(&cb).is_empty(), "no mark");
+ assert!(crate::widget::WidgetHostExt::extra_circles(&cb).is_empty(), "no mark");
if crate::layout::control_relief() {
cb.inner_mut().set_checked(false);
diff --git a/src/widget/input/color_selector.rs b/src/widget/input/color_selector.rs
index 12a55b6..061d750 100644
--- a/src/widget/input/color_selector.rs
+++ b/src/widget/input/color_selector.rs
@@ -1094,7 +1094,7 @@ mod tests {
!items.iter().any(|it| matches!(it.prim, Prim::Quad { color, .. } if color == [1.0; 4])),
"no cell is a plain quad, so the legacy plain view cannot carry it"
);
- let plain = crate::widget::WidgetHost::extra_quads(&cs);
+ let plain = crate::widget::WidgetHostExt::extra_quads(&cs);
assert!(plain.iter().all(|q| q.4 != [1.0, 1.0, 1.0, 1.0]), "the plain view has no white cells: {plain:?}");
}
diff --git a/src/widget/input/slider.rs b/src/widget/input/slider.rs
index e552c1d..ba11444 100644
--- a/src/widget/input/slider.rs
+++ b/src/widget/input/slider.rs
@@ -1124,8 +1124,8 @@ fn probe_slider_bridge() {
let mut sl = Slider::new().with_label("Slider");
WidgetHost::set_rect(&mut sl, 20.0, 220.0, 200.0, 40.0);
eprintln!("rect = {:?}", WidgetHost::rect(&sl));
- eprintln!("extra_quads = {:?}", WidgetHost::extra_quads(&sl));
- eprintln!("rounded = {:?}", WidgetHost::all_rounded_quads(&sl, &ctx));
+ eprintln!("extra_quads = {:?}", crate::widget::WidgetHostExt::extra_quads(&sl));
+ eprintln!("rounded = {:?}", crate::widget::WidgetHostExt::all_rounded_quads(&sl, &ctx));
eprintln!("labels = {:?}", sl.own_text_labels().iter().map(|l| l.text.clone()).collect::<Vec<_>>());
}
diff --git a/src/widget/input/text_box.rs b/src/widget/input/text_box.rs
index a099575..91dca63 100644
--- a/src/widget/input/text_box.rs
+++ b/src/widget/input/text_box.rs
@@ -2817,7 +2817,7 @@ mod tests {
tb.select_anchor = Some(7); // starts at "Line 2"
tb.cursor_idx = 13; // ends at end of "Line 2"
- let has_rounded = WidgetHost::corner_style(&tb).1 != (false, false, false, false);
+ let has_rounded = crate::widget::WidgetHostExt::corner_style(&tb).1 != (false, false, false, false);
let has_highlight = if has_rounded {
let rounded = tb.all_rounded_quads(&dummy);
println!("Rounded quads: {:?}", rounded);
diff --git a/src/widget/mod.rs b/src/widget/mod.rs
index 02098a9..4da0d65 100644
--- a/src/widget/mod.rs
+++ b/src/widget/mod.rs
@@ -379,21 +379,6 @@ pub trait WidgetHost {
// `Widget::hovered` flag, read/written directly by the defaults above; Button/Checkbox
// keep inherent accessors for immediate-mode hosts.
- fn highlight_quad(&self, ctx: &UiContext) -> Option<(f32, f32, f32, f32, [f32; 4])> {
- // Focus/hover highlight color, folded from the zero-override `highlight_color` (6bd).
- let is_focused = ctx.is_focused_id(self.base().id());
- let hc = if is_focused {
- colors::highlight_primary_color()
- } else if self.base().hovered {
- colors::HIGHLIGHT_SECONDARY
- } else {
- return None;
- };
- let b = self.base();
- let hx = if b.row_w > 0.0 { b.row_x } else { b.x };
- let hw = if b.row_w > 0.0 { b.row_w } else { b.w };
- Some((hx, b.y, hw, b.h, hc))
- }
// `draggable`/`is_dragging` are GONE from the trait (the ControlPanel endgame
@@ -401,19 +386,7 @@ pub trait WidgetHost {
// inherent `Adapted<W>` reads; index-driven rosters (TI, designer) route them
// through per-slot matches like the other value drains.
- fn extra_quads(&self) -> Vec<(f32, f32, f32, f32, [f32; 4])> { Vec::new() }
- fn extra_arcs(&self) -> Vec<(f32, f32, f32, f32, f32, f32, [f32; 4])> { Vec::new() }
- fn extra_circles(&self) -> Vec<(f32, f32, f32, [f32; 4])> { Vec::new() }
- fn all_quads(&self, ctx: &UiContext) -> Vec<(f32, f32, f32, f32, [f32; 4])> {
- let mut quads = self.extra_quads();
- if let Some(hq) = self.highlight_quad(ctx) {
- if hq.4 != colors::HIGHLIGHT_SECONDARY {
- quads.push(hq);
- }
- }
- quads
- }
/// Emit this widget's OWN primitives (non-recursive) into the single paint pass (Phase 3).
/// The default composes the pieces the legacy recursive `all_*` emit for one node: rounded
@@ -427,10 +400,13 @@ pub trait WidgetHost {
let color = self.color();
if ui.tree.children_ptrs(self.base().id()).is_empty() {
- // Leaf: emit its own rounded quads directly. For an ordinary widget this is just the
- // rounded background; for widgets that override `all_rounded_quads` with custom
- // geometry (e.g. Graph's nodes and edges) it captures that too. No recursion happens
- // because there are no children.
+ // Leaf: its rounded background, from its colour and corner style, then the rounded
+ // quads its model paints. (Every production host overrides `paint_self`; this
+ // default serves a host without a model of its own.)
+ let (radius, corners) = self.corner_style();
+ if corners != (false, false, false, false) && color[3].abs() > 0.001 {
+ ctx.rounded_rect(rect, radius, corners, color);
+ }
for (qx, qy, qw, qh, r, c, corners) in self.all_rounded_quads(ui) {
ctx.rounded_rect(Rect { x: qx, y: qy, width: qw, height: qh }, r, corners, c);
}
@@ -468,25 +444,6 @@ pub trait WidgetHost {
- fn all_rounded_quads(&self, ctx: &UiContext) -> Vec<(f32, f32, f32, f32, f32, [f32; 4], (bool, bool, bool, bool))> {
- if !self.visible() {
- return Vec::new();
- }
- let mut quads = Vec::new();
- let (radius, (r1, r2, r3, r4)) = self.corner_style();
- if r1 || r2 || r3 || r4 {
- let (x, y, w, h) = self.rect();
- let c = self.color();
- if c[3].abs() > 0.001 {
- quads.push((x, y, w, h, radius, c, (r1, r2, r3, r4)));
- }
- }
- for &child_ptr in &ctx.tree.children_ptrs(self.base().id()) {
- let widget = unsafe { &*child_ptr };
- quads.extend(widget.all_rounded_quads(ctx));
- }
- quads
- }
// The per-widget text getters (text_labels / text_labels_with_bounds /
@@ -529,13 +486,6 @@ pub trait WidgetHost {
// the tree link its per-tick `register_embedded_children` maintains.
- /// Uniform corner radius + per-corner on-flags, in one read (6bd batch 2 — replaced the
- /// separate `corner_radius`/`rounded_corners` getters). The radius is meaningful even with
- /// every corner off: Menu/StatusBar report their parent's radius to children this way, so
- /// the flags-off channel can't be folded into `corner_radii`.
- fn corner_style(&self) -> (f32, (bool, bool, bool, bool)) {
- (12.0, (false, false, false, false))
- }
@@ -689,6 +639,190 @@ pub trait WidgetHostExt: WidgetHost {
}
}
}
+
+ // ── The legacy tuple views ──────────────────────────────────────────────────
+ // What a widget paints, projected onto the pre-display-list surface: plain quads,
+ // rounded quads, arcs, circles, the shared highlight, the corner style. Hosts that
+ // still draw a widget through these rather than `paint_self` — the designer's render
+ // loop, the gallery, the display manager, the settings app's flat collector,
+ // cce-secrets, the flat-host bridge — read them here. They were `WidgetHost` methods
+ // until 2026-10-08, each implemented by `Adapted` from its widget's `Paint`; they are
+ // computed from the models now, the same way.
+
+ /// The rect the widget's model paints into: the host's rect below its detached label.
+ fn content_rect(&self) -> crate::scene::layout::Rect {
+ let b = self.base();
+ let top = if self.layout_model().inline_label() { 0.0 } else { b.label_offset() };
+ // Deliberately NOT clamped at zero: hosts under-size labeled sliders (label taller
+ // than the assigned rect), and the negative-height quads still rasterize.
+ crate::scene::layout::Rect { x: b.x, y: b.y + top, width: b.w, height: b.h - top }
+ }
+
+ /// Everything the widget's model paints into [`content_rect`](Self::content_rect), as prims.
+ fn painted_prims(&self) -> Vec<crate::scene::paint::Prim> {
+ let mut pc = crate::scene::paint::PaintCtx::new();
+ self.paint_model().paint(self.content_rect(), &mut pc);
+ pc.finish().items.into_iter().map(|item| item.prim).collect()
+ }
+
+ /// The container's children that pass its [`Layout::child_visible`] policy; empty for a
+ /// non-container.
+ fn visible_children(&self) -> Vec<*mut (dyn WidgetHost + 'static)> {
+ let model = self.layout_model();
+ if !model.has_container_children() {
+ return Vec::new();
+ }
+ model.container_children().into_iter().filter(|c| model.child_visible(*c)).collect()
+ }
+
+ /// The corner radius and which corners it rounds; 12 and none for a widget without a
+ /// corner style.
+ fn corner_style(&self) -> (f32, (bool, bool, bool, bool)) {
+ self.paint_model().corner_style(self.content_rect()).unwrap_or((12.0, (false, false, false, false)))
+ }
+
+ /// The legacy hover/focus highlight over the row span: only for a widget that opts into
+ /// it ([`Paint::legacy_focus_highlight`], the TextBox) or forwards one
+ /// ([`Paint::forwarded_highlight`], the Paginator's ButtonStrip). Primary tint when
+ /// focused, secondary when hovered.
+ fn highlight_quad(&self, ctx: &UiContext) -> Option<(f32, f32, f32, f32, [f32; 4])> {
+ if let Some(forwarded) = self.paint_model().forwarded_highlight(ctx) {
+ return forwarded;
+ }
+ if !self.paint_model().legacy_focus_highlight() {
+ return None;
+ }
+ let b = self.base();
+ let hc = if ctx.is_focused_id(b.id()) {
+ colors::highlight_primary_color()
+ } else if b.hovered {
+ colors::HIGHLIGHT_SECONDARY
+ } else {
+ return None;
+ };
+ let hx = if b.row_w > 0.0 { b.row_x } else { b.x };
+ let hw = if b.row_w > 0.0 { b.row_w } else { b.w };
+ Some((hx, b.y, hw, b.h, hc))
+ }
+
+ /// The widget's own plain-quad prims.
+ fn own_plain_quads(&self) -> Vec<(f32, f32, f32, f32, [f32; 4])> {
+ self.painted_prims()
+ .into_iter()
+ .filter_map(|prim| match prim {
+ crate::scene::paint::Prim::Quad { rect, color } => Some((rect.x, rect.y, rect.width, rect.height, color)),
+ _ => None,
+ })
+ .collect()
+ }
+
+ /// The plain-quad view: a widget's own plain quads, or the legacy view it serves
+ /// ([`Paint::legacy_plain_quads`]), or — for an aggregating container (the Paginator) —
+ /// its visible children's.
+ fn extra_quads(&self) -> Vec<(f32, f32, f32, f32, [f32; 4])> {
+ if !self.visible() {
+ return Vec::new();
+ }
+ if self.paint_model().serves_legacy_plain_quads() {
+ return self.paint_model().legacy_plain_quads(self.content_rect());
+ }
+ if self.paint_model().aggregates_child_extra_quads() {
+ let mut out = Vec::new();
+ for child in self.visible_children() {
+ out.extend(unsafe { &*child }.extra_quads());
+ }
+ return out;
+ }
+ self.own_plain_quads()
+ }
+
+ /// Every plain quad the widget and its visible children draw, the opted-in highlight
+ /// included (not the hover tint), a rounded child's background left to
+ /// [`all_rounded_quads`](Self::all_rounded_quads). Empty for a widget serving the
+ /// legacy plain-quad view, which reaches flat hosts through `all_rounded_quads` only.
+ fn all_quads(&self, ctx: &UiContext) -> Vec<(f32, f32, f32, f32, [f32; 4])> {
+ if self.paint_model().serves_legacy_plain_quads() {
+ return Vec::new();
+ }
+ let mut quads = if self.visible() { self.own_plain_quads() } else { Vec::new() };
+ if self.paint_model().legacy_focus_highlight() {
+ if let Some(hq) = self.highlight_quad(ctx) {
+ if hq.4 != colors::HIGHLIGHT_SECONDARY {
+ quads.push(hq);
+ }
+ }
+ }
+ if self.visible() {
+ for child in self.visible_children() {
+ let widget = unsafe { &*child };
+ let (wx, wy, ww, wh) = widget.rect();
+ let has_rounded = widget.corner_style().1 != (false, false, false, false);
+ for (qx, qy, qw, qh, qc) in widget.all_quads(ctx) {
+ if has_rounded
+ && (qx - wx).abs() < 0.1
+ && (qy - wy).abs() < 0.1
+ && (qw - ww).abs() < 0.1
+ && (qh - wh).abs() < 0.1
+ {
+ continue;
+ }
+ quads.push((qx, qy, qw, qh, qc));
+ }
+ }
+ }
+ quads
+ }
+
+ /// Every rounded quad the widget and its visible children draw.
+ fn all_rounded_quads(&self, ctx: &UiContext) -> Vec<(f32, f32, f32, f32, f32, [f32; 4], (bool, bool, bool, bool))> {
+ if !self.visible() {
+ return Vec::new();
+ }
+ let mut out: Vec<_> = self
+ .painted_prims()
+ .into_iter()
+ .filter_map(|prim| match prim {
+ crate::scene::paint::Prim::RoundedRect { rect, radius, corners, color } => {
+ Some((rect.x, rect.y, rect.width, rect.height, radius, color, corners))
+ }
+ _ => None,
+ })
+ .collect();
+ for child in self.visible_children() {
+ out.extend(unsafe { &*child }.all_rounded_quads(ctx));
+ }
+ out
+ }
+
+ /// The widget's arc prims.
+ fn extra_arcs(&self) -> Vec<(f32, f32, f32, f32, f32, f32, [f32; 4])> {
+ if !self.visible() {
+ return Vec::new();
+ }
+ self.painted_prims()
+ .into_iter()
+ .filter_map(|prim| match prim {
+ crate::scene::paint::Prim::Arc { cx, cy, radius, thickness, start, end, color } => {
+ Some((cx, cy, radius, thickness, start, end, color))
+ }
+ _ => None,
+ })
+ .collect()
+ }
+
+ /// The widget's circle prims.
+ fn extra_circles(&self) -> Vec<(f32, f32, f32, [f32; 4])> {
+ if !self.visible() {
+ return Vec::new();
+ }
+ self.painted_prims()
+ .into_iter()
+ .filter_map(|prim| match prim {
+ crate::scene::paint::Prim::Circle { cx, cy, radius, color } => Some((cx, cy, radius, color)),
+ _ => None,
+ })
+ .collect()
+ }
}
impl<T: WidgetHost + ?Sized> WidgetHostExt for T {}
diff --git a/src/widget/model.rs b/src/widget/model.rs
index 86a77c2..4993467 100644
--- a/src/widget/model.rs
+++ b/src/widget/model.rs
@@ -804,22 +804,6 @@ impl<W: Layout + Paint + Input + 'static> Adapted<W> {
Paint::sync_label(&mut self.inner, text);
}
- /// The rect the wrapped widget paints into: the widget's rect minus the detached-label
- /// strip at the top (zero when there is no label, or when the widget's label is its
- /// content — [`Layout::inline_label`]).
- fn content_rect(&self) -> Rect {
- let top = if Layout::inline_label(&self.inner) { 0.0 } else { self.base.label_offset() };
- Rect {
- x: self.base.x,
- y: self.base.y + top,
- width: self.base.w,
- // Deliberately NOT clamped at zero: legacy geometry computed `h - label_offset`
- // raw, and hosts under-size labeled sliders (label taller than the assigned rect);
- // the resulting negative-height quads still rasterize (flipped), which is what
- // keeps those tracks visible. Clamping made them vanish — found the hard way.
- height: self.base.h - top,
- }
- }
}
impl<W: Layout + Paint + Input + 'static> Adapted<W> {
@@ -982,41 +966,8 @@ impl<W: Layout + Paint + Input + 'static> Adapted<W> {
Layout::intrinsic_size(&self.inner)
}
- /// Run the wrapped widget's [`Paint::paint`] against its content rect and return the emitted
- /// prims — the shared source for the reverse bridges (`extra_quads`, `all_rounded_quads`,
- /// `extra_circles`, `extra_arcs`, prim-derived `text_labels`) that legacy render loops read.
- fn painted_prims(&self) -> Vec<Prim> {
- let mut pc = PaintCtx::new();
- Paint::paint(&self.inner, self.content_rect(), &mut pc);
- pc.finish().items.into_iter().map(|item| item.prim).collect()
- }
- /// This widget's OWN plain-quad prims from [`Paint::paint`] — the shared source for the
- /// `extra_quads`/`all_quads` reverse bridges (kept separate from `extra_quads` itself,
- /// which may serve the child aggregation instead —
- /// [`Paint::aggregates_child_extra_quads`]).
- fn own_plain_quads(&self) -> Vec<(f32, f32, f32, f32, [f32; 4])> {
- self.painted_prims()
- .into_iter()
- .filter_map(|prim| match prim {
- Prim::Quad { rect, color } => Some((rect.x, rect.y, rect.width, rect.height, color)),
- _ => None,
- })
- .collect()
- }
- /// The container's children that pass the [`Layout::child_visible`] policy — the set the
- /// adapter's subtree plumbing (aggregation, recursion, hit-through) operates on. Empty for
- /// non-containers.
- fn visible_children(&self) -> Vec<*mut (dyn WidgetHost + 'static)> {
- if !Layout::has_container_children(&self.inner) {
- return Vec::new();
- }
- Layout::container_children(&self.inner)
- .into_iter()
- .filter(|c| Layout::child_visible(&self.inner, *c))
- .collect()
- }
/// This widget's OWN text (prim-derived + detached base label), before any child
/// aggregation — the shared source for the three text getters.
@@ -1290,34 +1241,6 @@ impl<W: Layout + Paint + Input + 'static> WidgetHost for Adapted<W> {
}
}
- /// Narrow widgets own every pixel they draw through [`Paint::paint`]; the legacy shared
- /// hover-highlight overlay is suppressed (matching what most control widgets' `None`
- /// overrides do today) — unless the widget opts back in
- /// ([`Paint::legacy_focus_highlight`], TextBox), in which case this replicates the
- /// `WidgetHost` default byte-for-byte: primary tint when ctx-focused (or active), secondary
- /// when hovered, over the row-substituted span.
- fn highlight_quad(&self, ctx: &UiContext) -> Option<(f32, f32, f32, f32, [f32; 4])> {
- // A forwarding widget (Paginator → its ButtonStrip) serves the forwarded value here —
- // and only here; `all_quads`/`paint_self` gate on `legacy_focus_highlight` instead, so
- // the forwarded quad is never double-drawn.
- if let Some(forwarded) = Paint::forwarded_highlight(&self.inner, ctx) {
- return forwarded;
- }
- if !Paint::legacy_focus_highlight(&self.inner) {
- return None;
- }
- let is_focused = ctx.is_focused_id(self.base.id());
- let hc = if is_focused {
- crate::colors::highlight_primary_color()
- } else if self.base.hovered {
- crate::colors::HIGHLIGHT_SECONDARY
- } else {
- return None;
- };
- let hx = if self.base.row_w > 0.0 { self.base.row_x } else { self.base.x };
- let hw = if self.base.row_w > 0.0 { self.base.row_w } else { self.base.w };
- Some((hx, self.base.y, hw, self.base.h, hc))
- }
/// Report the *inner* type's name, not `Adapted<W>`: runtime type-name matching (e.g.
/// `layout.rs`' span-full widget list) must keep seeing the widget it knows.
@@ -1326,11 +1249,6 @@ impl<W: Layout + Paint + Input + 'static> WidgetHost for Adapted<W> {
}
// --- Paint concern -> `Paint` ---
- fn corner_style(&self) -> (f32, (bool, bool, bool, bool)) {
- // 12.0 / all-off mirrors the `WidgetHost` default for widgets without a corner style.
- Paint::corner_style(&self.inner, self.content_rect())
- .unwrap_or((12.0, (false, false, false, false)))
- }
@@ -1383,7 +1301,7 @@ impl<W: Layout + Paint + Input + 'static> WidgetHost for Adapted<W> {
// highlight — replicate for opt-in widgets, over the background (same draw order).
// Forwarded highlights stay out: the paint walk reaches the owning child itself.
if Paint::legacy_focus_highlight(&self.inner) {
- if let Some((hx, hy, hw, hh, hc)) = WidgetHost::highlight_quad(self, ui) {
+ if let Some((hx, hy, hw, hh, hc)) = crate::widget::WidgetHostExt::highlight_quad(self, ui) {
if hc != crate::colors::HIGHLIGHT_SECONDARY {
ctx.quad(Rect { x: hx, y: hy, width: hw, height: hh }, hc);
}
@@ -1436,120 +1354,10 @@ impl<W: Layout + Paint + Input + 'static> WidgetHost for Adapted<W> {
// the widget's OWN geometry only: adapted widgets are leaves for now; recursion belongs to
// `scene::painter`.
- fn all_rounded_quads(&self, ctx: &UiContext) -> Vec<(f32, f32, f32, f32, f32, [f32; 4], (bool, bool, bool, bool))> {
- if !self.visible() {
- return Vec::new();
- }
- let mut out: Vec<_> = self
- .painted_prims()
- .into_iter()
- .filter_map(|prim| match prim {
- Prim::RoundedRect { rect, radius, corners, color } => {
- Some((rect.x, rect.y, rect.width, rect.height, radius, color, corners))
- }
- _ => None,
- })
- .collect();
- // Containers recurse, matching the `WidgetHost` default this override replaces.
- for child in self.visible_children() {
- out.extend(unsafe { &*child }.all_rounded_quads(ctx));
- }
- out
- }
- fn extra_quads(&self) -> Vec<(f32, f32, f32, f32, [f32; 4])> {
- if !self.visible() {
- return Vec::new();
- }
- if Paint::serves_legacy_plain_quads(&self.inner) {
- return Paint::legacy_plain_quads(&self.inner, self.content_rect());
- }
- // Legacy container aggregation (Paginator): the plain view is the visible children's
- // chrome, and only that — the widget's own background stays in `all_quads`.
- if Paint::aggregates_child_extra_quads(&self.inner) {
- let mut out = Vec::new();
- for child in self.visible_children() {
- out.extend(unsafe { &*child }.extra_quads());
- }
- return out;
- }
- self.own_plain_quads()
- }
- /// When the widget serves a legacy plain-quad view, its geometry reaches
- /// `render_widget`-style hosts (which read BOTH quad getters) through `all_rounded_quads`
- /// only — `all_quads` must stay empty or they draw it twice. Mirrors legacy Graph's
- /// highlight-only `all_quads` override. Otherwise: the `WidgetHost` default minus the shared
- /// highlight (suppressed for all adapted widgets via `highlight_quad -> None`).
- fn all_quads(&self, ctx: &UiContext) -> Vec<(f32, f32, f32, f32, [f32; 4])> {
- if Paint::serves_legacy_plain_quads(&self.inner) {
- return Vec::new();
- }
- // Own prims directly (NOT `extra_quads`, which may serve the child aggregation — those
- // children arrive once, through the recursion below).
- let mut quads = if self.visible() { self.own_plain_quads() } else { Vec::new() };
- // The `WidgetHost` default's highlight inclusion (secondary/hover tint excluded), live
- // only for widgets that opt into the legacy overlay. A forwarded highlight
- // ([`Paint::forwarded_highlight`]) is deliberately excluded: its owner's aggregation
- // already carries it, matching the legacy container `all_quads` overrides.
- if Paint::legacy_focus_highlight(&self.inner) {
- if let Some(hq) = WidgetHost::highlight_quad(self, ctx) {
- if hq.4 != crate::colors::HIGHLIGHT_SECONDARY {
- quads.push(hq);
- }
- }
- }
- if self.visible() {
- // Container aggregation, replicating the shared legacy loop (Layer, Switcher):
- // children contribute their plain quads, except a rounded-cornered child's
- // background quad — that one arrives through `all_rounded_quads` instead.
- for child in self.visible_children() {
- let widget = unsafe { &*child };
- let (wx, wy, ww, wh) = widget.rect();
- let has_rounded = widget.corner_style().1 != (false, false, false, false);
- for (qx, qy, qw, qh, qc) in widget.all_quads(ctx) {
- if has_rounded
- && (qx - wx).abs() < 0.1
- && (qy - wy).abs() < 0.1
- && (qw - ww).abs() < 0.1
- && (qh - wh).abs() < 0.1
- {
- continue;
- }
- quads.push((qx, qy, qw, qh, qc));
- }
- }
- }
- quads
- }
- fn extra_circles(&self) -> Vec<(f32, f32, f32, [f32; 4])> {
- if !self.visible() {
- return Vec::new();
- }
- self.painted_prims()
- .into_iter()
- .filter_map(|prim| match prim {
- Prim::Circle { cx, cy, radius, color } => Some((cx, cy, radius, color)),
- _ => None,
- })
- .collect()
- }
- fn extra_arcs(&self) -> Vec<(f32, f32, f32, f32, f32, f32, [f32; 4])> {
- if !self.visible() {
- return Vec::new();
- }
- self.painted_prims()
- .into_iter()
- .filter_map(|prim| match prim {
- Prim::Arc { cx, cy, radius, thickness, start, end, color } => {
- Some((cx, cy, radius, thickness, start, end, color))
- }
- _ => None,
- })
- .collect()
- }
// --- Input concern -> `Input` ---
/// Row-rect assignment (row-layout hosts): apply the widget's clamp
diff --git a/src/widget/owned.rs b/src/widget/owned.rs
index 630a09f..7ad0db2 100644
--- a/src/widget/owned.rs
+++ b/src/widget/owned.rs
@@ -160,15 +160,7 @@ impl<W: WidgetHost + 'static> WidgetHost for Owned<W> {
fn set_rect(&mut self, x: f32, y: f32, w: f32, h: f32) { (**self).set_rect(x, y, w, h) }
fn set_row_rect(&mut self, x: f32, w: f32) { (**self).set_row_rect(x, w) }
fn hit_test(&self, px: f32, py: f32, ctx: &UiContext) -> bool { (**self).hit_test(px, py, ctx) }
- fn highlight_quad(&self, ctx: &UiContext) -> Option<(f32, f32, f32, f32, [f32; 4])> { (**self).highlight_quad(ctx) }
- fn extra_quads(&self) -> Vec<(f32, f32, f32, f32, [f32; 4])> { (**self).extra_quads() }
- fn extra_arcs(&self) -> Vec<(f32, f32, f32, f32, f32, f32, [f32; 4])> { (**self).extra_arcs() }
- fn extra_circles(&self) -> Vec<(f32, f32, f32, [f32; 4])> { (**self).extra_circles() }
- fn all_quads(&self, ctx: &UiContext) -> Vec<(f32, f32, f32, f32, [f32; 4])> { (**self).all_quads(ctx) }
fn paint_self(&self, ui: &UiContext, ctx: &mut crate::scene::paint::PaintCtx) { (**self).paint_self(ui, ctx) }
- fn all_rounded_quads(&self, ctx: &UiContext) -> Vec<(f32, f32, f32, f32, f32, [f32; 4], (bool, bool, bool, bool))> {
- (**self).all_rounded_quads(ctx)
- }
fn type_name(&self) -> &'static str { (**self).type_name() }
fn popover_rect(&self) -> Option<(f32, f32, f32, f32)> { (**self).popover_rect() }
fn render_popover(&self, pc: &mut dyn crate::layout::RenderTarget) { (**self).render_popover(pc) }
@@ -180,7 +172,6 @@ impl<W: WidgetHost + 'static> WidgetHost for Owned<W> {
fn visible(&self) -> bool { (**self).visible() }
fn tick(&mut self, dt: f32, ctx: &mut UiContext) -> bool { (**self).tick(dt, ctx) }
fn is_child_visible(&self, child_id: WidgetId) -> bool { (**self).is_child_visible(child_id) }
- fn corner_style(&self) -> (f32, (bool, bool, bool, bool)) { (**self).corner_style() }
fn a11y_items(&self) -> Vec<crate::a11y::A11yItem> { (**self).a11y_items() }
}