reroute method
Uses installed route planners and publishes all results as one edit.
Implementation
EditResult reroute({Iterable<String>? connectorIds}) {
if (store.isInteracting) {
return const EditResult.denied(
reason: 'Finish the active edit before rerouting.',
);
}
final publication = store.internals.committedPublication;
final document = publication.state.document;
final scene = publication.scene;
final routes = store.diagram.resolver.registry.routes;
final ids =
connectorIds?.toSet() ??
{
for (final element in document.elements.whereType<ConnectorElement>())
if (routes.capabilitiesOf(element.route).planner != null &&
scene.isVisible(element.id))
element.id,
};
final connectionLabel = ids.length == 1 ? 'connection' : 'connections';
final requests = <ConnectorElement>[];
for (final id in ids.toList()..sort()) {
final resolved = scene.connectorById(id);
if (!scene.isVisible(id) && resolved != null) {
return const EditResult.denied(
reason:
'Expand the containing frame before rerouting this connection.',
);
}
if (resolved == null ||
routes.capabilitiesOf(resolved.source.route).planner == null) {
return EditResult.denied(
reason: ids.length == 1
? 'Choose a connection with an installed route planner.'
: 'Choose connections with an installed route planner.',
);
}
requests.add(
resolved.source.copyWith(
controlPoints: const [],
routedPoints: const [],
),
);
}
// One batch shares scene queries and lets routes nudge shared channels.
final plans = store.diagram.resolver.planConnectorReroutes(
requests,
scene: scene,
);
final changes = <ReplaceElementStep>[];
for (final request in requests) {
final plan = plans[request.id];
if (plan is! DiagramConnectorRouteGeometry) {
return EditResult.denied(
reason:
'Make more room around the $connectionLabel, then reroute again.',
);
}
final before = scene.connectorById(request.id)!.source;
final after = before.copyWith(
controlPoints: const [],
routedPoints: plan.waypoints,
preserveRoute: false,
);
if (after != before) {
changes.add(ReplaceElementStep(before: before, after: after));
}
}
if (changes.isEmpty) return const EditResult.allow();
return store.edits.dispatch(
DiagramTransaction(label: 'Reroute $connectionLabel', steps: changes),
expectedRevision: document.revision,
);
}