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

commit0ad5b393c937f3c1776d592a1f7e9bcb2cb3f7e3
parentded654647c
authorLucas Galante <[email protected]>
date2026-09-06 12:31
refactor: one visibility table, one page switch, helpers for the repeated shapes

main.rs 2767 -> 2540 lines, behaviour unchanged except one fix:

- Visibility: the slot-visibility match lived six times (is_widget_visible
  plus a copied closure in tick and the four input handlers). It is now
  one `Visibility` value copied out of State; the handlers ask it.
- Page: `Page::from_index` / `Page::label` and `go_to_page` replace the two
  copies of the switch-page-and-announce block (dropdown and keyboard).
- Children: `child_title` serves both the window title and the menu-bar
  title (their None cases had drifted); `child_command` / `spawn_editor`
  replace three copies of the re-exec block; Create Window builds its
  argv with `args`.
- Arguments: flag / value / number closures replace the position+get
  chains.
- Preview: `preview_style` computes the Windows-page preview's backplate /
  transparency / colour once for the three paint passes; `toggled(idx)`
  replaces the `get_value_string(idx) == Some("true")` idiom.
- `relayout` recomputes the positions table (resize, layout dropdown,
  startup) instead of three inline copies with two different expect
  messages; `window_type_description` serves both the initial label and
  the dropdown change.
- Dead: cursor_x/y and physical_width/height (written, never read); the
  demo_positions row for the page selector (apply_layout places it); the
  `2 => status_bar` drain arm nothing called; Backplate's bevel field and
  set_bevel (nothing on the display path read it, so the child's
  --border-width / --border-bevel parse went too — README says so).
- Fix: `Roster::take_click` went through `gallery_mut()`, which panics in
  child mode, so a child's Close button "closed" the window by crashing
  the process. The child roster now drains its own Close slot.
- Toggles that start off no longer call set_toggled(false); the initial
  status line is "Ready."; comments describe the code as it is instead
  of the refactor phases that produced it. gallery_widgets.rs likewise.

Verified in a shadow session: all three pages render as before, the
panel scrolls and clips, Create Window maps a toplevel child, that
child's Close closes it without a panic, Ramp... maps the editor.

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

 README.md              |   4 +-
 src/gallery_widgets.rs |  78 ++---
 src/main.rs            | 919 +++++++++++++++++++------------------------------
 3 files changed, 385 insertions(+), 616 deletions(-)

diff --git a/README.md b/README.md
index 1e0d835..469b794 100644
--- a/README.md
+++ b/README.md
@@ -58,7 +58,9 @@ cce-gallery --child --type <Toplevel|Popup|LayerTop|LayerOverlay|LayerBackground
 ```
 
 A simulated window shows a description label, a `Close` button, and the
-optional menu bar and status bar. Its `app_id` encodes what it is, so
+optional menu bar and status bar. `--border-width` and `--border-bevel` are
+accepted so the argv mirrors the panel, but the child does not draw a bevel
+yet; the bevel preview lives in the main window's panel. Its `app_id` encodes what it is, so
 compositor rules can target it: `cce-gallery-child-<type>` with `-circular`
 and/or `-noborder` appended when those apply. The main window's `app_id` is
 `cce-gallery` (also with `-noborder` when the border is disabled).
diff --git a/src/gallery_widgets.rs b/src/gallery_widgets.rs
index 554588d..bcd3ebf 100644
--- a/src/gallery_widgets.rs
+++ b/src/gallery_widgets.rs
@@ -1,16 +1,13 @@
-//! Test-interface-owned copies of the dissolved cce-ui containers (Phase 6as): the
-//! gallery is the last constructor of ControlPanel / SectionContainer / Plate /
-//! Backplate, and it needs them only as demo chrome — the panel verbatim, the other
-//! three as passive lookalikes replicating the legacy types' exact emission surfaces
-//! (color rules, corner radius/rounding, borders, separators, labels, hit shapes).
-//! Phase 6az: all four are on the narrow traits wrapped in `Adapted<W>`; the gallery
-//! roster keeps them as `Box<dyn WidgetHost>` and reaches the models through `as_any`.
+//! Gallery-owned copies of containers the toolkit no longer ships: the ControlPanel
+//! (scroll chrome the app lays children into) and passive lookalikes of the old
+//! Plate, SectionContainer and Backplate, kept as exhibits that reproduce their colour
+//! rules, corner rounding, borders, separators and labels. All four sit on the narrow
+//! widget traits wrapped in `Adapted<W>`.
 
 use cce_ui::colors;
 use cce_ui::scene::layout::Rect;
 use cce_ui::scene::paint::PaintCtx;
 use cce_ui::widget::*;
-use cce_ui::widget::ScrollBox;
 
 pub struct ControlPanel {
     x: f32,
@@ -20,13 +17,9 @@ pub struct ControlPanel {
     pub scroll_box: ScrollBox,
 }
 
-/// The panel is scroll chrome only (the ControlPanel endgame): background, borders, and
-/// the ScrollBox machinery. Its former stored child pointers, label-matched arrangement,
-/// aggregate views, and dyn event/tick/drag forwarding are DISSOLVED into the app —
-/// main.rs lays the child slots out at SCREEN (scrolled) coordinates
-/// (`arrange_control_panel`), emits their geometry/text clamped to the panel viewport in
-/// `display_list`, and dispatches them as ordinary routed roots. No `*mut dyn` storage,
-/// no dummy contexts, no scroll-translated coordinates anywhere.
+/// Scroll chrome only: background, borders and the ScrollBox. main.rs lays the child
+/// slots out at screen coordinates (`arrange_control_panel`), paints them clamped to
+/// the panel viewport in `display_list`, and dispatches them as ordinary roots.
 impl ControlPanel {
     pub fn new() -> Adapted<ControlPanel> {
         let mut sb = ScrollBox::new();
@@ -48,8 +41,7 @@ impl ControlPanel {
 }
 
 impl cce_ui::widget::Layout for ControlPanel {
-    // The panel's own label ("ControlPanel") never rendered on the legacy paths and its
-    // rect was never label-inflated — keep the adapter out of both.
+    // The panel's label is never rendered and its rect is never label-inflated.
     fn inline_label(&self) -> bool {
         true
     }
@@ -69,13 +61,12 @@ impl cce_ui::widget::Paint for ControlPanel {
     }
 
     fn corner_style(&self, _rect: Rect) -> Option<(f32, (bool, bool, bool, bool))> {
-        // Legacy: rounded_corners all-true with the WidgetHost-default 12.0 radius.
+        // All corners, 12px.
         Some((12.0, (true, true, true, true)))
     }
 
-    /// Background + borders, as radius-0 rounded prims so they ride the adapter's
-    /// rounded-tuple bridge exactly where the legacy aggregate emitted them (the app
-    /// emits the children and the scrollbar after these, in the legacy order).
+    /// Background + borders as radius-0 rounded prims, so they land in the rounded pass
+    /// ahead of the children and the scrollbar the app paints after them.
     fn paint(&self, _rect: Rect, pc: &mut PaintCtx) {
         let (x, y, w, h) = self.rect();
         let none = (false, false, false, false);
@@ -132,10 +123,9 @@ impl cce_ui::widget::Input for ControlPanel {
     }
 }
 
-/// Gallery exhibit lookalike of the dissolved cce-ui `Plate`: default plate color rule
-/// (config plate color, else page color) at plate opacity, alpha negated under blur,
-/// plate corner radius/rounding, config border, detached-top label handled like the
-/// legacy plate (background shifted below the label, label drawn from `paint`).
+/// Exhibit lookalike of the old cce-ui `Plate`: config plate colour (else page colour)
+/// at plate opacity, alpha negated under blur, plate corner radius, config border, and a
+/// detached-top label with the background shifted below it.
 pub struct Plate {
     blur: bool,
     label: Option<String>,
@@ -161,7 +151,7 @@ impl Plate {
         c
     }
 
-    /// The legacy `Widget::label_offset` rule for the model-held label copy.
+    /// Label offset for the model-held label copy.
     fn label_offset(&self) -> f32 {
         if cce_ui::layout::control_label_layout() == "side" {
             return 0.0;
@@ -176,8 +166,8 @@ impl Plate {
 }
 
 impl cce_ui::widget::Layout for Plate {
-    // The legacy plate never inflated its rect for the label; it shifted its background
-    // below it instead (see `paint`).
+    // The rect is not inflated for the label; the background shifts below it instead
+    // (see `paint`).
     fn inline_label(&self) -> bool {
         true
     }
@@ -203,8 +193,8 @@ impl cce_ui::widget::Paint for Plate {
     }
 
     fn paint(&self, rect: Rect, pc: &mut PaintCtx) {
-        // Rounded background below the label region — the legacy all_rounded_quads
-        // override: emitted only while corners are on and the color has alpha.
+        // Rounded background below the label region, only while corners are on and the
+        // colour has alpha.
         let radius = cce_ui::layout::plate_corner_radius();
         let c = self.plate_color();
         if radius > 0.0 && c[3].abs() > 0.001 {
@@ -225,9 +215,8 @@ impl cce_ui::widget::Paint for Plate {
 
 impl cce_ui::widget::Input for Plate {}
 
-/// Gallery lookalike of the dissolved cce-ui `SectionContainer` as the ControlPanel uses
-/// it: a childless section header row — the title label plus the SectionHeader separator
-/// line. The panel matches sections by the adapter's base label; the model keeps a copy
+/// Lookalike of the old cce-ui `SectionContainer` as the panel used it: a childless
+/// section header row, title plus separator line. The model keeps a copy of the label
 /// (via `sync_label`) for its own painting.
 pub struct SectionContainer {
     title: String,
@@ -240,8 +229,8 @@ impl SectionContainer {
 }
 
 impl cce_ui::widget::Layout for SectionContainer {
-    // The title is painted by the model at its legacy position; keep the adapter's
-    // detached-label machinery (offset inflation + fallback label) out of it.
+    // The model paints the title itself; keep the adapter's detached-label machinery
+    // (offset inflation + fallback label) out of it.
     fn inline_label(&self) -> bool {
         true
     }
@@ -271,23 +260,17 @@ impl cce_ui::widget::Input for SectionContainer {
     }
 }
 
-/// Child-window background lookalike of the dissolved cce-ui `Backplate`: the base color
-/// forced to the configured backplate opacity, backplate corner radius, immovable.
-pub struct Backplate {
-    bevel: Option<f32>,
-}
+/// Child-window background, a lookalike of the old cce-ui `Backplate`: page colour at
+/// the configured backplate opacity, backplate corner radius, immovable.
+pub struct Backplate;
 
 impl Backplate {
     pub fn new(x: f32, y: f32, w: f32, h: f32) -> Adapted<Backplate> {
-        let mut bp = Adapted::new(Self { bevel: None });
+        let mut bp = Adapted::new(Self);
         bp.set_rect(x, y, w, h);
         bp
     }
 
-    pub fn set_bevel(&mut self, thickness: f32) {
-        self.bevel = Some(thickness);
-    }
-
     fn backplate_color(&self) -> [f32; 4] {
         let mut c = cce_ui::color::page_low_color();
         if c[3] > 0.001 {
@@ -311,10 +294,7 @@ impl cce_ui::widget::Paint for Backplate {
     }
 
     fn paint(&self, rect: Rect, pc: &mut PaintCtx) {
-        // The legacy rounded Backplate emitted its background only through
-        // all_rounded_quads (nothing when the radius is off) — same shape here. The bevel
-        // field is carried for the --border-bevel flag but, like the legacy lookalike, has
-        // no reader on the gallery's display path.
+        // Painted only while the radius is on.
         let radius = cce_ui::color::root_plate_corner_radius();
         let c = self.backplate_color();
         if radius > 0.1 && c[3].abs() > 0.001 {
diff --git a/src/main.rs b/src/main.rs
index 1bff095..15ec3d0 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,6 +1,6 @@
 use cce_ui::widget::{
     Button, Checkbox, ContentBg, Dropdown, Label, Paginator, Panel, ProgressBar, RangeSlider, Slider, Spinbox, StatusBar,
-    Toggle, WidgetHost, Trackpad, hover_animation, TextBox, CornerRadii, MenuBar, 
+    Toggle, WidgetHost, Trackpad, hover_animation, TextBox, CornerRadii, MenuBar,
     Ramp, RampKey, ColorRamp, MouseButton, ElementState, Key, NamedKey, KeyEvent, MouseScrollDelta
 };
 mod gallery_widgets;
@@ -16,10 +16,64 @@ enum Page {
     Xdg,
 }
 
+impl Page {
+    fn from_index(i: usize) -> Page {
+        match i {
+            0 => Page::Controls,
+            1 => Page::Windows,
+            _ => Page::Xdg,
+        }
+    }
+
+    fn label(self) -> &'static str {
+        match self {
+            Page::Controls => "Controls",
+            Page::Windows => "Windows",
+            Page::Xdg => "XDG",
+        }
+    }
+}
+
+/// What the roster's visibility filter needs, copied out of `State` so the dispatch
+/// loops can hold `&mut self.roster` while asking.
+#[derive(Clone, Copy)]
+struct Visibility {
+    is_child: bool,
+    use_menubar: bool,
+    use_statusbar: bool,
+    page: Page,
+}
 
-/// The gallery roster, concretely typed (Phase 6bb): 45 named slots replacing the erased
-/// `Vec<Box<dyn WidgetHost>>`. The historical numeric indexes (positions vec, dispatch loops,
-/// page layouts) keep addressing the same slots through `get_dyn`/`get_dyn_mut`.
+impl Visibility {
+    fn is_visible(self, index: usize) -> bool {
+        if self.is_child {
+            return match index {
+                0..=2 => true, // background, main, Close
+                3 => self.use_menubar,
+                4 => self.use_statusbar,
+                _ => false,
+            };
+        }
+        match index {
+            0..=2 | 38 => true,
+            3..=8 | 22 | 23 | 28 | 29 | 39 | 41 | 42 | 44 => self.page == Page::Controls,
+            9..=21 | 30..=37 | 40 | 43 => self.page == Page::Windows,
+            24..=27 => self.page == Page::Xdg,
+            _ => false,
+        }
+    }
+}
+
+/// The Windows page's preview panel look, shared by its three paint passes.
+struct PreviewStyle {
+    backplate: bool,
+    transparency: f32,
+    bg_color: [f32; 4],
+}
+
+/// The gallery roster: 45 named slots. The numeric indexes used by the positions
+/// table, the visibility filter and the dispatch loops address these slots through
+/// `get_dyn`/`get_dyn_mut`.
 pub struct GallerySlots {
     pub menu_bar: Adapted<MenuBar>,
     pub paginator: Adapted<Paginator>,
@@ -72,8 +126,7 @@ pub const GALLERY_COUNT: usize = 45;
 
 impl GallerySlots {
 
-    // Per-slot drag queries (the ControlPanel endgame took `draggable`/`is_dragging`
-    // off `WidgetHost`).
+    // Per-slot drag queries.
     pub fn draggable(&self, idx: usize) -> bool {
         match idx {
             0 => self.menu_bar.draggable(),
@@ -469,15 +522,17 @@ impl Roster {
         }
     }
 
-    // --- App-local value drains (6bd value shrink): the `WidgetHost` polling block
-    // (`take_click`/`value`/`get_value_string`/`set_text`) went concrete-slot — these
-    // route a gallery index to its concrete slot's inherent `Adapted` method. Arms exist
-    // only for the slots the page logic actually drains; a new drain site adds its arm.
+    // --- Value drains: route a slot index to its concrete slot's `take_click` /
+    // `value` / `get_value_string` / `set_text`. Arms exist only for the slots the
+    // page logic actually drains; a new drain site adds its arm.
 
     pub fn take_click(&mut self, idx: usize) -> bool {
-        let s = self.gallery_mut();
+        let s = match self {
+            Roster::Gallery(s) => s,
+            // The child roster drains one slot: its Close button.
+            Roster::Child(c) => return idx == 2 && c.close.take_click(),
+        };
         match idx {
-            2 => s.status_bar.take_click(),
             3 => s.button_demo.take_click(),
             4 => s.checkbox_demo.take_click(),
             5 => s.toggle_demo.take_click(),
@@ -558,13 +613,8 @@ struct State {
 
     focused_widget: Option<usize>,
 
-    cursor_x: f32,
-    cursor_y: f32,
-
     width: f32,
     height: f32,
-    physical_width: u32,
-    physical_height: u32,
     scale: f64,
 
     current_page: Page,
@@ -724,9 +774,8 @@ fn is_control_panel_child(i: usize) -> bool {
     matches!(i, 10..=18 | 30..=37 | 40)
 }
 
-/// The panel's child slots in the legacy arrangement/aggregation order (the ControlPanel
-/// endgame: the panel no longer stores pointers to them — the app lays them out, emits
-/// them clamped to the panel viewport, and dispatches them as ordinary routed roots).
+/// The control panel's child slots, in arrangement order: the app lays them out, paints
+/// them clamped to the panel viewport, and dispatches them as ordinary roots.
 const CP_CHILDREN: [usize; 18] = [10, 14, 15, 11, 12, 13, 16, 17, 18, 30, 31, 32, 33, 34, 35, 36, 37, 40];
 
 impl State {
@@ -766,29 +815,63 @@ fn run_file_dialog(save: bool, sender: calloop::channel::Sender<String>) {
 
 
 impl State {
-    fn is_widget_visible(&self, index: usize) -> bool {
-        if self.is_child {
-            return match index {
-                0..=2 => true,
-                3 => self.use_menubar,
-                4 => self.use_statusbar,
-                _ => false,
-            };
-        }
-        match index {
-            0..=2 | 38 => true,
-            3..=8 | 22 | 23 | 28 | 29 | 39 | 41 | 42 | 44 => self.current_page == Page::Controls,
-            9..=21 | 30..=37 | 40 | 43 => self.current_page == Page::Windows,
-            24..=27 => self.current_page == Page::Xdg,
-            _ => false,
+    fn visibility(&self) -> Visibility {
+        Visibility {
+            is_child: self.is_child,
+            use_menubar: self.use_menubar,
+            use_statusbar: self.use_statusbar,
+            page: self.current_page,
         }
     }
 
+    fn is_widget_visible(&self, index: usize) -> bool {
+        self.visibility().is_visible(index)
+    }
+
+    /// A toggle slot's state.
+    fn toggled(&self, idx: usize) -> bool {
+        self.roster.get_value_string(idx) == Some("true".to_string())
+    }
+
+    fn go_to_page(&mut self, page: Page) {
+        self.current_page = page;
+        self.update_status_text(&format!("Viewing {} Page", page.label()));
+        self.apply_layout();
+    }
+
+    /// Recompute the positions table for the current size, mode and layout.
+    fn relayout(&mut self) {
+        self.positions = if self.is_child {
+            child_positions(self.width, self.height, self.use_menubar, self.use_statusbar, self.child_type.as_deref())
+        } else {
+            let sidebar_w = self.sidebar_w();
+            demo_positions(self.width, self.height, sidebar_w, self.layout_idx, self.roster.gallery())
+        };
+    }
+
+    fn sidebar_w(&self) -> f32 {
+        cce_ui::widget::PageSelector::sidebar_w(
+            self.roster.gallery().paginator.as_any().downcast_ref::<cce_ui::widget::Paginator>().expect("slot 1 must be the Paginator"),
+        )
+    }
+
+    fn preview_style(&self) -> PreviewStyle {
+        let backplate = self.toggled(30);
+        let transparency = if self.toggled(11) { self.roster.value(12) as f32 / 100.0 } else { 1.0 };
+        let bg_color = if backplate {
+            let mut col = cce_ui::color::page_low_color();
+            col[3] = transparency;
+            col
+        } else {
+            [0.12, 0.12, 0.15, transparency]
+        };
+        PreviewStyle { backplate, transparency, bg_color }
+    }
+
     /// Register every roster widget in the ui_context (idempotent — `register` is
     /// id-keyed and the boxed slots keep pointers stable). The id-rooted router
-    /// (`propagate_event(event, WidgetId)`) resolves roots through this registry;
-    /// TI's custom paint loop never goes through `render_widget`, which is where
-    /// other apps pick registration up as a side effect.
+    /// resolves roots through this registry; the gallery's own paint loop never goes
+    /// through `render_widget`, where other apps pick registration up as a side effect.
     fn register_roster(&mut self) {
         for i in 0..self.roster.len() {
             let w = self.roster.get_dyn_mut(i);
@@ -805,40 +888,28 @@ impl State {
             sh - 24.0
         };
 
-        for i in 0..self.positions.len() {
+        for i in 0..self.roster.len() {
+            if self.roster.is_dragging(i) {
+                continue;
+            }
+            // The page selector (38) is placed inside the status bar below; the panel's
+            // children are laid out by arrange_control_panel at real screen coordinates.
+            if !self.is_child && (i == 38 || is_control_panel_child(i)) {
+                continue;
+            }
             let visible = self.is_widget_visible(i);
-            let pos = self.positions[i];
-            if i < self.roster.len() {
-                if self.roster.is_dragging(i) {
-                    continue;
-                }
-                let widget = self.roster.get_dyn_mut(i);
-                
-                if !self.is_child && i == 38 {
-                    continue;
-                }
-
-                if is_control_panel_child(i) {
-                    // Laid out by arrange_control_panel after this loop (real screen
-                    // coordinates; every consumer gates on page visibility).
-                    continue;
-                }
-                
-                if visible {
-                    let (x, y, w, h) = pos;
-                    let mut final_h = h;
-                    if i != 0 && i != 1 && i != 2 && i != 43 {
-                        if y + h > limit_y {
-                            final_h = (limit_y - y).max(0.0);
-                        }
-                    }
-                    widget.set_rect(x, y, w, final_h);
-                } else {
-                    widget.set_rect(-1000.0, -1000.0, 0.0, 0.0);
-                }
+            let (x, y, w, h) = self.positions[i];
+            let widget = self.roster.get_dyn_mut(i);
+            if visible {
+                // Everything but the chrome and the panel clips at the status bar.
+                let clipped = i != 0 && i != 1 && i != 2 && i != 43 && y + h > limit_y;
+                let final_h = if clipped { (limit_y - y).max(0.0) } else { h };
+                widget.set_rect(x, y, w, final_h);
+            } else {
+                widget.set_rect(-1000.0, -1000.0, 0.0, 0.0);
             }
         }
-        
+
         if !self.is_child {
             let (x, y, w, h) = self.positions[43];
             self.roster.get_dyn_mut(43).set_rect(x, y, w, h);
@@ -856,17 +927,15 @@ impl State {
         }
     }
 
-    /// Lay the panel's child slots out at SCREEN coordinates (the ControlPanel endgame).
-    /// The legacy panel arranged them in content space and shifted at aggregate time;
-    /// applying the scroll offset at layout time means hit-testing, dispatch, text, and
-    /// popovers all see real positions. Runs from apply_layout — every rebuild — which is
-    /// also what re-arranges after a scroll (the wheel handler sets needs_rebuild).
+    /// Lay the panel's child slots out at screen coordinates, scroll offset applied, so
+    /// hit-testing, dispatch, text and popovers all see real positions. Runs from
+    /// apply_layout and from display_list, which is what re-arranges after a scroll.
     fn arrange_control_panel(&mut self) {
         let s = self.roster.gallery_mut();
         let (x, y, w, h) = s.control_panel.rect();
         let padding = cce_ui::layout::control_panel_padding();
         let gap = cce_ui::layout::control_panel_gap();
-        // 12px reserved for the scrollbar track, like the legacy arrangement.
+        // 12px reserved for the scrollbar track.
         let mut col = cce_ui::widget::ColumnLayout::new(x, y, w - 12.0, gap, padding);
 
         col.add_widget(&mut s.create_window_btn, 28.0);
@@ -915,40 +984,21 @@ impl cce_ui::engine::Application for State {
 
     fn new(_qh: &QueueHandle<cce_ui::engine::EngineState<Self>>, sender: calloop::channel::Sender<Self::Message>) -> Self {
         let args: Vec<String> = std::env::args().collect();
-        let is_child = args.contains(&"--child".to_string());
-        let use_backplate = if is_child {
-            args.contains(&"--backplate".to_string())
-        } else {
-            !args.contains(&"--no-backplate".to_string())
-        };
-        let use_menubar = args.contains(&"--menubar".to_string());
-        let use_statusbar = args.contains(&"--statusbar".to_string());
-        let type_idx = args.iter().position(|a| a == "--type");
-        let child_type = type_idx.and_then(|i| args.get(i + 1)).cloned();
-        let shape_idx = args.iter().position(|a| a == "--shape");
-        let child_shape = shape_idx.and_then(|i| args.get(i + 1)).cloned();
-        let opacity = args.contains(&"--opacity".to_string());
-        let transp_idx = args.iter().position(|a| a == "--transparency");
-        let transparency = transp_idx
-            .and_then(|i| args.get(i + 1))
-            .and_then(|s| s.parse::<f32>().ok())
-            .unwrap_or(1.0);
-        let no_border = args.contains(&"--no-border".to_string());
-        let border_enabled = !no_border;
-        let border_width_idx = args.iter().position(|a| a == "--border-width");
-        let border_width = border_width_idx
-            .and_then(|i| args.get(i + 1))
-            .and_then(|s| s.parse::<f32>().ok())
-            .unwrap_or(1.0);
-        let border_bevel = args.contains(&"--border-bevel".to_string());
-        let width_idx = args.iter().position(|a| a == "--width");
-        let custom_width = width_idx
-            .and_then(|i| args.get(i + 1))
-            .and_then(|s| s.parse::<f32>().ok());
-        let height_idx = args.iter().position(|a| a == "--height");
-        let custom_height = height_idx
-            .and_then(|i| args.get(i + 1))
-            .and_then(|s| s.parse::<f32>().ok());
+        let flag = |name: &str| args.iter().any(|a| a == name);
+        let value = |name: &str| args.iter().position(|a| a == name).and_then(|i| args.get(i + 1)).cloned();
+        let number = |name: &str| value(name).and_then(|s| s.parse::<f32>().ok());
+
+        let is_child = flag("--child");
+        let use_backplate = if is_child { flag("--backplate") } else { !flag("--no-backplate") };
+        let use_menubar = flag("--menubar");
+        let use_statusbar = flag("--statusbar");
+        let child_type = value("--type");
+        let child_shape = value("--shape");
+        let opacity = flag("--opacity");
+        let transparency = number("--transparency").unwrap_or(1.0);
+        let border_enabled = !flag("--no-border");
+        let custom_width = number("--width");
+        let custom_height = number("--height");
 
         let (mut c_w, mut c_h): (f32, f32) = if is_child {
             if let (Some(w), Some(h)) = (custom_width, custom_height) {
@@ -973,9 +1023,9 @@ impl cce_ui::engine::Application for State {
             c_h = side;
         }
 
-        let is_ramp_child = is_child && (child_type.as_deref() == Some("Ramp") || child_type.as_deref() == Some("ColorRamp"));
+        let is_ramp_child = is_child && matches!(child_type.as_deref(), Some("Ramp") | Some("ColorRamp"));
         let opacity = opacity || is_ramp_child;
-        let status_text = "Select a test case to begin verification.".to_string();
+        let status_text = "Ready.".to_string();
 
         let roster = if is_child {
             let desc_label = match child_type.as_deref() {
@@ -988,11 +1038,7 @@ impl cce_ui::engine::Application for State {
                 None => "This is an active simulated window in the window manager.".to_string(),
             };
             let bg = if use_backplate {
-                let mut bp = Backplate::new(0.0, 0.0, c_w, c_h);
-                if border_bevel {
-                    bp.set_bevel(border_width);
-                }
-                ChildBg::Backplate(bp)
+                ChildBg::Backplate(Backplate::new(0.0, 0.0, c_w, c_h))
             } else {
                 ChildBg::ContentBg(ContentBg::new())
             };
@@ -1042,11 +1088,8 @@ impl cce_ui::engine::Application for State {
                 .with_item("Help", &["About"])
                 .with_right_aligned_title(true);
             Roster::Gallery(Box::new(GallerySlots {
-                menu_bar: menu_bar,
-                paginator: {
-                    let paginator = Paginator::new(vec![]);
-                    paginator
-                },
+                menu_bar,
+                paginator: Paginator::new(vec![]),
                 status_bar: StatusBar::new(),
                 button_demo: Button::new(0.0, 0.0, 140.0, 40.0).with_label("Button"),
                 checkbox_demo: Checkbox::new().with_label("Checkbox"),
@@ -1079,15 +1122,7 @@ impl cce_ui::engine::Application for State {
                 height_spin: Spinbox::new(250, 100, 2000, 10).with_label("Height"),
                 surface_plate: Plate::new(0.0, 0.0, 190.0, 250.0, true),
                 surface_info_label: Label::new("Surface Info").with_font_size(12.0),
-                surface_desc_label: Label::new(
-                    "A standard application\n\
-window (xdg_toplevel).\n\
-It supports tiling (cascade,\n\
-split, grid), fullscreening,\n\
-dragging, and resizing.\n\n\
-Testing layout:\n\
-cascades in cce."
-                ).with_font_size(10.0),
+                surface_desc_label: Label::new(window_type_description(0)).with_font_size(10.0),
                 range_slider_demo: RangeSlider::new().with_label("RangeSlider"),
                 trackpad_demo: Trackpad::new().with_label("Trackpad"),
                 portal_panel: Panel::new(0.0, 0.0, 450.0, 200.0).with_label("File chooser"),
@@ -1101,22 +1136,10 @@ cascades in cce."
                     t.set_toggled(true);
                     t
                 },
-                menubar_toggle: {
-                    let mut t = Toggle::new().with_label("MenuBar");
-                    t.set_toggled(false);
-                    t
-                },
-                statusbar_toggle: {
-                    let mut t = Toggle::new().with_label("StatusBar");
-                    t.set_toggled(false);
-                    t
-                },
+                menubar_toggle: Toggle::new().with_label("MenuBar"),
+                statusbar_toggle: Toggle::new().with_label("StatusBar"),
                 border_section: SectionContainer::new("Border"),
-                bevel_toggle: {
-                    let mut t = Toggle::new().with_label("Bevel");
-                    t.set_toggled(false);
-                    t
-                },
+                bevel_toggle: Toggle::new().with_label("Bevel"),
                 border_width_spin: Spinbox::new(1, 1, 20, 1).with_label("Border Width"),
                 bevel_depth_spin: {
                     let default_depth = (cce_ui::layout::bevel_depth() * 100.0) as i32;
@@ -1145,28 +1168,15 @@ cascades in cce."
             }))
         };
 
-        let positions = if is_child {
-            child_positions(c_w, c_h, use_menubar, use_statusbar, child_type.as_deref())
-        } else {
-            let sidebar_w = cce_ui::widget::PageSelector::sidebar_w(
-                roster.gallery().paginator.as_any().downcast_ref::<cce_ui::widget::Paginator>().expect("slot 1 must be the Paginator"),
-            );
-            demo_positions(c_w, c_h, sidebar_w, 9, roster.gallery())
-        };
-
         let (loaded_keys, loaded_type) = load_bevel_ramp();
 
         let mut state = Self {
             roster,
-            positions,
+            positions: Vec::new(),
             status_text,
             focused_widget: None,
-            cursor_x: 0.0,
-            cursor_y: 0.0,
             width: c_w,
             height: c_h,
-            physical_width: c_w as u32,
-            physical_height: c_h as u32,
             scale: 1.0,
             current_page: Page::Controls,
             is_child,
@@ -1187,8 +1197,7 @@ cascades in cce."
         };
 
         if !is_child {
-            // Link page selector (38) under StatusBar (2) — the old set_parent + add_child
-            // pair as the one tree link it always was (6bd batch 4).
+            // Link the page selector (38) under the status bar (2) in the ui tree.
             let statusbar_ptr = state.roster.get_dyn_mut(2) as *mut (dyn WidgetHost + 'static);
             let dropdown_ptr = state.roster.get_dyn_mut(38) as *mut (dyn WidgetHost + 'static);
             unsafe {
@@ -1215,25 +1224,18 @@ cascades in cce."
             }
         }
 
+        state.relayout();
         state.apply_layout();
         state
     }
 
     fn settings(&self) -> cce_ui::engine::WindowSettings {
         let title = if self.is_child {
-            match self.child_type.as_deref() {
-                Some("Toplevel") => "Simulated Toplevel Window".to_string(),
-                Some("Popup") => "Simulated Popup Window".to_string(),
-                Some("LayerTop") => "Simulated Layer Shell (Top) Surface".to_string(),
-                Some("LayerOverlay") => "Simulated Layer Shell (Overlay) Surface".to_string(),
-                Some("LayerBackground") => "Simulated Layer Shell (Background) Surface".to_string(),
-                Some(other) => format!("Simulated {} Window", other),
-                None => "Simulated Client Window".to_string(),
-            }
+            child_title(self.child_type.as_deref())
         } else {
             "Gallery".to_string()
         };
-        
+
         let mut app_id = if self.is_child {
             if let Some(ref t) = self.child_type {
                 format!("cce-gallery-child-{}", t.to_lowercase())
@@ -1292,28 +1294,8 @@ cascades in cce."
         if hover_animation::tick(dt) {
             changed = true;
         }
-        let is_child = self.is_child;
-        let use_menubar = self.use_menubar;
-        let use_statusbar = self.use_statusbar;
-        let current_page = self.current_page;
-        let is_visible = move |index: usize| -> bool {
-            if is_child {
-                match index {
-                    0..=2 => true,
-                    3 => use_menubar,
-                    4 => use_statusbar,
-                    _ => false,
-                }
-            } else {
-                match index {
-                    0..=2 | 38 => true,
-                    3..=8 | 22 | 23 | 28 | 29 | 39 | 41 | 42 | 44 => current_page == Page::Controls,
-                    9..=21 | 30..=37 | 40 | 43 => current_page == Page::Windows,
-                    24..=27 => current_page == Page::Xdg,
-                    _ => false,
-                }
-            }
-        };
+        let vis = self.visibility();
+        let is_visible = move |index: usize| vis.is_visible(index);
         for i in 0..self.roster.len() {
             let w = self.roster.get_dyn_mut(i);
             if is_visible(i) {
@@ -1337,34 +1319,23 @@ cascades in cce."
     }
 
     fn display_list(&mut self, size: LogicalSize, scale: f64) -> Option<cce_ui::scene::paint::DisplayList> {
-        // Phase 6af single paint path: the whole frame — the legacy view_rounded_quads
-        // geometry, then the view() geometry (the wrapper's order), then every text
-        // label as a prim — is this one list, rebuilt fresh each frame (the old
-        // rebuild_text_items cache and its 14 invalidation call sites are gone).
+        // The whole frame — rounded geometry, plain geometry, popovers, then text — is
+        // one display list, rebuilt each frame.
         use cce_ui::scene::layout::Rect;
         self.register_roster();
-        // Panel children follow the scroll offset at LAYOUT time (the dissolved panel
-        // shifted at aggregate time): re-arrange every frame so a wheel scroll moves the
-        // content on the frame it repaints. Idempotent and cheap (~20 set_rects).
+        // Panel children follow the scroll offset at layout time: re-arrange every frame
+        // so a wheel scroll moves the content on the frame it repaints. Idempotent and
+        // cheap (~20 set_rects).
         if !self.is_child {
             self.arrange_control_panel();
         }
         if (self.width - size.width as f32).abs() > 0.001 || (self.height - size.height as f32).abs() > 0.001 || (self.scale - scale).abs() > 0.001 {
             self.width = size.width as f32;
             self.height = size.height as f32;
-            self.physical_width = (size.width * scale as f32) as u32;
-            self.physical_height = (size.height * scale as f32) as u32;
             self.scale = scale;
             cce_ui::scale::set_scale_factor(scale as f32);
 
-            self.positions = if self.is_child {
-                child_positions(self.width, self.height, self.use_menubar, self.use_statusbar, self.child_type.as_deref())
-            } else {
-                let sidebar_w = cce_ui::widget::PageSelector::sidebar_w(
-                    self.roster.get_dyn_mut(1).as_any().downcast_ref::<cce_ui::widget::Paginator>().expect("widgets[1] must be the Paginator"),
-                );
-                demo_positions(self.width, self.height, sidebar_w, self.layout_idx, self.roster.gallery())
-            };
+            self.relayout();
             self.apply_layout();
             let text = self.status_text.clone();
             self.update_status_text(&text);
@@ -1374,7 +1345,7 @@ cascades in cce."
         let sh = self.height;
         let mut pc = cce_ui::scene::paint::PaintCtx::new();
 
-        // ── Rounded geometry (the legacy view_rounded_quads body) ──
+        // ── Rounded geometry ──
         if !self.is_child && self.use_backplate {
             let r = cce_ui::color::root_plate_corner_radius();
             let bg_color = cce_ui::color::page_low_color();
@@ -1400,17 +1371,8 @@ cascades in cce."
             }
             if !self.is_child && i == 9 {
                 let r = cce_ui::color::root_plate_corner_radius();
-                let backplate_enabled = self.roster.get_value_string(30) == Some("true".to_string());
-                let border_bevel = self.roster.get_value_string(34) == Some("true".to_string());
-                let opacity_enabled = self.roster.get_value_string(11) == Some("true".to_string());
-                let transparency_val = if opacity_enabled { self.roster.value(12) as f32 / 100.0 } else { 1.0 };
-                let bg_color = if backplate_enabled {
-                    let mut col = cce_ui::color::page_low_color();
-                    col[3] = transparency_val;
-                    col
-                } else {
-                    [0.12, 0.12, 0.15, transparency_val]
-                };
+                let PreviewStyle { backplate: backplate_enabled, transparency: transparency_val, bg_color } = self.preview_style();
+                let border_bevel = self.toggled(34);
 
                 let (wx, wy, ww, wh) = w.rect();
                 if backplate_enabled {
@@ -1423,7 +1385,7 @@ cascades in cce."
                     }
                 }
 
-                let menubar_enabled = self.roster.get_value_string(31) == Some("true".to_string());
+                let menubar_enabled = self.toggled(31);
                 if menubar_enabled {
                     let mut menu_color = cce_ui::color::root_plate_menubar_color();
                     menu_color[3] = transparency_val;
@@ -1434,7 +1396,7 @@ cascades in cce."
                     }
                 }
 
-                let statusbar_enabled = self.roster.get_value_string(32) == Some("true".to_string());
+                let statusbar_enabled = self.toggled(32);
                 if statusbar_enabled {
                     let mut status_color = cce_ui::color::root_plate_statusbar_color();
                     status_color[3] = transparency_val;
@@ -1460,13 +1422,11 @@ cascades in cce."
             }
         }
 
-        // ── ControlPanel children (the dissolved panel's aggregate, app-side): the slots
-        // are at real screen coordinates now; the legacy clamp-to-viewport, partial-clip
-        // radius zeroing, and solid-border synthesis/inset rules apply verbatim, and the
-        // scrollbar draws last, over the children, like the aggregate did. ──
+        // ── ControlPanel children: clamped to the panel viewport (a partially clipped
+        // quad loses its radius), solid borders synthesized and their fill inset, then
+        // the scrollbar last, over the children. ──
         if !self.is_child && self.current_page == Page::Windows {
-            let (panel_x, panel_y, panel_w, panel_h) = self.roster.gallery().control_panel.rect();
-            let _ = (panel_x, panel_w);
+            let (_, panel_y, _, panel_h) = self.roster.gallery().control_panel.rect();
             let y_start = panel_y;
             let y_end = panel_y + panel_h;
             for &ci in CP_CHILDREN.iter() {
@@ -1532,7 +1492,7 @@ cascades in cce."
             }
         }
 
-        // ── Plain geometry (the legacy view() body) ──
+        // ── Plain geometry ──
         for i in 0..self.roster.len() {
             let w = self.roster.get_dyn(i);
             if !self.is_widget_visible(i) {
@@ -1542,19 +1502,10 @@ cascades in cce."
                 continue;
             }
             if !self.is_child && i == 9 {
-                let backplate_enabled = self.roster.get_value_string(30) == Some("true".to_string());
-                let opacity_enabled = self.roster.get_value_string(11) == Some("true".to_string());
-                let transparency_val = if opacity_enabled { self.roster.value(12) as f32 / 100.0 } else { 1.0 };
-                let bg_color = if backplate_enabled {
-                    let mut col = cce_ui::color::page_low_color();
-                    col[3] = transparency_val;
-                    col
-                } else {
-                    [0.12, 0.12, 0.15, transparency_val]
-                };
+                let style = self.preview_style();
                 let (wx, wy, ww, wh) = w.rect();
-                if !backplate_enabled {
-                    pc.quad(Rect { x: wx, y: wy, width: ww, height: wh }, bg_color);
+                if !style.backplate {
+                    pc.quad(Rect { x: wx, y: wy, width: ww, height: wh }, style.bg_color);
                 }
             } else {
                 for (qx, qy, qw, qh, qc) in w.all_quads(&self.ui_context) {
@@ -1563,9 +1514,8 @@ cascades in cce."
             }
         }
 
-        // ── ControlPanel children, plain decorations (the dissolved aggregate_plain):
-        // the child's own rounded background is skipped like the legacy rule, the rest
-        // clamps to the panel viewport. ──
+        // ── ControlPanel children, plain decorations: a child's own rounded background
+        // was painted above; the rest clamps to the panel viewport. ──
         if !self.is_child && self.current_page == Page::Windows {
             let (_panel_x, panel_y, _panel_w, panel_h) = self.roster.gallery().control_panel.rect();
             let y_start = panel_y;
@@ -1607,23 +1557,11 @@ cascades in cce."
             }
         }
 
-        // ── Text, as prims (the legacy rebuild_text_items assembly, uncached) ──
+        // ── Text ──
         let label_text = if self.is_child {
-            match self.child_type.as_deref() {
-                Some("Toplevel") => "Simulated Toplevel Window".to_string(),
-                Some("Popup") => "Simulated Popup Window".to_string(),
-                Some("LayerTop") => "Simulated Layer Shell (Top) Surface".to_string(),
-                Some("LayerOverlay") => "Simulated Layer Shell (Overlay) Surface".to_string(),
-                Some("LayerBackground") => "Simulated Layer Shell (Background) Surface".to_string(),
-                Some(other) => format!("Simulated {} Window", other),
-                None => "Simulated Window".to_string(),
-            }
+            child_title(self.child_type.as_deref())
         } else {
-            match self.current_page {
-                Page::Controls => "Gallery - Controls".to_string(),
-                Page::Windows => "Gallery - Windows".to_string(),
-                Page::Xdg => "Gallery - XDG".to_string(),
-            }
+            format!("Gallery - {}", self.current_page.label())
         };
         let mut has_menu_bar = false;
         for i in 0..self.roster.len() {
@@ -1661,13 +1599,9 @@ cascades in cce."
             if !self.is_widget_visible(i) {
                 continue;
             }
-            // Text via the paint walk (not the legacy getters): same labels with the
-            // widget's content font and clip bounds; the popover cull stays on the prim
-            // coordinates. Any widget with a ui-tree parent (the page selector under the
-            // status bar) is covered by that parent's descent — walking it here too would
-            // emit its text twice. ControlPanel children clamp their bounds to the panel
-            // viewport (the dissolved scrolled_child_labels rule, minus the shift — the
-            // slots sit at real screen coordinates now).
+            // A widget with a ui-tree parent (the page selector under the status bar) is
+            // covered by that parent's walk — emitting it here too would draw its text
+            // twice. Text inside a popover is culled; panel children clip to the panel.
             if self.ui_context.tree.parent_ptr(w.base().id()).is_some() {
                 continue;
             }
@@ -1697,7 +1631,7 @@ cascades in cce."
         }
 
 
-        // The status line the old text_areas() override appended.
+        // The status line.
         if !self.is_child {
             let (_, status_font_size) = cce_ui::layout::statusbar_font_parsed();
             let status_size = if status_font_size > 0.0 { status_font_size } else { 12.0 };
@@ -1738,26 +1672,17 @@ cascades in cce."
             }
 
             if !self.is_child && i == 9 {
-                let border_enabled = self.roster.get_value_string(16) == Some("true".to_string());
+                let border_enabled = self.toggled(16);
                 if border_enabled {
-                    let backplate_enabled = self.roster.get_value_string(30) == Some("true".to_string());
-                    let opacity_enabled = self.roster.get_value_string(11) == Some("true".to_string());
-                    let transparency_val = if opacity_enabled { self.roster.value(12) as f32 / 100.0 } else { 1.0 };
-                    let bg_color = if backplate_enabled {
-                        let mut col = cce_ui::color::page_low_color();
-                        col[3] = transparency_val;
-                        col
-                    } else {
-                        [0.12, 0.12, 0.15, transparency_val]
-                    };
+                    let PreviewStyle { backplate: backplate_enabled, transparency: transparency_val, bg_color } = self.preview_style();
 
                     let mut border_color = cce_ui::color::plate_border_color().unwrap_or([0.3, 0.3, 0.4, 1.0]);
                     border_color[3] = transparency_val;
                     let t = self.roster.value(35) as f32;
-                    let border_bevel = self.roster.get_value_string(34) == Some("true".to_string());
+                    let border_bevel = self.toggled(34);
                     let r = cce_ui::color::root_plate_corner_radius();
                     let (wx, wy, ww, wh) = w.rect();
-                    
+
                     if backplate_enabled {
                         let radii = CornerRadii::new(r, r, r, r);
                         if border_bevel {
@@ -1766,18 +1691,18 @@ cascades in cce."
                             for idx in 0..slices {
                                 let u_curr = idx as f32 / slices as f32;
                                 let u_next = (idx + 1) as f32 / slices as f32;
-                                
+
                                 let h_outer = interpolate_ramp_value(&self.bevel_ramp, u_curr, &self.bevel_ramp_line_type);
                                 let h_inner = interpolate_ramp_value(&self.bevel_ramp, u_next, &self.bevel_ramp_line_type);
-                                
+
                                 let d_h = h_inner - h_outer;
                                 let bevel_depth = self.roster.value(36) as f32 / 100.0;
                                 let color_offset = d_h * bevel_depth * 2.667;
-                                
+
                                  let rad = cce_ui::layout::light_source_position();
                                  let lx = rad.cos();
                                  let ly = -rad.sin();
-                                 
+
                                  let c_offset = |factor: f32| -> [f32; 4] {
                                      let o = factor * color_offset;
                                      [
@@ -1787,19 +1712,19 @@ cascades in cce."
                                          bg_color[3]
                                      ]
                                  };
-                                 
+
                                  let top_color = c_offset(-ly);
                                  let left_color = c_offset(-lx);
                                  let bottom_color = c_offset(ly);
                                  let right_color = c_offset(lx);
- 
+
                                  let offset = idx as f32 * slice_w;
                                  let r_offset = (r - offset).max(0.0);
                                  verts.extend(quad_vertices(wx + r_offset, wy + offset, ww - 2.0 * r_offset, slice_w, sw, sh, top_color));
                                  verts.extend(quad_vertices(wx + offset, wy + r_offset, slice_w, wh - 2.0 * r_offset, sw, sh, left_color));
                                  verts.extend(quad_vertices(wx + r_offset, wy + wh - offset - slice_w, ww - 2.0 * r_offset, slice_w, sw, sh, bottom_color));
                                  verts.extend(quad_vertices(wx + ww - offset - slice_w, wy + r_offset, slice_w, wh - 2.0 * r_offset, sw, sh, right_color));
- 
+
                                  push_bevel_slice_corners(
                                      wx, wy, ww, wh,
                                      r, r_offset, slice_w,
@@ -1850,37 +1775,15 @@ cascades in cce."
 
     fn handle_pointer_move(&mut self, pos: LogicalPosition, needs_rebuild: &mut bool) {
         let (lx, ly) = (pos.x as f32, pos.y as f32);
-        self.cursor_x = lx;
-        self.cursor_y = ly;
 
         let mut changed = false;
-        // Routed dispatch (6bd shrink): the router owns the drag lifecycle — one
+        // The router owns the drag lifecycle — one
         // PointerMove per visible root forwards DragUpdate to a live drag target and
         // runs hover bookkeeping otherwise.
         let mv = cce_ui::widget::Event::PointerMove { x: lx, y: ly, local_x: lx, local_y: ly };
         {
-            let is_child = self.is_child;
-            let use_menubar = self.use_menubar;
-            let use_statusbar = self.use_statusbar;
-            let current_page = self.current_page;
-            let is_visible = move |index: usize| -> bool {
-                if is_child {
-                    match index {
-                        0..=2 => true,
-                        3 => use_menubar,
-                        4 => use_statusbar,
-                        _ => false,
-                    }
-                } else {
-                    match index {
-                        0..=2 | 38 => true,
-                        3..=8 | 22 | 23 | 28 | 29 | 39 | 41 | 42 | 44 => current_page == Page::Controls,
-                        9..=21 | 30..=37 | 40 | 43 => current_page == Page::Windows,
-                        24..=27 => current_page == Page::Xdg,
-                        _ => false,
-                    }
-                }
-            };
+            let vis = self.visibility();
+            let is_visible = move |index: usize| vis.is_visible(index);
             for i in 0..self.roster.len() {
                 if !is_visible(i) {
                     continue;
@@ -1901,32 +1804,10 @@ cascades in cce."
 
     fn handle_mouse_input(&mut self, button: MouseButton, state: ElementState, pos: LogicalPosition, needs_rebuild: &mut bool) -> Option<Self::Message> {
         let (lx, ly) = (pos.x as f32, pos.y as f32);
-        self.cursor_x = lx;
-        self.cursor_y = ly;
 
         let mut changed = false;
-        let is_child = self.is_child;
-        let use_menubar = self.use_menubar;
-        let use_statusbar = self.use_statusbar;
-        let current_page = self.current_page;
-        let is_visible = move |index: usize| -> bool {
-            if is_child {
-                match index {
-                    0..=2 => true,
-                    3 => use_menubar,
-                    4 => use_statusbar,
-                    _ => false,
-                }
-            } else {
-                match index {
-                    0..=2 | 38 => true,
-                    3..=8 | 22 | 23 | 28 | 29 | 39 | 41 | 42 | 44 => current_page == Page::Controls,
-                    9..=21 | 30..=37 | 40 | 43 => current_page == Page::Windows,
-                    24..=27 => current_page == Page::Xdg,
-                    _ => false,
-                }
-            }
-        };
+        let vis = self.visibility();
+        let is_visible = move |index: usize| vis.is_visible(index);
 
         if state == ElementState::Pressed {
             let mut clicked_idx = None;
@@ -1964,10 +1845,9 @@ cascades in cce."
                 }
             }
             if let Some(i) = clicked_idx {
-                // Routed press: the router records the drag target on a handled press
-                // and synthesizes DragStart past its threshold (the old immediate
-                // drag_begin). Legacy also armed drags whose press handler returned
-                // false — preserve that by recording the target explicitly.
+                // The router records the drag target on a handled press and synthesizes
+                // DragStart past its threshold; a draggable slot whose press handler
+                // returned false is armed explicitly.
                 let ev = cce_ui::widget::Event::MouseButton { button, state, x: lx, y: ly, local_x: lx, local_y: ly };
                 let root = self.roster.get_dyn(i).base().id();
                 let press_handled = self.ui_context.propagate_event(&ev, root);
@@ -2010,62 +1890,21 @@ cascades in cce."
                         return Some("exit".to_string());
                     }
                 } else {
-                    let mut page_changed = false;
-                    let mut selected = 0;
                     if self.roster.take_click(38) {
-                        selected = self.roster.value(38);
-                        page_changed = true;
-                    }
-                    
-                    if page_changed {
-                        if selected == 0 {
-                            self.current_page = Page::Controls;
-                            self.update_status_text("Viewing Controls Page");
-                        } else if selected == 1 {
-                            self.current_page = Page::Windows;
-                            self.update_status_text("Viewing Windows Page");
-                        } else {
-                            self.current_page = Page::Xdg;
-                            self.update_status_text("Viewing XDG Page");
-                        }
-                        self.apply_layout();
+                        self.go_to_page(Page::from_index(self.roster.value(38) as usize));
                         changed = true;
                     } else if self.roster.take_click(44) {
                         self.layout_idx = self.roster.value(44) as usize;
-                        self.positions = demo_positions(self.width, self.height, cce_ui::widget::PageSelector::sidebar_w(self.roster.gallery().paginator.as_any().downcast_ref::<cce_ui::widget::Paginator>().expect("slot 1 must be the Paginator")), self.layout_idx, self.roster.gallery());
+                        self.relayout();
                         self.apply_layout();
                         changed = true;
                     } else if self.current_page == Page::Controls {
-                        if self.roster.take_click(3) {
-                            // Does nothing
-                        } else if self.roster.take_click(39) {
-                            if let Ok(exe) = std::env::current_exe() {
-                                let mut cmd = std::process::Command::new(exe);
-                                cmd.arg("--child")
-                                   .arg("--type")
-                                   .arg("ColorRamp")
-                                   .arg("--width")
-                                   .arg("450")
-                                   .arg("--height")
-                                   .arg("350")
-                                   .arg("--backplate");
-                                let _ = cmd.spawn();
-                            }
+                        if self.roster.take_click(39) {
+                            spawn_editor("ColorRamp");
                         } else if self.roster.take_click(42) {
-                            if let Ok(exe) = std::env::current_exe() {
-                                let mut cmd = std::process::Command::new(exe);
-                                cmd.arg("--child")
-                                   .arg("--type")
-                                   .arg("Ramp")
-                                   .arg("--width")
-                                   .arg("450")
-                                   .arg("--height")
-                                   .arg("350")
-                                   .arg("--backplate");
-                                let _ = cmd.spawn();
-                            }
+                            spawn_editor("Ramp");
                         } else {
-                            for i in [4, 5, 7, 8, 22, 23, 28, 29] {
+                            for i in [3, 4, 5, 7, 8, 22, 23, 28, 29] {
                                 if self.roster.take_click(i) {
                                     changed = true;
                                 }
@@ -2073,22 +1912,11 @@ cascades in cce."
                         }
                     } else if self.current_page == Page::Windows {
                         let mut create_window = false;
-                        
+
                         if self.roster.take_click(10) {
                             create_window = true;
                         } else if self.roster.take_click(40) {
-                            if let Ok(exe) = std::env::current_exe() {
-                                let mut cmd = std::process::Command::new(exe);
-                                cmd.arg("--child")
-                                   .arg("--type")
-                                   .arg("Ramp")
-                                   .arg("--width")
-                                   .arg("450")
-                                   .arg("--height")
-                                   .arg("350")
-                                   .arg("--backplate");
-                                let _ = cmd.spawn();
-                            }
+                            spawn_editor("Ramp");
                         } else {
                             let mut dropdown_clicked = false;
                             for i in [11, 12, 14, 15, 16, 17, 18, 30, 31, 32, 34, 35, 36] {
@@ -2106,48 +1934,11 @@ cascades in cce."
                                 }
                             }
                             if dropdown_clicked {
-                                let desc = match self.roster.value(14) {
-                                    0 => "A standard application\n\
-window (xdg_toplevel).\n\
-It supports tiling (cascade,\n\
-split, grid), fullscreening,\n\
-dragging, and resizing.\n\n\
-Testing layout:\n\
-cascades in cce.",
-                                    1 => "An anchored sub-surface\n\
-popup (xdg_popup).\n\
-Usually transient context\n\
-menus, tooltips, or dropdown\n\
-lists. Bypasses tiling.\n\n\
-Testing layout:\n\
-maps floating on top.",
-                                    2 => "A high-level Layer Shell\n\
-surface (anchored to top).\n\
-Typically status bars, menus,\n\
-or docks. Reserves panel\n\
-space, limiting workspace.\n\n\
-Testing layout:\n\
-full width at top.",
-                                    3 => "A high-priority Layer Shell\n\
-surface (overlay layer).\n\
-Used for screensavers, lock\n\
-screens, or overlay HUDs.\n\
-Sits above tiling windows.\n\n\
-Testing layout:\n\
-center floating window.",
-                                    4 => "A bottom-level Layer Shell\n\
-surface (background layer).\n\
-Used for desktop wallpaper.\n\
-Renders below all other\n\
-client windows.\n\n\
-Testing layout:\n\
-full screen background.",
-                                    _ => "",
-                                };
+                                let desc = window_type_description(self.roster.value(14));
                                 self.roster.set_text(21, desc);
                             }
                         }
-                        
+
                         if create_window {
                             let window_type = match self.roster.value(14) {
                                 0 => "Toplevel",
@@ -2162,55 +1953,35 @@ full screen background.",
                                 1 => "circular",
                                 _ => "rectangular",
                             };
-                            let opacity_enabled = self.roster.get_value_string(11) == Some("true".to_string());
+                            let opacity_enabled = self.toggled(11);
                             let transparency_pct = self.roster.value(12);
                             let transparency_val = transparency_pct as f32 / 100.0;
-                            let border_enabled = self.roster.get_value_string(16) == Some("true".to_string());
+                            let border_enabled = self.toggled(16);
                             let custom_width = self.roster.value(17);
                             let custom_height = self.roster.value(18);
-     
+
                             self.update_status_text(&format!("Spawning simulated {} {} window...", shape, window_type));
-                            if let Ok(exe) = std::env::current_exe() {
-                                let mut cmd = std::process::Command::new(exe);
-                                cmd.arg("--child")
-                                   .arg("--type")
-                                   .arg(window_type)
-                                   .arg("--shape")
-                                   .arg(shape);
-                                let backplate_enabled = self.roster.get_value_string(30) == Some("true".to_string());
-                                let menubar_enabled = self.roster.get_value_string(31) == Some("true".to_string());
-                                let statusbar_enabled = self.roster.get_value_string(32) == Some("true".to_string());
+                            if let Some(mut cmd) = child_command() {
+                                cmd.args(["--type", window_type, "--shape", shape]);
                                 if opacity_enabled {
-                                    cmd.arg("--opacity")
-                                       .arg("--transparency")
-                                       .arg(transparency_val.to_string());
+                                    cmd.args(["--opacity", "--transparency", &transparency_val.to_string()]);
                                 }
                                 if !border_enabled {
                                     cmd.arg("--no-border");
                                 } else {
-                                    let border_width = self.roster.value(35) as f32;
-                                    let border_bevel = self.roster.get_value_string(34) == Some("true".to_string());
-                                    cmd.arg("--border-width")
-                                       .arg(border_width.to_string());
-                                    if border_bevel {
+                                    cmd.args(["--border-width", &self.roster.value(35).to_string()]);
+                                    if self.toggled(34) {
                                         cmd.arg("--border-bevel");
                                     }
                                 }
-                                if backplate_enabled {
-                                    cmd.arg("--backplate");
-                                }
-                                if menubar_enabled {
-                                    cmd.arg("--menubar");
-                                }
-                                if statusbar_enabled {
-                                    cmd.arg("--statusbar");
+                                for (flag, on) in [("--backplate", self.toggled(30)), ("--menubar", self.toggled(31)), ("--statusbar", self.toggled(32))] {
+                                    if on {
+                                        cmd.arg(flag);
+                                    }
                                 }
-                                 cmd.arg("--width")
-                                    .arg(custom_width.to_string())
-                                    .arg("--height")
-                                    .arg(custom_height.to_string());
-                                 let _ = cce_ui::process::spawn_tracked(cmd);
-                             }
+                                cmd.args(["--width", &custom_width.to_string(), "--height", &custom_height.to_string()]);
+                                let _ = cce_ui::process::spawn_tracked(cmd);
+                            }
                             changed = true;
                         }
                     } else if self.current_page == Page::Xdg {
@@ -2240,31 +2011,11 @@ full screen background.",
     fn handle_mouse_wheel(&mut self, delta: &MouseScrollDelta, pos: LogicalPosition, needs_rebuild: &mut bool) {
         let (lx, ly) = (pos.x as f32, pos.y as f32);
         let mut changed = false;
-        let is_child = self.is_child;
-        let use_menubar = self.use_menubar;
-        let use_statusbar = self.use_statusbar;
-        let current_page = self.current_page;
-        let is_visible = move |index: usize| -> bool {
-            if is_child {
-                match index {
-                    0..=2 => true,
-                    3 => use_menubar,
-                    4 => use_statusbar,
-                    _ => false,
-                }
-            } else {
-                match index {
-                    0..=2 | 38 => true,
-                    3..=8 | 22 | 23 | 28 | 29 | 39 | 41 | 42 | 44 => current_page == Page::Controls,
-                    9..=21 | 30..=37 | 40 | 43 => current_page == Page::Windows,
-                    24..=27 => current_page == Page::Xdg,
-                    _ => false,
-                }
-            }
-        };
+        let vis = self.visibility();
+        let is_visible = move |index: usize| vis.is_visible(index);
         let ev = cce_ui::widget::Event::MouseWheel { delta: *delta, x: lx, y: ly, local_x: lx, local_y: ly };
-        // Panel scroll first (legacy: the panel's scroll frame consumed the wheel before
-        // its children saw it); a consumed wheel never reaches the panel's children.
+        // The panel's scroll frame gets the wheel first; a consumed wheel never reaches
+        // its children.
         let mut cp_took_wheel = false;
         if !self.is_child && is_visible(43) {
             let root = self.roster.get_dyn(43).base().id();
@@ -2296,28 +2047,8 @@ full screen background.",
 
     fn handle_key_input(&mut self, event: &KeyEvent, needs_rebuild: &mut bool) -> Option<Self::Message> {
         let mut changed = false;
-        let is_child = self.is_child;
-        let use_menubar = self.use_menubar;
-        let use_statusbar = self.use_statusbar;
-        let current_page = self.current_page;
-        let is_visible = move |index: usize| -> bool {
-            if is_child {
-                match index {
-                    0..=2 => true,
-                    3 => use_menubar,
-                    4 => use_statusbar,
-                    _ => false,
-                }
-            } else {
-                match index {
-                    0..=2 | 38 => true,
-                    3..=8 | 22 | 23 | 28 | 29 | 39 | 41 | 42 | 44 => current_page == Page::Controls,
-                    9..=21 | 30..=37 | 40 | 43 => current_page == Page::Windows,
-                    24..=27 => current_page == Page::Xdg,
-                    _ => false,
-                }
-            }
-        };
+        let vis = self.visibility();
+        let is_visible = move |index: usize| vis.is_visible(index);
         let mut handled = false;
         let key_ev = cce_ui::widget::Event::KeyInput(event.clone());
         if let Some(focused) = self.focused_widget {
@@ -2336,8 +2067,7 @@ full screen background.",
                 if !is_visible(i) {
                     continue;
                 }
-                // Panel children take keys only through the focused path above (the
-                // legacy panel never forwarded keys).
+                // Panel children take keys only through the focused path above.
                 if is_control_panel_child(i) {
                     continue;
                 }
@@ -2353,37 +2083,22 @@ full screen background.",
             }
         }
 
-        if event.state == ElementState::Pressed {
-            let mut page_nav = false;
-            let mut selected = 0;
-            {
-                // input.kdl `cce-gallery` domain
-                let m = |name: &str, default: &str| {
-                    cce_ui::widget::match_key_shortcut(event, &cce_ui::input::app_chord(name, default))
-                };
-                if m("page_1", "ctrl+1") {
-                    selected = 0;
-                    page_nav = true;
-                } else if m("page_2", "ctrl+2") {
-                    selected = 1;
-                    page_nav = true;
-                } else if m("page_3", "ctrl+3") {
-                    selected = 2;
-                    page_nav = true;
-                }
-            }
-            if page_nav && !self.is_child {
-                if selected == 0 {
-                    self.current_page = Page::Controls;
-                    self.update_status_text("Viewing Controls Page");
-                } else if selected == 1 {
-                    self.current_page = Page::Windows;
-                    self.update_status_text("Viewing Windows Page");
-                } else {
-                    self.current_page = Page::Xdg;
-                    self.update_status_text("Viewing XDG Page");
-                }
-                self.apply_layout();
+        if event.state == ElementState::Pressed && !self.is_child {
+            // input.kdl `cce-gallery` domain
+            let m = |name: &str, default: &str| {
+                cce_ui::widget::match_key_shortcut(event, &cce_ui::input::app_chord(name, default))
+            };
+            let page = if m("page_1", "ctrl+1") {
+                Some(Page::Controls)
+            } else if m("page_2", "ctrl+2") {
+                Some(Page::Windows)
+            } else if m("page_3", "ctrl+3") {
+                Some(Page::Xdg)
+            } else {
+                None
+            };
+            if let Some(page) = page {
+                self.go_to_page(page);
                 changed = true;
             }
         }
@@ -2408,6 +2123,78 @@ full screen background.",
     }
 }
 
+/// A child window's title, from its `--type`.
+fn child_title(child_type: Option<&str>) -> String {
+    match child_type {
+        Some("Toplevel") => "Simulated Toplevel Window".to_string(),
+        Some("Popup") => "Simulated Popup Window".to_string(),
+        Some("LayerTop") => "Simulated Layer Shell (Top) Surface".to_string(),
+        Some("LayerOverlay") => "Simulated Layer Shell (Overlay) Surface".to_string(),
+        Some("LayerBackground") => "Simulated Layer Shell (Background) Surface".to_string(),
+        Some(other) => format!("Simulated {} Window", other),
+        None => "Simulated Window".to_string(),
+    }
+}
+
+/// The Windows page's description of a window-type dropdown entry.
+fn window_type_description(idx: i32) -> &'static str {
+    match idx {
+        0 => "A standard application\n\
+window (xdg_toplevel).\n\
+It supports tiling (cascade,\n\
+split, grid), fullscreening,\n\
+dragging, and resizing.\n\n\
+Testing layout:\n\
+cascades in cce.",
+        1 => "An anchored sub-surface\n\
+popup (xdg_popup).\n\
+Usually transient context\n\
+menus, tooltips, or dropdown\n\
+lists. Bypasses tiling.\n\n\
+Testing layout:\n\
+maps floating on top.",
+        2 => "A high-level Layer Shell\n\
+surface (anchored to top).\n\
+Typically status bars, menus,\n\
+or docks. Reserves panel\n\
+space, limiting workspace.\n\n\
+Testing layout:\n\
+full width at top.",
+        3 => "A high-priority Layer Shell\n\
+surface (overlay layer).\n\
+Used for screensavers, lock\n\
+screens, or overlay HUDs.\n\
+Sits above tiling windows.\n\n\
+Testing layout:\n\
+center floating window.",
+        4 => "A bottom-level Layer Shell\n\
+surface (background layer).\n\
+Used for desktop wallpaper.\n\
+Renders below all other\n\
+client windows.\n\n\
+Testing layout:\n\
+full screen background.",
+        _ => "",
+    }
+}
+
+/// A `Command` that re-runs this binary as a child window; the caller adds the flags.
+fn child_command() -> Option<std::process::Command> {
+    let exe = std::env::current_exe().ok()?;
+    let mut cmd = std::process::Command::new(exe);
+    cmd.arg("--child");
+    Some(cmd)
+}
+
+/// Opens a Ramp or ColorRamp editor window. Untracked on purpose: an editor outlives
+/// the gallery, unlike the simulated windows Create Window spawns.
+fn spawn_editor(kind: &str) {
+    if let Some(mut cmd) = child_command() {
+        cmd.args(["--type", kind, "--width", "450", "--height", "350", "--backplate"]);
+        let _ = cmd.spawn();
+    }
+}
+
 fn demo_positions(sw: f32, sh: f32, sidebar_w: f32, layout_idx: usize, slots: &GallerySlots) -> Vec<(f32, f32, f32, f32)> {
     let base_x = sidebar_w + 20.0;
     let sph = cce_ui::layout::spinbox_height();
@@ -2415,14 +2202,14 @@ fn demo_positions(sw: f32, sh: f32, sidebar_w: f32, layout_idx: usize, slots: &G
     let slh = cce_ui::layout::slider_height();
     let bh = cce_ui::layout::button_height();
     let ddh = cce_ui::layout::dropdown_height();
-    
+
     let mut vec = vec![(0.0, 0.0, 0.0, 0.0); 45];
-    
+
     // Common layout elements
     vec[0] = (0.0, 0.0, sw, 40.0); // 0 MenuBar
     vec[1] = (0.0, 40.0, sidebar_w, sh - 40.0 - 24.0); // 1 Page selector (Sidebar)
     vec[2] = (0.0, sh - 24.0, sw, 24.0); // 2 StatusBar
-    
+
     // Page 1 (Windows)
     vec[9] = (base_x, 60.0, 400.0, 250.0); // 9 Panel (Window simulation area)
     vec[10] = (base_x + 420.0, 60.0, 140.0, bh); // 10 Button (Create Window)
@@ -2437,13 +2224,13 @@ fn demo_positions(sw: f32, sh: f32, sidebar_w: f32, layout_idx: usize, slots: &G
     vec[19] = (base_x, 320.0, 190.0, 250.0); // 19 Plate
     vec[20] = (base_x + 10.0, 330.0, 170.0, 20.0); // 20 Label
     vec[21] = (base_x + 10.0, 360.0, 170.0, 180.0); // 21 Label
-    
+
     // Page 2 (XDG)
     vec[24] = (base_x, 60.0, 450.0, 200.0); // 24 Panel
     vec[25] = (base_x + 20.0, 80.0, 410.0, 60.0); // 25 Label
     vec[26] = (base_x + 20.0, 160.0, 180.0, bh); // 26 Button
     vec[27] = (base_x + 220.0, 160.0, 180.0, bh); // 27 Button
-    
+
     // Window Simulation options (visible when Page::Windows is active)
     vec[30] = (base_x + 420.0, 300.0, 140.0, tgh); // 30 Toggle: Backplate
     vec[31] = (base_x + 420.0, 340.0, 140.0, tgh); // 31 Toggle: MenuBar
@@ -2453,13 +2240,13 @@ fn demo_positions(sw: f32, sh: f32, sidebar_w: f32, layout_idx: usize, slots: &G
     vec[35] = (base_x + 420.0, 490.0, 140.0, sph); // 35 Spinbox: Border Width
     vec[36] = (base_x + 420.0, 535.0, 140.0, sph); // 36 Spinbox: Bevel Depth
     vec[37] = (base_x + 420.0, 270.0, 140.0, 20.0); // 37 SectionContainer: Window Elements
-    vec[38] = (sw - 140.0, sh - 14.0 - ddh / 2.0, 120.0, ddh); // 38 Dropdown: Page selector
+    // 38 (page selector) is placed by apply_layout, inside the status bar.
     vec[40] = (base_x + 420.0, 580.0, 140.0, bh); // 40 Button: Bevel Shape
     vec[43] = (sw - 270.0, 60.0, 250.0, sh - 100.0); // 43 ControlPanel
-    
+
     // Dynamically position Page 0 (Controls) elements using the selected layout index
     let available_w = (sw - base_x - 290.0).max(300.0);
-    
+
     struct DemoPacker {
         free_rects: Vec<(f32, f32, f32, f32)>,
         max_w: f32,
@@ -2479,7 +2266,7 @@ fn demo_positions(sw: f32, sh: f32, sidebar_w: f32, layout_idx: usize, slots: &G
 
         fn pack(&mut self, cw: f32, ch: f32) -> (f32, f32) {
             let cw_clamped = cw.min(self.max_w);
-            
+
             let mut best_idx = None;
             let mut best_y = f32::MAX;
             let mut best_x = f32::MAX;
@@ -2713,8 +2500,8 @@ fn demo_positions(sw: f32, sh: f32, sidebar_w: f32, layout_idx: usize, slots: &G
             }
         }
     }
-    
-    
+
+
     vec
 }