GPU-accelerated UI toolkit (Vulkan)
git clone https://git.lucas.co/cce-ui.git
feat: backplate_padding + backplate_gap config keys
Two DE-wide spacing keys under style.surface.backplate: padding (plate
rim to objects, default 16) and gap (between sibling objects on the
plate, default 12). Apps were hardcoding divergent values — cce-files
16/12 vs cce-data-editor 10/10 — visibly inconsistent side by side.
DemoApp consumes both as the reference.
Co-Authored-By: Claude Fable 5 <[email protected]>
src/layout.rs | 19 +++++++++++++++++++
src/main.rs | 9 ++++++---
2 files changed, 25 insertions(+), 3 deletions(-)
diff --git a/src/layout.rs b/src/layout.rs
index 9360647..65577ce 100644
--- a/src/layout.rs
+++ b/src/layout.rs
@@ -142,6 +142,8 @@ fn flatten_json_to_flat_props(val: &serde_json::Value, prefix: &str, flat_props:
"style.surface.desktop.solid_color" => "desktop_solid_color",
"style.surface.desktop.grid_cell_size" => "desktop_grid_scale",
"style.surface.plate.padding" => "plate_padding",
+ "style.surface.backplate.padding" => "backplate_padding",
+ "style.surface.backplate.gap" => "backplate_gap",
"style.surface.backplate.color" => "backplate_color",
"style.surface.backplate.blur" => "backplate_blur",
"style.surface.backplate.corner_radius" => "backplate_corner_radius",
@@ -158,6 +160,7 @@ fn flatten_json_to_flat_props(val: &serde_json::Value, prefix: &str, flat_props:
"style.surface.graph.cell_color" => "graph_cell_color",
"style.surface.graph.gap_color" => "graph_gap_color",
"style.surface.graph.opacity" => "graph_opacity",
+ "style.surface.graph.node.opacity" => "graph_node_opacity",
"style.surface.graph.spacing_x" => "graph_spacing_x",
"style.surface.graph.spacing_y" => "graph_spacing_y",
"style.surface.graph.gap_col_w" => "graph_gap_col_w",
@@ -1536,6 +1539,22 @@ pub fn bevel_width() -> f32 {
get_style_registry().read().unwrap().get_float("bevel_width").unwrap_or(9.3)
}
+/// Padding between the window plate's edge and the objects sitting on it, in
+/// logical px (`style.surface.backplate.padding` in config.kdl). DE-wide so
+/// every app's content sits the same distance off the plate rim.
+pub fn backplate_padding() -> f32 {
+ lazy_init_style_registry();
+ get_style_registry().read().unwrap().get_float("backplate_padding").unwrap_or(16.0)
+}
+
+/// Gap between sibling objects on the window plate, in logical px
+/// (`style.surface.backplate.gap` in config.kdl) — pane splits, control rows.
+/// The companion to [`backplate_padding`]: rim distance vs object spacing.
+pub fn backplate_gap() -> f32 {
+ lazy_init_style_registry();
+ get_style_registry().read().unwrap().get_float("backplate_gap").unwrap_or(12.0)
+}
+
/// Roll-off width for the wall where a bar (menubar / status bar / the demo's
/// header band) steps down into the window plate. Wider than the plate's own
/// perimeter roll on purpose: the carve depth saturates at `bevel_width` in the
diff --git a/src/main.rs b/src/main.rs
index a6e6260..d1e87da 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -260,9 +260,12 @@ impl Application for DemoApp {
// ── Layout: a plain LayoutBox tree, solved in one call. Leaves carry their
// intrinsic sizes; `grow` distributes leftover space; the solved rects are
// assigned straight onto the widgets.
+ // DE-wide plate spacing: rim padding and object gap from config.
+ let plate_pad = cce_ui::layout::backplate_padding();
+ let plate_gap = cce_ui::layout::backplate_gap();
let mut arena: Arena<LayoutBox> = Arena::new();
let root = arena.insert(LayoutBox::container(
- Style::column().padding(16.0).gap(14.0).cross_align(CrossAlign::Stretch),
+ Style::column().padding(plate_pad).gap(plate_gap).cross_align(CrossAlign::Stretch),
));
let title = arena.insert(LayoutBox::leaf(
Style::row(),
@@ -279,7 +282,7 @@ impl Application for DemoApp {
// toggle, and dropdown plates land on the same top and bottom edge.
const CONTROL_H: f32 = 28.0;
let controls = arena.insert(LayoutBox::container(
- Style::row().gap(14.0).height(Length::Fixed(CONTROL_H)),
+ Style::row().gap(plate_gap).height(Length::Fixed(CONTROL_H)),
));
// `shrink` lets the fixed leaves give up width when the window is at its
// minimum instead of overflowing the row.
@@ -290,7 +293,7 @@ impl Application for DemoApp {
let name_box = arena.insert(LayoutBox::leaf(Style::row(), LSize::new(0.0, 30.0)));
// ImageView row: same texture through two fit modes side by side.
let images = arena.insert(LayoutBox::container(
- Style::row().gap(14.0).height(Length::Fixed(72.0)),
+ Style::row().gap(plate_gap).height(Length::Fixed(72.0)),
));
let image_contain = arena.insert(LayoutBox::leaf(Style::row().grow(1.0), LSize::new(0.0, 72.0)));
let image_stretch = arena.insert(LayoutBox::leaf(Style::row().grow(1.0), LSize::new(0.0, 72.0)));