widget gallery and compositor test bench
fix: the flat run starts below the Flat lasso's headroom
The Flat lasso's title tab landed on the exhibit above its first member:
the tab and padding need 28px above the hull, the strategies leave 24
between blocks, and a lasso is an overlay the strategy never sees. The
exhibits are now laid out in two passes of the selected strategy — the rest,
then the flat run one gap plus `Group::headroom` lower — so the tab clears
the block above by exactly a gap, under every strategy.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
README.md | 4 +++-
src/main.rs | 20 ++++++++++++++++++--
2 files changed, 21 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
index 9a57045..d3cc259 100644
--- a/README.md
+++ b/README.md
@@ -38,7 +38,9 @@ hex field, ProgressBar, UsageBar and Trackpad — show their flat look too (`wit
StatusDot statuses and the plain Label round it off. When a widget gains a
style, it gains an exhibit here. The flat looks come last, in one run,
so the page reads them as a section; a `Group` lasso titled `Flat` gathers
-them. Two more lassos lie over the named exhibits — `Group`, loose around the
+them, and the run is laid out as a second pass of the same strategy, one gap
+plus the lasso's headroom (`Group::headroom`, its padding and title tab)
+below the rest, so the tab clears the exhibit above it. Two more 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
by the strategy: under Mosaic it is the hull of wherever they landed.
diff --git a/src/main.rs b/src/main.rs
index 3aa946b..13c7d4c 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -983,8 +983,24 @@ impl State {
children.push(widget as *mut (dyn WidgetHost + 'static));
indices.push(idx);
}
- 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);
+ let make = LAYOUTS.get(self.layout_idx).unwrap_or(&LAYOUTS[DEFAULT_LAYOUT]).1;
+ // Two passes of the one strategy: the flat run (`FLAT_FIRST..`, the tail of the
+ // exhibits) starts one gap plus the Flat lasso's headroom below the rest, so the
+ // lasso's title tab clears the block above it — the room a strategy would reserve
+ // for the title if the lasso were its child. A lasso is an overlay the strategy
+ // never sees, so the gallery reserves it.
+ let flat_from = GALLERY_COUNT + FLAT_FIRST;
+ let (split, headroom) = match &self.roster {
+ Roster::Gallery(s) => (
+ indices.iter().position(|&i| i >= flat_from).unwrap_or(indices.len()),
+ s.group_flat.headroom(),
+ ),
+ _ => (indices.len(), 0.0),
+ };
+ let h1 = if split > 0 { make().layout(x, y, w, h, &children[..split], &mut self.ui_context) } else { 0.0 };
+ let y2 = if split > 0 { y + h1 + GAP + headroom } else { y };
+ let h2 = if split < children.len() { make().layout(x, y2, w, h, &children[split..], &mut self.ui_context) } else { 0.0 };
+ let content_h = (y2 - y) + h2;
self.exhibit_scroll.update_bounds(content_h, y, h);
let scroll_y = self.exhibit_scroll.scroll_y;
for (&child, &idx) in children.iter().zip(&indices) {