flow_rs_core/graph/
mod.rs1use std::collections::HashMap;
4use std::marker::PhantomData;
5
6#[cfg(feature = "serde")]
7use serde::{Deserialize, Serialize};
8
9use crate::error::{FlowError, Result};
10use crate::handle::Handle;
11use crate::types::{EdgeId, NodeId, Position, Rect};
12
13pub mod drag_operations;
14pub mod edge;
15pub mod node;
16pub mod traversal;
17pub mod validation;
18
19pub use edge::{Edge, EdgeBuilder};
20pub use node::{Node, NodeBuilder};
21
22#[derive(Debug, Clone, PartialEq)]
24#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
25pub struct Graph<N = (), E = ()> {
26 pub(crate) nodes: HashMap<NodeId, Node<N>>,
27 pub(crate) edges: HashMap<EdgeId, Edge<E>>,
28
29 #[cfg_attr(feature = "serde", serde(skip))]
30 _phantom: PhantomData<(N, E)>,
31}
32
33impl<N, E> Graph<N, E> {
34 pub fn new() -> Self {
36 Self {
37 nodes: HashMap::new(),
38 edges: HashMap::new(),
39 _phantom: PhantomData,
40 }
41 }
42
43 pub fn add_node(&mut self, node: Node<N>) -> Result<()> {
45 if self.nodes.contains_key(&node.id) {
46 return Err(FlowError::duplicate_node_id(node.id.as_str()));
47 }
48
49 self.nodes.insert(node.id.clone(), node);
50 Ok(())
51 }
52
53 pub fn remove_node(&mut self, node_id: &NodeId) -> Result<Node<N>> {
55 let node = self
56 .nodes
57 .remove(node_id)
58 .ok_or_else(|| FlowError::node_not_found(node_id.as_str()))?;
59
60 self.edges.retain(|_, edge| !edge.is_connected_to(node_id));
62
63 Ok(node)
64 }
65
66 pub fn get_node(&self, node_id: &NodeId) -> Option<&Node<N>> {
68 self.nodes.get(node_id)
69 }
70
71 pub fn get_node_mut(&mut self, node_id: &NodeId) -> Option<&mut Node<N>> {
73 self.nodes.get_mut(node_id)
74 }
75
76 pub fn add_edge(&mut self, edge: Edge<E>) -> Result<()> {
78 if !self.nodes.contains_key(&edge.source) {
80 return Err(FlowError::node_not_found(edge.source.as_str()));
81 }
82 if !self.nodes.contains_key(&edge.target) {
83 return Err(FlowError::node_not_found(edge.target.as_str()));
84 }
85
86 if self.edges.contains_key(&edge.id) {
87 return Err(FlowError::duplicate_edge_id(edge.id.as_str()));
88 }
89
90 self.edges.insert(edge.id.clone(), edge);
91 Ok(())
92 }
93
94 pub fn remove_edge(&mut self, edge_id: &EdgeId) -> Result<Edge<E>> {
96 self.edges
97 .remove(edge_id)
98 .ok_or_else(|| FlowError::edge_not_found(edge_id.as_str()))
99 }
100
101 pub fn get_edge(&self, edge_id: &EdgeId) -> Option<&Edge<E>> {
103 self.edges.get(edge_id)
104 }
105
106 pub fn get_edge_mut(&mut self, edge_id: &EdgeId) -> Option<&mut Edge<E>> {
108 self.edges.get_mut(edge_id)
109 }
110
111 pub fn nodes(&self) -> impl Iterator<Item = &Node<N>> {
113 self.nodes.values()
114 }
115
116 pub fn nodes_mut(&mut self) -> impl Iterator<Item = &mut Node<N>> {
118 self.nodes.values_mut()
119 }
120
121 pub fn edges(&self) -> impl Iterator<Item = &Edge<E>> {
123 self.edges.values()
124 }
125
126 pub fn edges_mut(&mut self) -> impl Iterator<Item = &mut Edge<E>> {
128 self.edges.values_mut()
129 }
130
131 pub fn node_count(&self) -> usize {
133 self.nodes.len()
134 }
135
136 pub fn edge_count(&self) -> usize {
138 self.edges.len()
139 }
140
141 pub fn is_empty(&self) -> bool {
143 self.nodes.is_empty()
144 }
145
146 pub fn clear(&mut self) {
148 self.nodes.clear();
149 self.edges.clear();
150 }
151
152 pub fn get_connected_edges(&self, node_id: &NodeId) -> Vec<&Edge<E>> {
154 self.edges
155 .values()
156 .filter(|edge| edge.is_connected_to(node_id))
157 .collect()
158 }
159
160 pub fn get_incoming_edges(&self, node_id: &NodeId) -> Vec<&Edge<E>> {
162 self.edges
163 .values()
164 .filter(|edge| &edge.target == node_id)
165 .collect()
166 }
167
168 pub fn get_outgoing_edges(&self, node_id: &NodeId) -> Vec<&Edge<E>> {
170 self.edges
171 .values()
172 .filter(|edge| &edge.source == node_id)
173 .collect()
174 }
175
176 pub fn are_connected(&self, source: &NodeId, target: &NodeId) -> bool {
178 self.edges
179 .values()
180 .any(|edge| edge.connects(source, target))
181 }
182
183 pub fn node_ids(&self) -> impl Iterator<Item = &NodeId> {
185 self.nodes.keys()
186 }
187
188 pub fn edge_ids(&self) -> impl Iterator<Item = &EdgeId> {
190 self.edges.keys()
191 }
192
193 pub fn bounds(&self) -> Option<Rect>
195 where
196 N: Clone,
197 {
198 if self.nodes.is_empty() {
199 return None;
200 }
201
202 let mut min_x = f64::INFINITY;
203 let mut min_y = f64::INFINITY;
204 let mut max_x = f64::NEG_INFINITY;
205 let mut max_y = f64::NEG_INFINITY;
206
207 for node in self.nodes.values() {
208 let bounds = node.bounds();
209 min_x = min_x.min(bounds.x);
210 min_y = min_y.min(bounds.y);
211 max_x = max_x.max(bounds.x + bounds.width);
212 max_y = max_y.max(bounds.y + bounds.height);
213 }
214
215 Some(Rect::new(min_x, min_y, max_x - min_x, max_y - min_y))
216 }
217
218 pub fn handle_at_position(
220 &self,
221 point: Position,
222 handle_size: f64,
223 ) -> Option<(&NodeId, &Handle)> {
224 for node in self.nodes.values() {
225 if let Some(handle) = node.handle_at_position(point, handle_size) {
226 return Some((&node.id, handle));
227 }
228 }
229 None
230 }
231
232 pub fn get_handles_by_type(
234 &self,
235 handle_type: crate::handle::HandleType,
236 ) -> Vec<(&NodeId, &Handle)> {
237 let mut handles = Vec::new();
238 for node in self.nodes.values() {
239 for handle in node.handles() {
240 if handle.handle_type == handle_type {
241 handles.push((&node.id, handle));
242 }
243 }
244 }
245 handles
246 }
247
248 pub fn create_edge_creator(&self) -> crate::edge_creator::EdgeCreator {
250 crate::edge_creator::EdgeCreator::new()
251 }
252}
253
254impl<N, E> Default for Graph<N, E> {
255 fn default() -> Self {
256 Self::new()
257 }
258}
259
260#[cfg(test)]
263mod tests;