Support per-view connection boundary attachments in ordinary and state diagrams

This commit is contained in:
2026-09-22 17:51:13 -07:00
parent 3f9e6a18af
commit 79cc9d5551
49 changed files with 3534 additions and 52 deletions
+62 -1
View File
@@ -14,6 +14,9 @@ pub struct Context {
pub enum Event {
SelectBend(Id, usize),
Commit(Context, EdgeRoute, Option<usize>),
CommitAttachment(Context, EdgeRoute, EdgeEnd, Id),
ChooseAttachment(EdgeEnd),
ResetAttachment(EdgeEnd),
AddBend,
AddBendAt(oa_core::Position),
RemoveBend,
@@ -23,7 +26,14 @@ pub enum Event {
#[derive(Debug, Clone)]
pub enum Handle {
Bend(usize),
Label { original: Position },
Label {
original: Position,
},
Attachment {
end: EdgeEnd,
owner: projection::ProjectedNode,
original: Option<EdgeAttachment>,
},
}
#[derive(Debug, Clone)]
@@ -58,8 +68,57 @@ impl Gesture {
};
}
}
Handle::Attachment { .. } => {}
}
}
pub fn move_attachment_to(&mut self, point: Point, zoom: f32) {
let Handle::Attachment {
end,
ref owner,
original,
} = self.handle
else {
self.move_to(point, zoom);
return;
};
if point.distance(self.start) * zoom < 3. {
self.route.set_attachment(end, original);
self.changed = false;
return;
}
self.changed = true;
let attachment = attachment_from_point(
owner,
position(point),
self.route.attachment(end).map(|a| a.side),
6. / zoom,
);
self.route.set_attachment(end, Some(attachment));
}
}
/// The painted endpoint must still be the actual unported placement, not a folded proxy.
pub fn attachment_node<'a>(
project: &Project,
diagram: &Diagram,
view: &'a projection::ProjectedView,
edge: Id,
end: EdgeEnd,
) -> Option<&'a projection::ProjectedNode> {
if semantic_port_endpoint(project, edge, end).is_some() {
return None;
}
let projected = view.edges.iter().find(|e| e.id == edge)?;
let actual = projection::edge_endpoint_placements(project, diagram, edge)?;
if actual != (projected.source, projected.target) {
return None;
}
let placement = match end {
EdgeEnd::Source => projected.source,
EdgeEnd::Target => projected.target,
};
view.nodes.iter().find(|node| node.id == placement)
}
pub fn stored_route(diagram: &Diagram, edge: Id) -> EdgeRoute {
@@ -72,6 +131,8 @@ pub fn stored_route(diagram: &Diagram, edge: Id) -> EdgeRoute {
edge,
waypoints: Vec::new(),
label: None,
source_attachment: None,
target_attachment: None,
})
}