use crate::graph::node_position::snap_position;
use crate::types::changes::NodeChange;
use crate::types::node::{InternalNode, NodeId};
use crate::types::position::Transform;
use std::collections::HashMap;
pub(crate) fn handle_node_drag<D>(
node_id: &NodeId,
drag_delta: egui::Vec2,
transform: &Transform,
snap_to_grid: bool,
snap_grid: &[f32; 2],
current_pos: egui::Pos2,
) -> Option<NodeChange<D>> {
if drag_delta == egui::Vec2::ZERO {
return None;
}
let flow_delta = egui::vec2(
drag_delta.x / transform.scale,
drag_delta.y / transform.scale,
);
let mut new_pos = egui::pos2(current_pos.x + flow_delta.x, current_pos.y + flow_delta.y);
if snap_to_grid {
new_pos = snap_position(new_pos, snap_grid);
}
Some(NodeChange::Position {
id: node_id.clone(),
position: Some(new_pos),
dragging: Some(true),
})
}
pub(crate) fn handle_multi_node_drag<D>(
primary_id: &NodeId,
drag_delta: egui::Vec2,
transform: &Transform,
snap_to_grid: bool,
snap_grid: &[f32; 2],
node_lookup: &HashMap<NodeId, InternalNode<D>>,
) -> Vec<NodeChange<D>> {
if drag_delta == egui::Vec2::ZERO {
return Vec::new();
}
let primary_selected = node_lookup
.get(primary_id)
.map(|n| n.node.selected)
.unwrap_or(false);
if !primary_selected {
return Vec::new();
}
let selected: Vec<(&NodeId, egui::Pos2)> = node_lookup
.iter()
.filter(|(_, n)| n.node.selected && !n.node.hidden)
.map(|(id, n)| (id, n.internals.position_absolute))
.collect();
if selected.is_empty() {
return Vec::new();
}
let flow_delta = egui::vec2(
drag_delta.x / transform.scale,
drag_delta.y / transform.scale,
);
selected
.into_iter()
.filter_map(|(id, flow_pos)| {
let can_drag = node_lookup
.get(id)
.and_then(|n| n.node.draggable)
.unwrap_or(true);
if !can_drag {
return None;
}
let mut new_pos = egui::pos2(flow_pos.x + flow_delta.x, flow_pos.y + flow_delta.y);
if snap_to_grid {
new_pos = snap_position(new_pos, snap_grid);
}
Some(NodeChange::Position {
id: id.clone(),
position: Some(new_pos),
dragging: Some(true),
})
})
.collect()
}
pub(crate) fn handle_multi_node_drag_end<D>(
node_lookup: &HashMap<NodeId, InternalNode<D>>,
) -> Vec<NodeChange<D>> {
node_lookup
.iter()
.filter(|(_, n)| n.node.dragging)
.map(|(id, _)| NodeChange::Position {
id: id.clone(),
position: None,
dragging: Some(false),
})
.collect()
}