git.lucas.co / cce-gallery
widget gallery and compositor test bench

commit558b4ef7a081f33f3f048955c0224f4c9bbc40f6
parentfd53ab7065
authorLucas Galante <[email protected]>
date2026-09-09 12:37
fix: the exhibits start at the fitted lasso's seat, so its padding is even

The top row sat flush with the exhibit area's corner, so the fitted lasso
had no room: its left wall landed on the Button (0px) and its title tab on
the row's labels, while the far sides kept their 6px. Inset the layout by
the lasso's padding (twice, for the frame's seat and the members inside it)
on the sides and by padding + headroom on top; the scroll bounds include
the inset. Every side of the row now shows the same 6px.

Co-Authored-By: Claude Fable 5.1 <[email protected]>

 README.md   |  4 +++-
 src/main.rs | 17 +++++++++++++++--
 2 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/README.md b/README.md
index fe35cd3..50da0f5 100644
--- a/README.md
+++ b/README.md
@@ -43,7 +43,9 @@ not follow the switch is a toolkit bug — every control's `with_raised` /
 
 Two `Group` lassos lie over the named exhibits — `Group`, loose around the
 FontSelector and the StatusDot, and `Group (fitted)` around the top row,
-fitted to the exhibit area's edges. A lasso is laid out by its members, not
+fitted to the exhibit area's edges. The exhibits are laid out at that fit's
+seat — a padding in from the sides, the lasso's headroom down — so the tab
+stays inside the area and the row has the same padding on every side. A lasso is laid out by its members, not
 by the strategy: under Mosaic it is the hull of wherever they landed.
 
 Every exhibit is drawn at its toolkit default size — the control's configured
diff --git a/src/main.rs b/src/main.rs
index 30579da..01ac4f4 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -951,9 +951,22 @@ impl State {
             children.push(widget as *mut (dyn WidgetHost + 'static));
             indices.push(idx);
         }
+        // The exhibits start at the fitted lasso's seat: one padding in from the
+        // area's sides for the frame plus one for the members inside it, and the
+        // lasso's headroom (padding + title tab) plus a padding down. A fitted group
+        // snaps to the area's edges one padding in, and its tab needs room inside
+        // the area above its members — laid out flush with the corner, the row had
+        // the frame's wall on its left edge and the tab over its labels.
+        let (inset_x, inset_top) = match &self.roster {
+            Roster::Gallery(s) => {
+                let g = s.group_fitted.inner();
+                (2.0 * g.padding(), g.padding() + g.headroom())
+            }
+            _ => (0.0, 0.0),
+        };
         let strategy = (LAYOUTS.get(self.layout_idx).unwrap_or(&LAYOUTS[DEFAULT_LAYOUT]).1)();
-        let content_h = strategy.layout(x, y, w, h, &children, &mut self.ui_context);
-        self.exhibit_scroll.update_bounds(content_h, y, h);
+        let content_h = strategy.layout(x + inset_x, y + inset_top, w - 2.0 * inset_x, h - inset_top, &children, &mut self.ui_context);
+        self.exhibit_scroll.update_bounds(content_h + inset_top, y, h);
         let scroll_y = self.exhibit_scroll.scroll_y;
         for (&child, &idx) in children.iter().zip(&indices) {
             let widget = unsafe { &mut *child };