Created
April 3, 2025 22:01
-
-
Save EsinShadrach/917f39f8dd2c4d90e5ea9e478a1acb58 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class DashedBorder extends BoxBorder { | |
| const DashedBorder({ | |
| this.top = BorderSide.none, | |
| this.right = BorderSide.none, | |
| this.bottom = BorderSide.none, | |
| this.left = BorderSide.none, | |
| this.dashLength = 5.0, | |
| this.dashGap = 3.0, | |
| }); | |
| factory DashedBorder.fromBorderSide({ | |
| required BorderSide borderSide, | |
| double dashLength = 5.0, | |
| double dashGap = 3.0, | |
| }) { | |
| return DashedBorder( | |
| top: borderSide, | |
| right: borderSide, | |
| bottom: borderSide, | |
| left: borderSide, | |
| dashLength: dashLength, | |
| dashGap: dashGap, | |
| ); | |
| } | |
| factory DashedBorder.all({ | |
| Color color = const Color(0xFF000000), | |
| double width = 1.0, | |
| BorderStyle style = BorderStyle.solid, | |
| double dashLength = 5.0, | |
| double dashGap = 3.0, | |
| }) { | |
| final BorderSide side = BorderSide( | |
| color: color, | |
| width: width, | |
| style: style, | |
| ); | |
| return DashedBorder.fromBorderSide( | |
| borderSide: side, | |
| dashLength: dashLength, | |
| dashGap: dashGap, | |
| ); | |
| } | |
| final double dashLength; | |
| final double dashGap; | |
| @override | |
| final BorderSide top; | |
| final BorderSide right; | |
| @override | |
| final BorderSide bottom; | |
| final BorderSide left; | |
| @override | |
| EdgeInsetsGeometry get dimensions { | |
| return EdgeInsets.fromLTRB( | |
| left.width, | |
| top.width, | |
| right.width, | |
| bottom.width, | |
| ); | |
| } | |
| @override | |
| bool get isUniform => top == right && right == bottom && bottom == left; | |
| @override | |
| void paint( | |
| Canvas canvas, | |
| Rect rect, { | |
| TextDirection? textDirection, | |
| BoxShape shape = BoxShape.rectangle, | |
| BorderRadius? borderRadius, | |
| }) { | |
| if (shape != BoxShape.rectangle && shape != BoxShape.circle) { | |
| throw ArgumentError('Unsupported shape: $shape'); | |
| } | |
| if (shape == BoxShape.circle) { | |
| _paintCircle(canvas, rect); | |
| return; | |
| } | |
| if (borderRadius != null) { | |
| _paintRoundedRectangle(canvas, rect, borderRadius); | |
| return; | |
| } | |
| _paintRectangle(canvas, rect); | |
| } | |
| void _paintCircle(Canvas canvas, Rect rect) { | |
| final Paint paint = Paint() | |
| ..color = top.color | |
| ..strokeWidth = top.width | |
| ..style = PaintingStyle.stroke; | |
| final double radius = math.min(rect.width, rect.height) / 2; | |
| final Offset center = rect.center; | |
| final double circumference = 2 * math.pi * radius; | |
| final int dashCount = (circumference / (dashLength + dashGap)).floor(); | |
| final double dashAngle = 2 * math.pi / dashCount; | |
| for (int i = 0; i < dashCount; i++) { | |
| final double startAngle = i * dashAngle; | |
| final double endAngle = | |
| startAngle + (dashLength / circumference) * 2 * math.pi; | |
| canvas.drawArc( | |
| Rect.fromCircle(center: center, radius: radius), | |
| startAngle, | |
| endAngle - startAngle, | |
| false, | |
| paint, | |
| ); | |
| } | |
| } | |
| void _paintRoundedRectangle( | |
| Canvas canvas, | |
| Rect rect, | |
| BorderRadius borderRadius, | |
| ) { | |
| final RRect rrect = RRect.fromRectAndCorners( | |
| rect, | |
| topLeft: borderRadius.topLeft, | |
| topRight: borderRadius.topRight, | |
| bottomLeft: borderRadius.bottomLeft, | |
| bottomRight: borderRadius.bottomRight, | |
| ); | |
| final Paint paint = Paint() | |
| ..color = top.color | |
| ..strokeWidth = top.width | |
| ..style = PaintingStyle.stroke; | |
| canvas.drawPath( | |
| _dashPath( | |
| Path()..addRRect(rrect), | |
| dashLength: dashLength, | |
| dashGap: dashGap, | |
| ), | |
| paint, | |
| ); | |
| } | |
| void _paintRectangle(Canvas canvas, Rect rect) { | |
| final Paint paint = Paint() | |
| ..color = top.color | |
| ..strokeWidth = top.width | |
| ..style = PaintingStyle.stroke; | |
| if (top.width > 0.0) { | |
| final Path topPath = Path() | |
| ..moveTo(rect.left, rect.top) | |
| ..lineTo(rect.right, rect.top); | |
| canvas.drawPath( | |
| _dashPath(topPath, dashLength: dashLength, dashGap: dashGap), | |
| paint..color = top.color, | |
| ); | |
| } | |
| if (right.width > 0.0) { | |
| final Path rightPath = Path() | |
| ..moveTo(rect.right, rect.top) | |
| ..lineTo(rect.right, rect.bottom); | |
| canvas.drawPath( | |
| _dashPath(rightPath, dashLength: dashLength, dashGap: dashGap), | |
| paint..color = right.color, | |
| ); | |
| } | |
| if (bottom.width > 0.0) { | |
| final Path bottomPath = Path() | |
| ..moveTo(rect.right, rect.bottom) | |
| ..lineTo(rect.left, rect.bottom); | |
| canvas.drawPath( | |
| _dashPath(bottomPath, dashLength: dashLength, dashGap: dashGap), | |
| paint..color = bottom.color, | |
| ); | |
| } | |
| if (left.width > 0.0) { | |
| final Path leftPath = Path() | |
| ..moveTo(rect.left, rect.bottom) | |
| ..lineTo(rect.left, rect.top); | |
| canvas.drawPath( | |
| _dashPath(leftPath, dashLength: dashLength, dashGap: dashGap), | |
| paint..color = left.color, | |
| ); | |
| } | |
| } | |
| Path _dashPath( | |
| Path source, { | |
| required double dashLength, | |
| required double dashGap, | |
| }) { | |
| final Path dest = Path(); | |
| final PathMetrics metrics = source.computeMetrics(); | |
| for (final PathMetric metric in metrics) { | |
| double distance = 0.0; | |
| bool draw = true; | |
| while (distance < metric.length) { | |
| final double length = draw ? dashLength : dashGap; | |
| if (draw) { | |
| dest.addPath( | |
| metric.extractPath(distance, distance + length), | |
| Offset.zero, | |
| ); | |
| } | |
| distance += length; | |
| draw = !draw; | |
| } | |
| } | |
| return dest; | |
| } | |
| @override | |
| ShapeBorder scale(double t) { | |
| return DashedBorder( | |
| top: top.scale(t), | |
| right: right.scale(t), | |
| bottom: bottom.scale(t), | |
| left: left.scale(t), | |
| dashLength: dashLength * t, | |
| dashGap: dashGap * t, | |
| ); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment