GPU-accelerated UI toolkit (Vulkan)
git clone https://git.lucas.co/cce-ui.git
feat: GraphController::node_at — topmost node under a point
node_at(px, py) hit-tests window-absolute coords against node_rect in
reverse draw order, for hosts that intercept a press before the graph
widget sees it (the designer's right-click node menu).
Co-Authored-By: Claude Fable 5 <[email protected]>
src/widget/container/content_bg.rs | 1 +
src/widget/display/graph.rs | 17 +++++++++++++++++
src/widget/mod.rs | 4 ++++
3 files changed, 22 insertions(+)
diff --git a/src/widget/container/content_bg.rs b/src/widget/container/content_bg.rs
index 1f61832..bc84800 100644
--- a/src/widget/container/content_bg.rs
+++ b/src/widget/container/content_bg.rs
@@ -269,4 +269,5 @@ impl GraphController for ContentBg {
fn take_pending_connection(&mut self) -> Option<(String, String)> { None }
fn cancel_connecting(&mut self) {}
fn is_node_rect(&self, _qx: f32, _qy: f32, _qw: f32, _qh: f32) -> bool { false }
+ fn node_at(&self, _px: f32, _py: f32) -> Option<usize> { None }
}
diff --git a/src/widget/display/graph.rs b/src/widget/display/graph.rs
index 079dcca..981e8ad 100644
--- a/src/widget/display/graph.rs
+++ b/src/widget/display/graph.rs
@@ -188,6 +188,20 @@ impl Graph {
false
}
+ /// The topmost node whose body contains (px, py), in the same
+ /// window-absolute space `node_rect` reports (grid_origin = pane + pan).
+ /// Reverse order so a later-drawn node wins where bodies overlap.
+ pub fn node_at(&self, px: f32, py: f32) -> Option<usize> {
+ for i in (0..self.nodes.len()).rev() {
+ if let Some((nx, ny, nw, nh)) = self.node_rect(i) {
+ if px >= nx && px < nx + nw && py >= ny && py < ny + nh {
+ return Some(i);
+ }
+ }
+ }
+ None
+ }
+
/// How far a port's center floats off its node edge: the connector's own
/// radius plus a small gap, so the circle sits fully OUTSIDE the node's
/// bounding box rather than straddling its border.
@@ -1012,6 +1026,9 @@ impl GraphController for Graph {
fn is_node_rect(&self, qx: f32, qy: f32, qw: f32, qh: f32) -> bool {
self.is_node_rect(qx, qy, qw, qh)
}
+ fn node_at(&self, px: f32, py: f32) -> Option<usize> {
+ self.node_at(px, py)
+ }
}
#[cfg(test)]
diff --git a/src/widget/mod.rs b/src/widget/mod.rs
index 1241ace..68c7153 100644
--- a/src/widget/mod.rs
+++ b/src/widget/mod.rs
@@ -92,6 +92,8 @@ pub enum ContextAction {
CollapseNode,
ExpandAll,
CollapseAll,
+ /// Ramp: hide/show the bottom control strip, the graph claiming the space.
+ ToggleRampControls,
}
use crate::colors;
@@ -580,6 +582,8 @@ pub trait GraphController {
fn take_pending_connection(&mut self) -> Option<(String, String)>;
fn cancel_connecting(&mut self);
fn is_node_rect(&self, qx: f32, qy: f32, qw: f32, qh: f32) -> bool;
+ /// The topmost node whose body contains (px, py), window-absolute coords.
+ fn node_at(&self, px: f32, py: f32) -> Option<usize>;
}
pub trait SpreadsheetController {