paint method

  1. @override
void paint(
  1. Canvas canvas,
  2. Offset center,
  3. Size size,
  4. Paint fillPaint,
  5. Paint? borderPaint, {
  6. ShapeDirection? orientation,
  7. bool isPointingOutward = false,
})
override

Paints the marker shape on the given canvas.

Parameters:

  • canvas: The canvas to draw on
  • center: The center position of the shape
  • size: The size of the shape (width and height)
  • fillPaint: Paint to use for filling the shape
  • borderPaint: Optional paint to use for the border/stroke
  • orientation: Direction the shape is anchored/facing (left, right, top, bottom)
  • isPointingOutward: For asymmetric shapes (triangle, capsuleHalf), whether the tip/arrow points outward. For ports: true for output ports, false for input ports. For connection endpoints: typically true (pointing along connection direction).

Implementation

@override
void paint(
  Canvas canvas,
  Offset center,
  Size size,
  Paint fillPaint,
  Paint? borderPaint, {
  ShapeDirection? orientation,
  bool isPointingOutward = false,
}) {
  final path = Path();
  final halfWidth = size.width / 2;
  final halfHeight = size.height / 2;

  // Default to right if no orientation provided
  final effectiveOrientation = orientation ?? ShapeDirection.right;

  // Orient triangle based on context:
  // - isPointingOutward = false: flat side faces outward, tip points inward (input ports)
  // - isPointingOutward = true: tip points outward, flat side faces inward (output ports, endpoints)
  //
  // The triangle is always centered on the passed center point. For both ports and
  // connection endpoints, external positioning code accounts for the centered nature.
  switch (effectiveOrientation) {
    case ShapeDirection.left:
      if (isPointingOutward) {
        // Point on left (outside), flat side on right (inside)
        path.moveTo(center.dx - halfWidth, center.dy);
        path.lineTo(center.dx + halfWidth, center.dy - halfHeight);
        path.lineTo(center.dx + halfWidth, center.dy + halfHeight);
      } else {
        // Flat side on left (outside), point toward right (inside)
        path.moveTo(center.dx + halfWidth, center.dy);
        path.lineTo(center.dx - halfWidth, center.dy - halfHeight);
        path.lineTo(center.dx - halfWidth, center.dy + halfHeight);
      }
      break;
    case ShapeDirection.right:
      if (isPointingOutward) {
        // Point on right (outside), flat side on left (inside)
        path.moveTo(center.dx + halfWidth, center.dy);
        path.lineTo(center.dx - halfWidth, center.dy - halfHeight);
        path.lineTo(center.dx - halfWidth, center.dy + halfHeight);
      } else {
        // Flat side on right (outside), point toward left (inside)
        path.moveTo(center.dx - halfWidth, center.dy);
        path.lineTo(center.dx + halfWidth, center.dy - halfHeight);
        path.lineTo(center.dx + halfWidth, center.dy + halfHeight);
      }
      break;
    case ShapeDirection.top:
      if (isPointingOutward) {
        // Point on top (outside), flat side on bottom (inside)
        path.moveTo(center.dx, center.dy - halfHeight);
        path.lineTo(center.dx - halfWidth, center.dy + halfHeight);
        path.lineTo(center.dx + halfWidth, center.dy + halfHeight);
      } else {
        // Flat side on top (outside), point toward bottom (inside)
        path.moveTo(center.dx, center.dy + halfHeight);
        path.lineTo(center.dx - halfWidth, center.dy - halfHeight);
        path.lineTo(center.dx + halfWidth, center.dy - halfHeight);
      }
      break;
    case ShapeDirection.bottom:
      if (isPointingOutward) {
        // Point on bottom (outside), flat side on top (inside)
        path.moveTo(center.dx, center.dy + halfHeight);
        path.lineTo(center.dx - halfWidth, center.dy - halfHeight);
        path.lineTo(center.dx + halfWidth, center.dy - halfHeight);
      } else {
        // Flat side on bottom (outside), point toward top (inside)
        path.moveTo(center.dx, center.dy - halfHeight);
        path.lineTo(center.dx - halfWidth, center.dy + halfHeight);
        path.lineTo(center.dx + halfWidth, center.dy + halfHeight);
      }
      break;
  }
  path.close();

  canvas.drawPath(path, fillPaint);
  if (borderPaint != null && borderPaint.strokeWidth > 0) {
    canvas.drawPath(path, borderPaint);
  }
}