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

commit21c765ab6ceed137328683e21c663f8bb769b00c
parent804d1c109a
authorLucas Galante <[email protected]>
date2026-07-12 19:12
refactor(widget)!: set_parent/add_child off Element — linking is a tree op (6bd)

Element 69 -> 67 (series count). Both methods move to inherent Adapted<W>
(files' ten set_parent(None) sites resolve unchanged); the dyn callers were
three:

- focus::link_parent_child body: the add_child + set_parent pair became the
  register + tree.link + tree.set_parent ops it always was (the container
  parent-back extra produced the same symmetric link).
- TI's page-selector/StatusBar pair of dyn roster calls -> one
  link_parent_child call.
- TI ControlPanel arrange_children's per-child dummy-ctx set_parent: deleted —
  every effect was discarded with the dummy ctx (same class as the ramp
  rituals).

Adapted::add_child keeps the has_container_children parent-back extra as
direct tree ops.

Verified: 163 tests; workspace builds; A/B TI gallery (the flat-walk
parent() skip still resolves — no page-selector double-draw) and dm greeter
(link_parent_child consumer) — both empty 8% masks.

Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_018u7qTwzX95dd5ysAkaSCLk

 src/main.rs       | 12 +++++++++---
 src/ti_widgets.rs |  9 +++------
 2 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/src/main.rs b/src/main.rs
index eb02860..27bf5af 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -896,11 +896,17 @@ cascades in cce."
                 cp.add_child(ptr);
             }
 
-            // Set page selector (46) parent to StatusBar (2)
+            // Link page selector (46) under StatusBar (2) — the old set_parent + add_child
+            // pair as the one tree link it always was (6bd batch 4).
             let statusbar_ptr = state.roster.get_dyn_mut(2).as_ptr_mut();
-            state.roster.get_dyn_mut(46).set_parent(Some(statusbar_ptr), &mut state.ui_context);
             let dropdown_ptr = state.roster.get_dyn_mut(46).as_ptr_mut();
-            state.roster.get_dyn_mut(2).add_child(dropdown_ptr, &mut state.ui_context);
+            unsafe {
+                cce_ui::widget::focus::link_parent_child(
+                    &mut *statusbar_ptr,
+                    &mut *dropdown_ptr,
+                    &mut state.ui_context,
+                );
+            }
         } else {
             state.focused_widget = Some(1);
             let ramp = state.roster.get_dyn_mut(1).as_any_mut().downcast_mut::<Ramp>().expect("child ramp widget");
diff --git a/src/ti_widgets.rs b/src/ti_widgets.rs
index 130c2a9..59c9401 100644
--- a/src/ti_widgets.rs
+++ b/src/ti_widgets.rs
@@ -282,15 +282,13 @@ impl cce_ui::widget::Layout for ControlPanel {
 
     // The old `set_rect` override's arrangement: children keep their label-matched slots
     // in a ColumnLayout, laid out UNSCROLLED; the scroll offset is an aggregate-time
-    // transform. `host` (the adapter) becomes the children's parent, as the legacy panel
-    // set itself.
-    fn arrange_children(&mut self, rect: Rect, host: *mut (dyn Element + 'static)) {
+    // transform. (The dummy-ctx child re-parenting onto the host adapter is gone,
+    // 6bd: every effect of it was discarded with the dummy ctx.)
+    fn arrange_children(&mut self, rect: Rect, _host: *mut (dyn Element + 'static)) {
         let (x, y, w, h) = (rect.x, rect.y, rect.width, rect.height);
 
         self.scroll_box.set_rect(x, y, w, h);
 
-        let mut dummy = cce_ui::context::UiContext::new();
-        let self_ptr_option = Some(host);
 
         let padding = cce_ui::layout::control_panel_padding();
         let gap = cce_ui::layout::control_panel_gap();
@@ -320,7 +318,6 @@ impl cce_ui::widget::Layout for ControlPanel {
 
             for &child_ptr in &self.children {
                 let child = &mut *child_ptr;
-                child.set_parent(self_ptr_option, &mut dummy);
                 let label = child.base().and_then(|b| b.label.as_ref()).map(|s| s.as_str()).unwrap_or("");
                 match label {
                     "Create Window" => create_btn = Some(child_ptr),