110 lines
2.9 KiB
Rust
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 }
|
|
}
|