controlGesture method

DiagramToolGesture controlGesture(
  1. String id,
  2. String nodeId,
  3. DiagramPathControl control, {
  4. required DiagramPoint pointerOrigin,
  5. bool splitSegment = false,
})

Implementation

DiagramToolGesture controlGesture(
  String id,
  String nodeId,
  DiagramPathControl control, {
  required DiagramPoint pointerOrigin,
  bool splitSegment = false,
}) {
  final source = _store.state.document.elementById(id) as ShapeElement;
  final resolved = _store.scene.shapeById(id)!;
  final outline = resolved.editablePath!;
  final key = resolved.definition.pathValue!;
  final path = _pathOf(id)!;
  var targetId = nodeId;
  final index = _index(path, nodeId);
  final node = outline.nodes[index];
  final localOrigin = splitSegment
      ? outline.segmentMidpoints[index]
      : node.position +
            switch (control) {
              DiagramPathControl.anchor => DiagramPoint.zero,
              DiagramPathControl.incoming => node.incoming,
              DiagramPathControl.outgoing => node.outgoing,
            };
  final worldOrigin = resolved.localToWorld(localOrigin);
  // Positions normalize against the frame the path has once split, as
  // adding the point reframes it before the point moves.
  var edited = source;
  if (splitSegment) {
    var suffix = path.nodes.length;
    while (path.nodes.any((n) => n.id == 'node-$suffix')) {
      suffix++;
    }
    targetId = 'node-$suffix';
    edited = reframe(source, key, split(path, nodeId, newNodeId: targetId));
  }
  return DiagramToolGesture(
    label: 'Edit path',
    preview: (start, pointer) {
      if (!splitSegment && pointer.world == pointerOrigin) {
        return DiagramGesturePreview.none;
      }
      var target = worldOrigin + pointer.world - pointerOrigin;
      if (pointer.shiftPressed &&
          !splitSegment &&
          !path.closed &&
          control == DiagramPathControl.anchor &&
          (index == 0 || index == path.nodes.length - 1)) {
        final neighbor = outline.nodes[index == 0 ? 1 : index - 1];
        target = DiagramSnapPolicy.endpoint(
          resolved.localToWorld(neighbor.position),
          target,
          _store.state.options.snaps.rotationSnap,
        );
      }
      final frame = edited.frame;
      final local = target.rotateAround(frame.center, -edited.rotation);
      final normalized = DiagramPoint(
        (local.x - frame.left) / frame.width,
        (local.y - frame.top) / frame.height,
      );
      return DiagramGesturePreview(
        verbs: [
          if (splitSegment)
            DiagramVerbInvocation(
              [id],
              'addPathPoint',
              {'after': nodeId, 'id': targetId},
            ),
          DiagramVerbInvocation(
            [id],
            'movePathControl',
            {'node': targetId, 'control': control, 'position': normalized},
          ),
        ],
      );
    },
  );
}