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

commit243497af85a8f8b5df444b47b98e9624712b1582
parent9592208342
authorLucas Galante <[email protected]>
date2026-07-01 21:28
Register popovers and implement render_popovers in GraphApp

 src/main.rs | 78 ++++++++++++++++++++++++++++++++++---------------------------
 1 file changed, 44 insertions(+), 34 deletions(-)

diff --git a/src/main.rs b/src/main.rs
index bda90e8..7db2b76 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,7 +1,7 @@
 use wayland_client::QueueHandle;
 use glyphon::{FontSystem, Buffer, Metrics, Attrs};
 use cce_ui::engine::{Application, EngineState, LogicalPosition, LogicalSize, WindowSettings};
-use cce_ui::widget::{MouseButton, ElementState, MouseScrollDelta, KeyEvent, TextItem, Element, Graph, GraphNode, MenuBar, MenuController, GraphController};
+use cce_ui::widget::{MouseButton, ElementState, MouseScrollDelta, KeyEvent, TextItem, Element, Graph, GraphNode, MenuBar, MenuController, GraphController, WidgetId};
 
 #[derive(Debug, Clone)]
 enum AppMessage {
@@ -17,6 +17,7 @@ enum AppMessage {
 struct GraphApp {
     menu_bar: MenuBar,
     graph: Graph,
+    graph_id: WidgetId,
     text_items: Vec<TextItem>,
     font_system: FontSystem,
     needs_rebuild: bool,
@@ -25,8 +26,7 @@ struct GraphApp {
     scale_factor: f64,
     show_grid: bool,
     uniform_background: bool,
-    cell_opacity: f32,
-    gap_opacity: f32,
+    opacity: f32,
     ui_context: cce_ui::context::UiContext,
 }
 
@@ -103,7 +103,7 @@ impl Application for GraphApp {
         ];
         graph.set_nodes(&nodes);
         
-        let (show_grid, snap_enabled, uniform_background, cell_opacity, gap_opacity, gap_width) = load_config();
+        let (show_grid, snap_enabled, uniform_background, opacity, gap_width) = load_config();
 
         // Configure initial grid settings on the graph
         graph.set_show_network_grid(show_grid);
@@ -112,8 +112,7 @@ impl Application for GraphApp {
         graph.set_grid_origin(60.0, 60.0);
         graph.set_grid_snap_enabled(snap_enabled);
         graph.set_uniform_background(uniform_background);
-        graph.set_cell_opacity(cell_opacity);
-        graph.set_gap_opacity(gap_opacity);
+        graph.set_network_opacity(opacity);
 
         // Build Menu Bar with options to toggle new features
         let mut menu_bar = MenuBar::new(0.0, 0.0, 1024.0, 26.0)
@@ -130,13 +129,16 @@ impl Application for GraphApp {
             
         menu_bar.set_item_checked(2, 0, show_grid);  // Show Grid checked
         menu_bar.set_item_checked(2, 1, uniform_background); // Uniform Background unchecked
-        menu_bar.set_item_checked(2, 2, (cell_opacity - 0.95).abs() < 0.05);  // Opacity 95% checked
-        menu_bar.set_item_checked(2, 3, (cell_opacity - 0.75).abs() < 0.05);  // Opacity 75% checked
-        menu_bar.set_item_checked(2, 4, (cell_opacity - 0.50).abs() < 0.05);  // Opacity 50% checked
+        menu_bar.set_item_checked(2, 2, (opacity - 0.95).abs() < 0.05);  // Opacity 95% checked
+        menu_bar.set_item_checked(2, 3, (opacity - 0.75).abs() < 0.05);  // Opacity 75% checked
+        menu_bar.set_item_checked(2, 4, (opacity - 0.50).abs() < 0.05);  // Opacity 50% checked
+
+        let graph_id = WidgetId(cce_ui::widget::NEXT_WIDGET_ID.fetch_add(1, std::sync::atomic::Ordering::SeqCst));
 
         let mut app = Self {
             menu_bar,
             graph,
+            graph_id,
             text_items: Vec::new(),
             font_system: FontSystem::new(),
             needs_rebuild: true,
@@ -145,8 +147,7 @@ impl Application for GraphApp {
             scale_factor: 1.0,
             show_grid,
             uniform_background,
-            cell_opacity,
-            gap_opacity,
+            opacity,
             ui_context: cce_ui::context::UiContext::new(),
         };
         
@@ -189,41 +190,32 @@ impl Application for GraphApp {
                 self.needs_rebuild = true;
             }
             AppMessage::SetOpacity95 => {
-                self.cell_opacity = 0.95;
-                self.gap_opacity = 0.95;
-                self.graph.set_cell_opacity(0.95);
-                self.graph.set_gap_opacity(0.95);
+                self.opacity = 0.95;
+                self.graph.set_network_opacity(0.95);
                 self.menu_bar.set_item_checked(2, 2, true);
                 self.menu_bar.set_item_checked(2, 3, false);
                 self.menu_bar.set_item_checked(2, 4, false);
-                write_config_value("graph_cell_opacity", "0.95");
-                write_config_value("graph_gap_opacity", "0.95");
+                write_config_value("graph_network_opacity", "0.95");
                 *needs_rebuild = true;
                 self.needs_rebuild = true;
             }
             AppMessage::SetOpacity75 => {
-                self.cell_opacity = 0.75;
-                self.gap_opacity = 0.75;
-                self.graph.set_cell_opacity(0.75);
-                self.graph.set_gap_opacity(0.75);
+                self.opacity = 0.75;
+                self.graph.set_network_opacity(0.75);
                 self.menu_bar.set_item_checked(2, 2, false);
                 self.menu_bar.set_item_checked(2, 3, true);
                 self.menu_bar.set_item_checked(2, 4, false);
-                write_config_value("graph_cell_opacity", "0.75");
-                write_config_value("graph_gap_opacity", "0.75");
+                write_config_value("graph_network_opacity", "0.75");
                 *needs_rebuild = true;
                 self.needs_rebuild = true;
             }
             AppMessage::SetOpacity50 => {
-                self.cell_opacity = 0.50;
-                self.gap_opacity = 0.50;
-                self.graph.set_cell_opacity(0.50);
-                self.graph.set_gap_opacity(0.50);
+                self.opacity = 0.50;
+                self.graph.set_network_opacity(0.50);
                 self.menu_bar.set_item_checked(2, 2, false);
                 self.menu_bar.set_item_checked(2, 3, false);
                 self.menu_bar.set_item_checked(2, 4, true);
-                write_config_value("graph_cell_opacity", "0.50");
-                write_config_value("graph_gap_opacity", "0.50");
+                write_config_value("graph_network_opacity", "0.50");
                 *needs_rebuild = true;
                 self.needs_rebuild = true;
             }
@@ -250,6 +242,20 @@ impl Application for GraphApp {
     fn tick(&mut self, _dt: f32, _needs_rebuild: &mut bool) {}
 
     fn view(&mut self, quads: &mut Vec<(f32, f32, f32, f32, [f32; 4])>, size: LogicalSize, scale: f64) {
+        self.ui_context.clear_popovers();
+        cce_ui::widget::popovers::clear();
+
+        // Register widgets with correct, stable self addresses
+        let menu_ptr = &mut self.menu_bar as *mut MenuBar as *mut (dyn Element + 'static);
+        let graph_ptr = &mut self.graph as *mut Graph as *mut (dyn Element + 'static);
+        self.ui_context.register_widget(self.menu_bar.base.id(), menu_ptr);
+        self.ui_context.register_widget(self.graph_id, graph_ptr);
+
+        if self.menu_bar.popover_rect().is_some() {
+            self.ui_context.register_popover(&self.menu_bar);
+            cce_ui::widget::popovers::register(&self.menu_bar);
+        }
+
         let size_changed = self.width != size.width as u32 || self.height != size.height as u32 || self.scale_factor != scale;
         if self.needs_rebuild || size_changed {
             self.width = size.width as u32;
@@ -264,6 +270,8 @@ impl Application for GraphApp {
             
             self.rebuild_text_items();
             self.needs_rebuild = false;
+
+            self.ui_context.rebuild_spatial_grid();
         }
 
         // 1. Background quad (outer window color)
@@ -292,6 +300,10 @@ impl Application for GraphApp {
         &self.text_items
     }
 
+    fn render_popovers(&self, pc: &mut dyn cce_ui::layout::RenderTarget) {
+        cce_ui::layout::render_popovers(pc, &self.ui_context);
+    }
+
     fn handle_pointer_move(&mut self, pos: LogicalPosition, needs_rebuild: &mut bool) {
         let mut changed = false;
 
@@ -402,7 +414,7 @@ impl Application for GraphApp {
     }
 }
 
-fn load_config() -> (bool, bool, bool, f32, f32, f32) {
+fn load_config() -> (bool, bool, bool, f32, f32) {
     let path = cce_ui::config::get_config_path();
     let content = std::fs::read_to_string(&path).unwrap_or_default();
     let val = cce_ui::config::parse_kdl_to_json(&content);
@@ -410,12 +422,10 @@ fn load_config() -> (bool, bool, bool, f32, f32, f32) {
     let show_grid = val.pointer("/layout/graph_show_grid").and_then(|v| v.as_bool()).unwrap_or(true);
     let snap_enabled = val.pointer("/layout/graph_snap_enabled").and_then(|v| v.as_bool()).unwrap_or(true);
     let uniform_background = val.pointer("/layout/graph_uniform_background").and_then(|v| v.as_bool()).unwrap_or(false);
-    let legacy_opacity = val.pointer("/layout/graph_network_opacity").and_then(|v| v.as_f64()).map(|n| n as f32).unwrap_or(0.95);
-    let cell_opacity = val.pointer("/layout/graph_cell_opacity").and_then(|v| v.as_f64()).map(|n| n as f32).unwrap_or(legacy_opacity);
-    let gap_opacity = val.pointer("/layout/graph_gap_opacity").and_then(|v| v.as_f64()).map(|n| n as f32).unwrap_or(legacy_opacity);
+    let opacity = val.pointer("/layout/graph_network_opacity").and_then(|v| v.as_f64()).map(|n| n as f32).unwrap_or(0.95);
     let gap_width = val.pointer("/layout/graph_gap_width").and_then(|v| v.as_f64()).map(|n| n as f32).unwrap_or(35.0);
     
-    (show_grid, snap_enabled, uniform_background, cell_opacity, gap_opacity, gap_width)
+    (show_grid, snap_enabled, uniform_background, opacity, gap_width)
 }
 
 fn write_config_value(key: &str, value: &str) -> bool {