Files
mirror-os-flutter/packages/mirror_ui/lib/widgets/progress_ring.dart
T
2026-07-11 21:51:34 -05:00

87 lines
2.0 KiB
Dart

import 'dart:math' as math;
import 'package:flutter/material.dart';
import '../theme.dart';
class ProgressRing extends StatelessWidget {
final double percent;
final double size;
final double strokeWidth;
final Color? color;
final Color? backgroundColor;
const ProgressRing({
super.key,
required this.percent,
this.size = 36,
this.strokeWidth = 3,
this.color,
this.backgroundColor,
});
@override
Widget build(BuildContext context) {
final effectiveColor = percent >= 95
? MirrorTheme.success
: (color ?? MirrorTheme.accent);
return SizedBox(
width: size,
height: size,
child: CustomPaint(
painter: _ProgressRingPainter(
percent: percent.clamp(0, 100),
strokeWidth: strokeWidth,
color: effectiveColor,
backgroundColor: backgroundColor ?? MirrorTheme.surfaceLight,
),
),
);
}
}
class _ProgressRingPainter extends CustomPainter {
final double percent;
final double strokeWidth;
final Color color;
final Color backgroundColor;
_ProgressRingPainter({
required this.percent,
required this.strokeWidth,
required this.color,
required this.backgroundColor,
});
@override
void paint(Canvas canvas, Size size) {
final center = Offset(size.width / 2, size.height / 2);
final radius = (size.width - strokeWidth) / 2;
final bgPaint = Paint()
..color = backgroundColor
..style = PaintingStyle.stroke
..strokeWidth = strokeWidth;
final fgPaint = Paint()
..color = color
..style = PaintingStyle.stroke
..strokeWidth = strokeWidth
..strokeCap = StrokeCap.round;
canvas.drawCircle(center, radius, bgPaint);
final sweepAngle = (percent / 100) * 2 * math.pi;
canvas.drawArc(
Rect.fromCircle(center: center, radius: radius),
-math.pi / 2,
sweepAngle,
false,
fgPaint,
);
}
@override
bool shouldRepaint(_ProgressRingPainter oldDelegate) =>
oldDelegate.percent != percent || oldDelegate.color != color;
}