content: import 'package:flutter/material.dart';
  
  import '../../menstrual_cycle_widget.dart';
  import '../../utils/dash_path.dart';
  
  typedef PathBuilder = Path Function(Size);
  
  class DashedPainter extends CustomPainter {
    final double strokeWidth;
    final List<double> dashPattern;
    final Color color;
    final Gradient? gradient;
    final BorderType borderType;
    final Radius radius;
    final StrokeCap strokeCap;
    final PathBuilder? customPath;
    final EdgeInsets padding;
  
    DashedPainter({
      this.strokeWidth = 2,
      this.dashPattern = const <double>[3, 1],
      this.color = Colors.black,
      this.gradient,
      this.borderType = BorderType.rect,
      this.radius = const Radius.circular(0),
      this.strokeCap = StrokeCap.butt,
      this.customPath,
      this.padding = EdgeInsets.zero,
    }) {
      assert(dashPattern.isNotEmpty, 'Dash Pattern cannot be empty');
    }
  
    @override
    void paint(Canvas canvas, Size size) {
      final Size newSize;
      if (padding == EdgeInsets.zero) {
        newSize = size;
      } else {
        canvas.translate(padding.left, padding.top);
        newSize = Size(
          size.width - padding.horizontal,
          size.height - padding.vertical,
        );
      }
  
      Paint paint = Paint()
        ..strokeWidth = strokeWidth
        ..strokeCap = strokeCap
        ..style = PaintingStyle.stroke;
  
      if (gradient != null) {
        final rect = Offset.zero & newSize;
        paint.shader = gradient!.createShader(rect);
      } else {
        paint.color = color;
      }
  
      Path path;
      if (customPath != null) {
        path = dashPath(
          customPath!(newSize),
          dashArray: CircularIntervalList(dashPattern),
        );
      } else {
        path = _getPath(newSize);
      }
  
      canvas.drawPath(path, paint);
    }
  
    /// Returns a [Path] based on the the [borderType] parameter
    Path _getPath(Size size) {
      Path path;
      switch (borderType) {
        case BorderType.circle:
          path = _getCirclePath(size);
          break;
        case BorderType.rRect:
          path = _getRRectPath(size, radius);
          break;
        case BorderType.rect:
          path = _getRectPath(size);
          break;
        case BorderType.oval:
          path = _getOvalPath(size);
          break;
      }
  
      return dashPath(path, dashArray: CircularIntervalList(dashPattern));
    }
  
    /// Returns a circular path of [size]
    Path _getCirclePath(Size size) {
      double w = size.width;
      double h = size.height;
      double s = size.shortestSide;
  
      return Path()
        ..addRRect(
          RRect.fromRectAndRadius(
            Rect.fromLTWH(
              w > s ? (w - s) / 2 : 0,
              h > s ? (h - s) / 2 : 0,
              s,
              s,
            ),
            Radius.circular(s / 2),
          ),
        );
    }
  
    /// Returns a Rounded Rectangular Path with [radius] of [size]
    Path _getRRectPath(Size size, Radius radius) {
      return Path()
        ..addRRect(
          RRect.fromRectAndRadius(
            Rect.fromLTWH(
              0,
              0,
              size.width,
              size.height,
            ),
            radius,
          ),
        );
    }
  
    /// Returns a path of [size]
    Path _getRectPath(Size size) {
      return Path()
        ..addRect(
          Rect.fromLTWH(
            0,
            0,
            size.width,
            size.height,
          ),
        );
    }
  
    /// Return an oval path of [size]
    Path _getOvalPath(Size size) {
      return Path()
        ..addOval(
          Rect.fromLTWH(
            0,
            0,
            size.width,
            size.height,
          ),
        );
    }
  
    @override
    bool shouldRepaint(DashedPainter oldDelegate) {
      return oldDelegate.strokeWidth != strokeWidth ||
          oldDelegate.color != color ||
          oldDelegate.dashPattern != dashPattern ||
          oldDelegate.padding != padding ||
          oldDelegate.borderType != borderType;
    }
  }
  