Files
ARCADIA-Studio/crates/oa-desktop/src/route_edit.rs
T

110 lines
2.9 KiB
Rust

//! Transient connection gestures. Only their final route enters model history.
use iced::Point;
use oa_core::{routing::*, *};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Context {
pub document: Id,
pub diagram: Id,
pub revision: u64,
pub epoch: u64,
}
#[derive(Debug, Clone)]
pub enum Event {
SelectBend(Id, usize),
Commit(Context, EdgeRoute, Option<usize>),
AddBend,
AddBendAt(oa_core::Position),
RemoveBend,
Reset,
}
#[derive(Debug, Clone)]
pub enum Handle {
Bend(usize),
Label { original: Position },
}
#[derive(Debug, Clone)]
pub struct Gesture {
pub context: Context,
pub start: Point,
pub handle: Handle,
pub route: EdgeRoute,
pub changed: bool,
pub baseline: std::sync::Arc<RoutedView>,
}
impl Gesture {
pub fn move_to(&mut self, point: Point, zoom: f32) {
let delta = point - self.start;
if !self.changed && (delta.x * delta.x + delta.y * delta.y) * zoom * zoom < 9. {
return;
}
self.changed = true;
match self.handle {
Handle::Bend(index) => {
self.route.waypoints[index] = Position {
x: (point.x / 5.).round() * 5.,
y: (point.y / 5.).round() * 5.,
}
}
Handle::Label { original } => {
if let Some(label) = &mut self.route.label {
label.offset = Position {
x: original.x + delta.x,
y: original.y + delta.y,
};
}
}
}
}
}
pub fn stored_route(diagram: &Diagram, edge: Id) -> EdgeRoute {
diagram
.routes
.iter()
.find(|r| r.edge == edge)
.cloned()
.unwrap_or(EdgeRoute {
edge,
waypoints: Vec::new(),
label: None,
})
}
/// Insert after the pins preceding the clicked segment along the routed path.
pub fn insert_pin(route: &mut EdgeRoute, geometry: &RoutedEdge, point: Position) -> usize {
let segment = geometry
.points
.windows(2)
.enumerate()
.min_by(|(_, a), (_, b)| {
let distance = |span: &[Position]| {
project_onto_polyline(span, point).map_or(f32::INFINITY, |p| p.distance)
};
distance(a).total_cmp(&distance(b))
})
.map_or(0, |(index, _)| index);
let index = pin_insertion_index(geometry, segment, point);
route.waypoints.insert(index, point);
index
}
pub fn with_route(diagram: &mut Diagram, route: EdgeRoute) {
if let Some(existing) = diagram.routes.iter_mut().find(|r| r.edge == route.edge) {
*existing = route;
} else {
diagram.routes.push(route);
}
}
pub fn point(p: Position) -> Point {
Point::new(p.x, p.y)
}
pub fn position(p: Point) -> Position {
Position { x: p.x, y: p.y }
}