1#[cfg(feature = "serde")]
4use serde::{Deserialize, Serialize};
5
6use crate::error::{FlowError, Result};
7use crate::types::{EdgeId, NodeId};
8
9#[derive(Debug, Clone, PartialEq)]
11#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12pub struct Edge<T = ()> {
13 pub id: EdgeId,
14 pub source: NodeId,
15 pub target: NodeId,
16 pub data: T,
17
18 pub source_handle: Option<String>,
20 pub target_handle: Option<String>,
21 pub edge_type: Option<String>,
22 pub selected: bool,
23 pub animated: bool,
24 pub hidden: bool,
25 pub selectable: bool,
26 pub deletable: bool,
27 pub z_index: Option<i32>,
28 pub label: Option<String>,
29}
30
31impl<T> Edge<T> {
32 pub fn new(
34 id: impl Into<EdgeId>,
35 source: impl Into<NodeId>,
36 target: impl Into<NodeId>,
37 data: T,
38 ) -> Self {
39 Self {
40 id: id.into(),
41 source: source.into(),
42 target: target.into(),
43 data,
44 source_handle: None,
45 target_handle: None,
46 edge_type: None,
47 selected: false,
48 animated: false,
49 hidden: false,
50 selectable: true,
51 deletable: true,
52 z_index: None,
53 label: None,
54 }
55 }
56
57 pub fn builder() -> EdgeBuilder<T> {
59 EdgeBuilder::new()
60 }
61
62 pub fn set_selected(&mut self, selected: bool) {
64 self.selected = selected;
65 }
66
67 pub fn connects(&self, source_id: &NodeId, target_id: &NodeId) -> bool {
69 &self.source == source_id && &self.target == target_id
70 }
71
72 pub fn is_connected_to(&self, node_id: &NodeId) -> bool {
74 &self.source == node_id || &self.target == node_id
75 }
76
77 pub fn map_data<U>(self, f: impl FnOnce(T) -> U) -> Edge<U> {
79 Edge {
80 id: self.id,
81 source: self.source,
82 target: self.target,
83 data: f(self.data),
84 source_handle: self.source_handle,
85 target_handle: self.target_handle,
86 edge_type: self.edge_type,
87 selected: self.selected,
88 animated: self.animated,
89 hidden: self.hidden,
90 selectable: self.selectable,
91 deletable: self.deletable,
92 z_index: self.z_index,
93 label: self.label,
94 }
95 }
96
97 pub fn with_source_handle(mut self, handle_id: impl Into<String>) -> Self {
99 self.source_handle = Some(handle_id.into());
100 self
101 }
102
103 pub fn with_target_handle(mut self, handle_id: impl Into<String>) -> Self {
105 self.target_handle = Some(handle_id.into());
106 self
107 }
108}
109
110impl Edge<()> {
111 pub fn simple(
113 id: impl Into<EdgeId>,
114 source: impl Into<NodeId>,
115 target: impl Into<NodeId>,
116 ) -> Self {
117 Self::new(id, source, target, ())
118 }
119}
120
121impl<T: Default> Edge<T> {
122 pub fn with_default_data(
124 id: impl Into<EdgeId>,
125 source: impl Into<NodeId>,
126 target: impl Into<NodeId>,
127 ) -> Self {
128 Self::new(id, source, target, T::default())
129 }
130}
131
132#[derive(Debug)]
134pub struct EdgeBuilder<T> {
135 id: Option<EdgeId>,
136 source: Option<NodeId>,
137 target: Option<NodeId>,
138 data: Option<T>,
139 source_handle: Option<String>,
140 target_handle: Option<String>,
141 edge_type: Option<String>,
142 selected: bool,
143 animated: bool,
144 hidden: bool,
145 selectable: bool,
146 deletable: bool,
147 z_index: Option<i32>,
148 label: Option<String>,
149}
150
151impl<T> EdgeBuilder<T> {
152 pub fn new() -> Self {
154 Self {
155 id: None,
156 source: None,
157 target: None,
158 data: None,
159 source_handle: None,
160 target_handle: None,
161 edge_type: None,
162 selected: false,
163 animated: false,
164 hidden: false,
165 selectable: true,
166 deletable: true,
167 z_index: None,
168 label: None,
169 }
170 }
171
172 pub fn id(mut self, id: impl Into<EdgeId>) -> Self {
174 self.id = Some(id.into());
175 self
176 }
177
178 pub fn connect(mut self, source: impl Into<NodeId>, target: impl Into<NodeId>) -> Self {
180 self.source = Some(source.into());
181 self.target = Some(target.into());
182 self
183 }
184
185 pub fn connect_handles(
187 mut self,
188 source: impl Into<NodeId>,
189 source_handle: impl Into<String>,
190 target: impl Into<NodeId>,
191 target_handle: impl Into<String>,
192 ) -> Self {
193 self.source = Some(source.into());
194 self.target = Some(target.into());
195 self.source_handle = Some(source_handle.into());
196 self.target_handle = Some(target_handle.into());
197 self
198 }
199
200 pub fn data(mut self, data: T) -> Self {
202 self.data = Some(data);
203 self
204 }
205
206 pub fn edge_type(mut self, edge_type: impl Into<String>) -> Self {
208 self.edge_type = Some(edge_type.into());
209 self
210 }
211
212 pub fn animated(mut self, animated: bool) -> Self {
214 self.animated = animated;
215 self
216 }
217
218 pub fn label(mut self, label: impl Into<String>) -> Self {
220 self.label = Some(label.into());
221 self
222 }
223
224 pub fn build(self) -> Result<Edge<T>>
226 where
227 T: Default,
228 {
229 let id = self.id.unwrap_or_else(EdgeId::generate);
230 let source = self
231 .source
232 .ok_or_else(|| FlowError::invalid_connection("Source node not specified"))?;
233 let target = self
234 .target
235 .ok_or_else(|| FlowError::invalid_connection("Target node not specified"))?;
236 let data = self.data.unwrap_or_default();
237
238 if source == target {
239 return Err(FlowError::SelfConnection);
240 }
241
242 Ok(Edge {
243 id,
244 source,
245 target,
246 data,
247 source_handle: self.source_handle,
248 target_handle: self.target_handle,
249 edge_type: self.edge_type,
250 selected: self.selected,
251 animated: self.animated,
252 hidden: self.hidden,
253 selectable: self.selectable,
254 deletable: self.deletable,
255 z_index: self.z_index,
256 label: self.label,
257 })
258 }
259
260 pub fn build_with_data(self, data: T) -> Result<Edge<T>> {
262 let id = self.id.unwrap_or_else(EdgeId::generate);
263 let source = self
264 .source
265 .ok_or_else(|| FlowError::invalid_connection("Source node not specified"))?;
266 let target = self
267 .target
268 .ok_or_else(|| FlowError::invalid_connection("Target node not specified"))?;
269
270 if source == target {
271 return Err(FlowError::SelfConnection);
272 }
273
274 Ok(Edge {
275 id,
276 source,
277 target,
278 data,
279 source_handle: self.source_handle,
280 target_handle: self.target_handle,
281 edge_type: self.edge_type,
282 selected: self.selected,
283 animated: self.animated,
284 hidden: self.hidden,
285 selectable: self.selectable,
286 deletable: self.deletable,
287 z_index: self.z_index,
288 label: self.label,
289 })
290 }
291}
292
293impl<T> Default for EdgeBuilder<T> {
294 fn default() -> Self {
295 Self::new()
296 }
297}