git.lucas.co / cce-graph
node-based graph editor
git clone https://git.lucas.co/cce-graph.git

commit9bf6e63ce7abefb79a096169d05d9ff621714531
parent7bdf96ed8e
authorLucas Galante <lsgalante12@gmail.com>
date2026-10-07 15:30
refactor: register widgets by reference (UiContext::register_host)

register_widget(id, ptr) took a raw pointer in a safe function; cce-ui is
making it an unsafe fn now that every app registers through
register_host(&mut w), which takes the widget's own id and a live borrow.
Registration loops that existed only to hand the registry raw pointers
(and the unsafe blocks and self_ptr casts around them) are gone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

 src/main.rs  | 22 +++++++++-------------
 src/vault.rs |  3 +--
 2 files changed, 10 insertions(+), 15 deletions(-)

diff --git a/src/main.rs b/src/main.rs
index 0c5260e..2709917 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1102,19 +1102,15 @@ impl Application for GraphApp {
             // The root plate container is DISSOLVED (Phase 6m recipe): top-level widgets register
             // directly (parentless), the window plate is emitted below as prims, and the two
             // Plates keep their own children.
-            unsafe {
-                let self_ptr = self as *mut Self;
-
-                self.ui_context.register_widget(self.menu_bar.id(), (*self_ptr).menu_bar.as_ptr_mut());
-                self.ui_context.register_widget(self.dropdown_file.base().id(), (*self_ptr).dropdown_file.as_ptr_mut());
-                self.ui_context.register_widget(self.dropdown_edit.base().id(), (*self_ptr).dropdown_edit.as_ptr_mut());
-                self.ui_context.register_widget(self.dropdown_view.base().id(), (*self_ptr).dropdown_view.as_ptr_mut());
-                // Registered under the widget's OWN base id (the id-rooted router resolves
-                // dispatch roots through the registry; the old synthetic `graph_id` key left
-                // `graph.id()` unresolvable — a latent hole the pointer router masked).
-                self.ui_context.register_widget(self.graph.id(), (*self_ptr).graph.as_ptr_mut());
-                self.ui_context.register_widget(self.control_panel_label.base().id(), (*self_ptr).control_panel_label.as_ptr_mut());
-            }
+            self.ui_context.register_host(&mut self.menu_bar);
+            self.ui_context.register_host(&mut self.dropdown_file);
+            self.ui_context.register_host(&mut self.dropdown_edit);
+            self.ui_context.register_host(&mut self.dropdown_view);
+            // Registered under the widget's OWN base id (the id-rooted router resolves
+            // dispatch roots through the registry; the old synthetic `graph_id` key left
+            // `graph.id()` unresolvable — a latent hole the pointer router masked).
+            self.ui_context.register_host(&mut self.graph);
+            self.ui_context.register_host(&mut self.control_panel_label);
             self.widgets_registered = true;
         }
 
diff --git a/src/vault.rs b/src/vault.rs
index eadc220..bbefd2c 100644
--- a/src/vault.rs
+++ b/src/vault.rs
@@ -634,8 +634,7 @@ impl Application for VaultApp {
     fn display_list(&mut self, size: LogicalSize, scale: f64) -> Option<DisplayList> {
         if !self.widgets_registered {
             self.widgets_registered = true;
-            let (id, ptr) = (self.filter_input.id(), self.filter_input.as_ptr_mut());
-            self.ui_context.register_widget(id, ptr);
+            self.ui_context.register_host(&mut self.filter_input);
         }
         let resized = self.width != size.width as u32 || self.height != size.height as u32;
         self.width = size.width as u32;