Persist diagram routing with atomic edits and grouped movement
This commit is contained in:
@@ -36,6 +36,14 @@ pub enum Command {
|
||||
original: Id,
|
||||
node: NodePlacement,
|
||||
},
|
||||
SetEdgeRoute {
|
||||
diagram: Id,
|
||||
route: EdgeRoute,
|
||||
},
|
||||
RemoveEdgeRoute {
|
||||
diagram: Id,
|
||||
edge: Id,
|
||||
},
|
||||
RelocateNode {
|
||||
node: Id,
|
||||
diagram: Id,
|
||||
@@ -559,6 +567,28 @@ fn apply_command(
|
||||
.ok_or_else(missing)? = value.clone();
|
||||
Some(*owner)
|
||||
}
|
||||
Command::SetEdgeRoute { diagram, route } => {
|
||||
let d = p.diagrams.get_mut(diagram).ok_or_else(missing)?;
|
||||
if let Some(existing) = d.routes.iter_mut().find(|r| r.edge == route.edge) {
|
||||
*existing = route.clone();
|
||||
} else {
|
||||
d.routes.push(route.clone());
|
||||
}
|
||||
Some(route.edge)
|
||||
}
|
||||
Command::RemoveEdgeRoute { diagram, edge } => {
|
||||
if !p.relations.contains_key(edge) && !p.traces.contains_key(edge) {
|
||||
return Err(ModelError(
|
||||
"Routing requires an existing relation or trace.".into(),
|
||||
));
|
||||
}
|
||||
p.diagrams
|
||||
.get_mut(diagram)
|
||||
.ok_or_else(missing)?
|
||||
.routes
|
||||
.retain(|route| route.edge != *edge);
|
||||
Some(*edge)
|
||||
}
|
||||
Command::MoveNode {
|
||||
diagram,
|
||||
node,
|
||||
@@ -570,12 +600,19 @@ fn apply_command(
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
let d = p.diagrams.get_mut(diagram).ok_or_else(missing)?;
|
||||
let n = d.nodes.get_mut(node).ok_or_else(missing)?;
|
||||
let d = p.diagrams.get(diagram).ok_or_else(missing)?;
|
||||
let n = d.nodes.get(node).ok_or_else(missing)?;
|
||||
let delta = Position {
|
||||
x: position.x - n.position.x,
|
||||
y: position.y - n.position.y,
|
||||
};
|
||||
let deltas = std::iter::once(*node)
|
||||
.chain(descendants.iter().copied())
|
||||
.map(|id| (id, delta))
|
||||
.collect();
|
||||
let routes = crate::projection::translated_routes(p, d, &deltas);
|
||||
let d = p.diagrams.get_mut(diagram).unwrap();
|
||||
let n = d.nodes.get_mut(node).unwrap();
|
||||
n.position = *position;
|
||||
for id in descendants {
|
||||
if let Some(child) = d.nodes.get_mut(&id) {
|
||||
@@ -583,6 +620,11 @@ fn apply_command(
|
||||
child.position.y += delta.y;
|
||||
}
|
||||
}
|
||||
for route in routes {
|
||||
if let Some(existing) = d.routes.iter_mut().find(|r| r.edge == route.edge) {
|
||||
*existing = route;
|
||||
}
|
||||
}
|
||||
Some(*node)
|
||||
}
|
||||
Command::Layout(diagram) => {
|
||||
@@ -817,11 +859,30 @@ fn layout(p: &mut Project, diagram: Id) -> Result<(), ModelError> {
|
||||
x += sizes[id].width + 240.;
|
||||
row_height = row_height.max(sizes[id].height);
|
||||
}
|
||||
let deltas = positions
|
||||
.iter()
|
||||
.map(|(id, position)| {
|
||||
let original = d.nodes[id].position;
|
||||
(
|
||||
*id,
|
||||
Position {
|
||||
x: position.x - original.x,
|
||||
y: position.y - original.y,
|
||||
},
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
let routes = crate::projection::translated_routes(p, d, &deltas);
|
||||
let d = p.diagrams.get_mut(&diagram).unwrap();
|
||||
for (id, position) in positions {
|
||||
let n = d.nodes.get_mut(&id).unwrap();
|
||||
n.position = position;
|
||||
n.size = sizes[&id];
|
||||
}
|
||||
for route in routes {
|
||||
if let Some(existing) = d.routes.iter_mut().find(|r| r.edge == route.edge) {
|
||||
*existing = route;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user