flow_rs_core/graph/
drag_operations.rs1use std::collections::HashSet;
4
5use crate::error::{FlowError, Result};
6use crate::types::{NodeId, Position, Rect};
7
8use super::{Graph, Node};
9
10impl<N, E> Graph<N, E> {
11 pub fn apply_node_drag(
13 &mut self,
14 selected_nodes: &HashSet<NodeId>,
15 delta: Position,
16 ) -> Result<()> {
17 self.apply_node_drag_with_transform(selected_nodes, delta, |pos, _| pos)
18 }
19
20 pub fn apply_node_drag_with_bounds(
22 &mut self,
23 selected_nodes: &HashSet<NodeId>,
24 delta: Position,
25 bounds: Option<Rect>,
26 ) -> Result<()> {
27 self.apply_node_drag_with_transform(selected_nodes, delta, |new_pos, node| {
28 if let Some(bounds) = bounds {
29 Position::new(
30 new_pos
31 .x
32 .max(bounds.x)
33 .min(bounds.x + bounds.width - node.size.width),
34 new_pos
35 .y
36 .max(bounds.y)
37 .min(bounds.y + bounds.height - node.size.height),
38 )
39 } else {
40 new_pos
41 }
42 })
43 }
44
45 pub fn apply_node_drag_with_snap(
47 &mut self,
48 selected_nodes: &HashSet<NodeId>,
49 delta: Position,
50 grid_size: f64,
51 ) -> Result<()> {
52 self.apply_node_drag_with_transform(selected_nodes, delta, |new_pos, _| {
53 Position::new(
54 (new_pos.x / grid_size).round() * grid_size,
55 (new_pos.y / grid_size).round() * grid_size,
56 )
57 })
58 }
59
60 pub fn apply_node_drag_with_constraint<F>(
62 &mut self,
63 selected_nodes: &HashSet<NodeId>,
64 delta: Position,
65 constraint: F,
66 ) -> Result<()>
67 where
68 F: Fn(Position) -> Position,
69 {
70 self.apply_node_drag_with_transform(selected_nodes, delta, |new_pos, _| constraint(new_pos))
71 }
72
73 fn apply_node_drag_with_transform<F>(
75 &mut self,
76 selected_nodes: &HashSet<NodeId>,
77 delta: Position,
78 transform: F,
79 ) -> Result<()>
80 where
81 F: Fn(Position, &Node<N>) -> Position,
82 {
83 for node_id in selected_nodes {
85 if !self.nodes.contains_key(node_id) {
86 return Err(FlowError::node_not_found(node_id.as_str()));
87 }
88 }
89
90 for node_id in selected_nodes {
92 if let Some(node) = self.get_node_mut(node_id) {
93 let new_pos = Position::new(node.position.x + delta.x, node.position.y + delta.y);
94 node.position = transform(new_pos, node);
95 }
96 }
97
98 Ok(())
99 }
100
101 pub fn create_drag_operation(
103 &self,
104 selected_nodes: &HashSet<NodeId>,
105 delta: Position,
106 ) -> Result<crate::drag_operations::DragOperation> {
107 for node_id in selected_nodes {
109 if !self.nodes.contains_key(node_id) {
110 return Err(FlowError::node_not_found(node_id.as_str()));
111 }
112 }
113
114 Ok(crate::drag_operations::DragOperation::new(
115 selected_nodes.clone(),
116 delta,
117 ))
118 }
119}