flow_rs_core/graph/
node.rs

1//! Node data structure and builder pattern
2
3#[cfg(feature = "serde")]
4use serde::{Deserialize, Serialize};
5
6use crate::error::Result;
7use crate::handle::{Handle, HandleId, HandleManager};
8use crate::types::{NodeId, Position, Rect, Size};
9
10/// Node in a flow graph
11#[derive(Debug, Clone, PartialEq)]
12#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
13pub struct Node<T = ()> {
14    pub id: NodeId,
15    pub position: Position,
16    pub size: Size,
17    pub data: T,
18
19    // Optional properties
20    pub node_type: Option<String>,
21    pub selected: bool,
22    pub dragging: bool,
23    pub selectable: bool,
24    pub connectable: bool,
25    pub deletable: bool,
26    pub drag_handle: Option<String>,
27    pub parent_node: Option<NodeId>,
28    pub z_index: Option<i32>,
29    pub hidden: bool,
30
31    // Computed properties (not serialized)
32    #[cfg_attr(feature = "serde", serde(skip))]
33    pub measured: Option<Size>,
34
35    // Handle management
36    #[cfg_attr(feature = "serde", serde(skip))]
37    handle_manager: HandleManager,
38}
39
40impl<T: Clone> Node<T> {
41    /// Create a new node
42    pub fn new(id: impl Into<NodeId>, position: Position, data: T) -> Self {
43        let node_id = id.into();
44        Self {
45            id: node_id.clone(),
46            position,
47            size: Size::default(),
48            data,
49            node_type: None,
50            selected: false,
51            dragging: false,
52            selectable: true,
53            connectable: true,
54            deletable: true,
55            drag_handle: None,
56            parent_node: None,
57            z_index: None,
58            hidden: false,
59            measured: None,
60            handle_manager: HandleManager::new(node_id),
61        }
62    }
63
64    /// Create a builder for fluent construction
65    pub fn builder(id: impl Into<NodeId>) -> NodeBuilder<T>
66    where
67        T: Default,
68    {
69        NodeBuilder::new(id)
70    }
71
72    /// Get the bounding rectangle
73    pub fn bounds(&self) -> Rect {
74        Rect::from_pos_size(self.position, self.size)
75    }
76
77    /// Get the center position
78    pub fn center(&self) -> Position {
79        self.bounds().center()
80    }
81
82    /// Check if point is inside the node
83    pub fn contains_point(&self, point: Position) -> bool {
84        self.bounds().contains_point(point)
85    }
86
87    /// Update position
88    pub fn set_position(&mut self, position: Position) {
89        self.position = position;
90    }
91
92    /// Update size
93    pub fn set_size(&mut self, size: Size) {
94        self.size = size;
95    }
96
97    /// Set selection state
98    pub fn set_selected(&mut self, selected: bool) {
99        self.selected = selected;
100    }
101
102    /// Set dragging state
103    pub fn set_dragging(&mut self, dragging: bool) {
104        self.dragging = dragging;
105    }
106
107    /// Convert to a different data type
108    pub fn map_data<U>(self, f: impl FnOnce(T) -> U) -> Node<U> {
109        Node {
110            id: self.id.clone(),
111            position: self.position,
112            size: self.size,
113            data: f(self.data),
114            node_type: self.node_type,
115            selected: self.selected,
116            dragging: self.dragging,
117            selectable: self.selectable,
118            connectable: self.connectable,
119            deletable: self.deletable,
120            drag_handle: self.drag_handle,
121            parent_node: self.parent_node,
122            z_index: self.z_index,
123            hidden: self.hidden,
124            measured: self.measured,
125            handle_manager: HandleManager::new(self.id),
126        }
127    }
128}
129
130impl<T> Node<T> {
131    /// Add a handle to this node
132    pub fn add_handle(&mut self, handle: Handle) -> Result<()> {
133        self.handle_manager.add_handle(handle)
134    }
135
136    /// Remove a handle from this node
137    pub fn remove_handle(&mut self, handle_id: &HandleId) -> Result<Handle> {
138        self.handle_manager.remove_handle(handle_id)
139    }
140
141    /// Get a handle by ID
142    pub fn get_handle(&self, handle_id: &HandleId) -> Option<&Handle> {
143        self.handle_manager.get_handle(handle_id)
144    }
145
146    /// Get all handles on this node
147    pub fn handles(&self) -> &[Handle] {
148        self.handle_manager.handles()
149    }
150
151    /// Find handle at position relative to this node
152    pub fn handle_at_position(&self, point: Position, handle_size: f64) -> Option<&Handle> {
153        self.handle_manager
154            .handle_at_position(point, self.position, self.size, handle_size)
155    }
156
157    /// Get source handles
158    pub fn source_handles(&self) -> impl Iterator<Item = &Handle> {
159        self.handle_manager.source_handles()
160    }
161
162    /// Get target handles
163    pub fn target_handles(&self) -> impl Iterator<Item = &Handle> {
164        self.handle_manager.target_handles()
165    }
166}
167
168impl Node<()> {
169    /// Create a simple node with default data
170    pub fn simple(id: impl Into<NodeId>, position: Position) -> Self {
171        Self::new(id, position, ())
172    }
173}
174
175impl<T: Default> Node<T> {
176    /// Create a node with default data
177    pub fn with_default_data(id: impl Into<NodeId>, position: Position) -> Self
178    where
179        T: Default + Clone,
180    {
181        Self::new(id, position, T::default())
182    }
183}
184
185/// Builder for fluent node construction
186#[derive(Debug)]
187pub struct NodeBuilder<T> {
188    node: Node<T>,
189}
190
191impl<T: Default + Clone> NodeBuilder<T> {
192    /// Create a new node builder
193    pub fn new(id: impl Into<NodeId>) -> Self {
194        Self {
195            node: Node::new(id, Position::zero(), T::default()),
196        }
197    }
198}
199
200impl<T: Clone> NodeBuilder<T> {
201    /// Create a builder with specific data
202    pub fn with_data(id: impl Into<NodeId>, data: T) -> Self {
203        Self {
204            node: Node::new(id, Position::zero(), data),
205        }
206    }
207
208    /// Set position
209    pub fn position(mut self, x: f64, y: f64) -> Self {
210        self.node.position = Position::new(x, y);
211        self
212    }
213
214    /// Set position from Position
215    pub fn at(mut self, position: Position) -> Self {
216        self.node.position = position;
217        self
218    }
219
220    /// Set size
221    pub fn size(mut self, width: f64, height: f64) -> Self {
222        self.node.size = Size::new(width, height);
223        self
224    }
225
226    /// Set size from Size
227    pub fn with_size(mut self, size: Size) -> Self {
228        self.node.size = size;
229        self
230    }
231
232    /// Set node type
233    pub fn node_type(mut self, node_type: impl Into<String>) -> Self {
234        self.node.node_type = Some(node_type.into());
235        self
236    }
237
238    /// Set selectable flag
239    pub fn selectable(mut self, selectable: bool) -> Self {
240        self.node.selectable = selectable;
241        self
242    }
243
244    /// Set connectable flag
245    pub fn connectable(mut self, connectable: bool) -> Self {
246        self.node.connectable = connectable;
247        self
248    }
249
250    /// Set deletable flag
251    pub fn deletable(mut self, deletable: bool) -> Self {
252        self.node.deletable = deletable;
253        self
254    }
255
256    /// Set drag handle
257    pub fn drag_handle(mut self, handle: impl Into<String>) -> Self {
258        self.node.drag_handle = Some(handle.into());
259        self
260    }
261
262    /// Set parent node
263    pub fn parent(mut self, parent_id: impl Into<NodeId>) -> Self {
264        self.node.parent_node = Some(parent_id.into());
265        self
266    }
267
268    /// Set z-index
269    pub fn z_index(mut self, z_index: i32) -> Self {
270        self.node.z_index = Some(z_index);
271        self
272    }
273
274    /// Set hidden flag
275    pub fn hidden(mut self, hidden: bool) -> Self {
276        self.node.hidden = hidden;
277        self
278    }
279
280    /// Build the node
281    pub fn build(self) -> Node<T> {
282        self.node
283    }
284}