reroute method

EditResult reroute({
  1. Iterable<String>? connectorIds,
})

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,
  );
}