system settings
git clone https://git.lucas.co/cce-system-interface.git
settings: re-emit Button and Toggle carves with the rest
Follows the toolkit's bridge from one hook per widget to one carve type:
`control_reliefs` is now a `Vec<ControlCarve>` — `Plate` (the inset face a
Dropdown or a Button draws) or `Step` (a `cce_ui::layout::ReliefCarve`,
which carries its own rect, per-corner radii, depth and wall mask, so nothing
here re-derives them). The scroll shift the popover collector applies moved
onto `ControlCarve::shifted_y`, one place instead of a tuple rebuild at each
site.
Buttons need one extra step: they never reach `render_widget` in this app,
because it collects them into `pc.buttons` and draws them itself, so the
toolkit's bridge cannot see them. The page carve list now asks each collected
button for `Button::inset_face` — the same source the drawn one reads — and
carves it in page coords with everything else.
Verified live headless on the Browser page: Record History draws its rocker
where there was previously nothing but a label, and Apply gained its groove
ring (measured trough profile at its top edge). Dropdowns, text fields and the
open dropdown popover are unchanged.
src/app.rs | 49 ++++++++++++++++++++++++++++++++-----------------
src/main.rs | 34 +++++++++++++++++++---------------
src/renderer.rs | 35 ++++++++++++++++++++++++++++++++---
3 files changed, 83 insertions(+), 35 deletions(-)
diff --git a/src/app.rs b/src/app.rs
index 9d89605..5624342 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -124,18 +124,33 @@ pub enum AppAction {
}
-/// A control carve bridged out of a widget's `paint` for the flat path: the
-/// two relief idioms the toolkit's controls draw for themselves, which the
-/// legacy `all_quads` stream cannot carry. The page collects them and
-/// `display_list` re-emits them as real prims into the window plate.
+/// A control carve bridged out of a widget's `paint` for the flat path — the
+/// relief prims the toolkit's controls draw for themselves and the legacy
+/// `all_quads` stream cannot carry. The page collects them and `display_list`
+/// re-emits them as real prims into the window plate.
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum ControlCarve {
/// `PaintCtx::inset_plate` — a flush inset face over a boundary seam
- /// (Dropdown). `color` fills the face; transparent leaves the plate below.
- Plate { color: [f32; 4] },
- /// `PaintCtx::recess` / `recess_tinted` — a sunken well (TextBox).
- /// `tint` is the focus accent on the rim while the box is being edited.
- Well { tint: Option<[f32; 3]> },
+ /// (Dropdown, Button). `color` fills the face; transparent leaves the
+ /// plate below.
+ Plate { x: f32, y: f32, w: f32, h: f32, radius: f32, depth: f32, color: [f32; 4] },
+ /// A step carve straight from the toolkit (TextBox well, Toggle rocker
+ /// halves and glider) — it already carries its own rect, per-corner radii,
+ /// depth and wall mask, so nothing here re-derives them.
+ Step(cce_ui::layout::ReliefCarve),
+}
+
+impl ControlCarve {
+ /// This carve shifted vertically — the page-scroll adjustment the popover
+ /// collector applies when it lifts page carves to the popover layer.
+ pub fn shifted_y(self, dy: f32) -> Self {
+ match self {
+ Self::Plate { x, y, w, h, radius, depth, color } => {
+ Self::Plate { x, y: y + dy, w, h, radius, depth, color }
+ }
+ Self::Step(c) => Self::Step(c.shifted_y(dy)),
+ }
+ }
}
pub struct PageContent {
@@ -154,7 +169,7 @@ pub struct PageContent {
/// `RenderTarget::recess` for a TextBox's well) — (x, y, w, h, radius,
/// depth, carve), page coordinates, pre-scroll; display_list re-emits them
/// as real relief prims.
- pub control_reliefs: Vec<(f32, f32, f32, f32, f32, f32, ControlCarve)>,
+ pub control_reliefs: Vec<ControlCarve>,
pub clip_stack: Vec<[f32; 4]>,
pub measure_only: bool,
}
@@ -325,18 +340,18 @@ impl RenderTarget for PageContent {
if self.measure_only {
return;
}
- self.control_reliefs.push((x, y, w, h, radius, depth, ControlCarve::Plate { color }));
+ self.control_reliefs.push(ControlCarve::Plate { x, y, w, h, radius, depth, color });
}
- /// The same bridge for a TextBox's well — a DIFFERENT carve, not the same
- /// one at another rect: a trough is a seam about the boundary with the face
- /// level, a well drops the whole interior. Collapsing them would give the
- /// settings app text fields no other relief host has.
- fn recess(&mut self, x: f32, y: f32, w: f32, h: f32, radius: f32, depth: f32, tint: Option<[f32; 3]>) {
+ /// The same bridge for the step carves — a DIFFERENT shape, not an inset
+ /// plate at another rect: a trough is a seam about the boundary with the
+ /// face left level, a well drops the whole interior, a boss raises it.
+ /// Collapsing them would give this app controls no other relief host has.
+ fn relief_carve(&mut self, carve: &cce_ui::layout::ReliefCarve) {
if self.measure_only {
return;
}
- self.control_reliefs.push((x, y, w, h, radius, depth, ControlCarve::Well { tint }));
+ self.control_reliefs.push(ControlCarve::Step(*carve));
}
fn section_relief(&mut self, f: &cce_ui::layout::SectionFrame) -> bool {
diff --git a/src/main.rs b/src/main.rs
index bec1283..af72d5a 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -46,7 +46,7 @@ struct SystemInterface {
popover_texts: Vec<(String, f32, f32, f32, [f32; 4], Option<String>, Option<[f32; 4]>)>,
/// Popover-layer inset plates (window coords, scroll already applied) —
/// the dropdown's grown-trigger surface via the inset_plate hook.
- popover_control_reliefs: Vec<(f32, f32, f32, f32, f32, f32, ControlCarve)>,
+ popover_control_reliefs: Vec<ControlCarve>,
page_buttons: Vec<(cce_ui::widget::Adapted<cce_ui::widget::Button>, AppAction)>,
sidebar_width: f32,
@@ -108,7 +108,7 @@ struct SystemInterface {
page_reliefs: Vec<((f32, f32, f32, f32), Option<(f32, f32, f32, f32)>)>,
/// Control troughs from `PageContent::control_reliefs` (page coords,
/// pre-scroll) — each carved as a flush inset plate after the section wells.
- page_control_reliefs: Vec<(f32, f32, f32, f32, f32, f32, ControlCarve)>,
+ page_control_reliefs: Vec<ControlCarve>,
// Root Backplate + StatusBar DISSOLVED (Phase 6s): the window plate and the status
// bar are emitted as tuples in rebuild_layout.
sans_serif_family: String,
@@ -417,13 +417,15 @@ impl cce_ui::engine::Application for SystemInterface {
};
let scroll_y = self.scroll_y;
pc.clip(view, |pc| {
- for &(x, y, w, h, radius, depth, carve) in &self.page_control_reliefs {
- let rect = Rect { x, y: y - scroll_y, width: w, height: h };
- let radii = (radius, radius, radius, radius);
- match carve {
- ControlCarve::Plate { color } => pc.inset_plate(rect, radii, color, depth),
- ControlCarve::Well { tint: Some(t) } => pc.recess_tinted(rect, radii, depth, t),
- ControlCarve::Well { tint: None } => pc.recess(rect, radii, depth),
+ for &carve in &self.page_control_reliefs {
+ match carve.shifted_y(-scroll_y) {
+ ControlCarve::Plate { x, y, w, h, radius, depth, color } => pc.inset_plate(
+ Rect { x, y, width: w, height: h },
+ (radius, radius, radius, radius),
+ color,
+ depth,
+ ),
+ ControlCarve::Step(c) => pc.carve(&c),
}
}
});
@@ -444,13 +446,15 @@ impl cce_ui::engine::Application for SystemInterface {
// Popover surfaces claimed through the inset_plate hook (the dropdown's
// grown-trigger plate): real relief prims at the popover layer, over
// the page and its control troughs.
- for &(x, y, w, h, radius, depth, carve) in &self.popover_control_reliefs {
- let rect = Rect { x, y, width: w, height: h };
- let radii = (radius, radius, radius, radius);
+ for &carve in &self.popover_control_reliefs {
match carve {
- ControlCarve::Plate { color } => pc.inset_plate(rect, radii, color, depth),
- ControlCarve::Well { tint: Some(t) } => pc.recess_tinted(rect, radii, depth, t),
- ControlCarve::Well { tint: None } => pc.recess(rect, radii, depth),
+ ControlCarve::Plate { x, y, w, h, radius, depth, color } => pc.inset_plate(
+ Rect { x, y, width: w, height: h },
+ (radius, radius, radius, radius),
+ color,
+ depth,
+ ),
+ ControlCarve::Step(c) => pc.carve(&c),
}
}
for (text, font_size, x, y, col, font, bounds) in self.texts.iter().chain(self.popover_texts.iter()) {
diff --git a/src/renderer.rs b/src/renderer.rs
index aa280aa..6456898 100644
--- a/src/renderer.rs
+++ b/src/renderer.rs
@@ -1,5 +1,5 @@
use crate::{SystemInterface, AppWidget, make_text_buffer_with_font};
-use cce_settings::app::PageContent;
+use cce_settings::app::{ControlCarve, PageContent};
use cce_settings::pages::Page;
use cce_ui::widget::WidgetHost;
@@ -264,6 +264,35 @@ impl SystemInterface {
let pc = self.render_page_content(lcx, lcy, lcw, lch);
self.page_reliefs = pc.reliefs.clone();
self.page_control_reliefs = pc.control_reliefs.clone();
+ // Buttons never reach the toolkit's flat-path bridge here: this app
+ // collects them into `pc.buttons` and draws them itself, so
+ // `render_widget` — where a Dropdown's and a TextBox's carves are
+ // offered — never sees one. Ask each button for the inset face its own
+ // `paint` draws (`Button::inset_face`, the same source the drawn one
+ // reads) and carve it with the rest. Page coords, pre-scroll, like
+ // everything else in this list.
+ if cce_ui::layout::control_relief() {
+ for (btn, _, _) in &pc.buttons {
+ let base = btn.base();
+ let rect = cce_ui::scene::layout::Rect {
+ x: base.x,
+ y: base.y,
+ width: base.w,
+ height: base.h,
+ };
+ if let Some((face, radius, depth, color)) = btn.inset_face(rect) {
+ self.page_control_reliefs.push(ControlCarve::Plate {
+ x: face.x,
+ y: face.y,
+ w: face.width,
+ h: face.height,
+ radius,
+ depth,
+ color,
+ });
+ }
+ }
+ }
@@ -602,8 +631,8 @@ impl SystemInterface {
let shifted = bounds.map(|[l, tb, rr, b]| [l, tb - self.scroll_y, rr, b - self.scroll_y]);
popover_pc.texts.push((t, size, x, y - self.scroll_y, tc, font, shifted));
}
- for (x, y, w, h, r, d, c) in page_pop_pc.control_reliefs {
- popover_pc.control_reliefs.push((x, y - self.scroll_y, w, h, r, d, c));
+ for carve in page_pop_pc.control_reliefs {
+ popover_pc.control_reliefs.push(carve.shifted_y(-self.scroll_y));
}
}
if cce_ui::widget::context_menu::is_visible() {