|  |  |  | @ -6,12 +6,33 @@ import 'package:flutter/scheduler.dart'; | 
			
		
	
		
			
				
					|  |  |  |  | const halfPi = pi / 2; | 
			
		
	
		
			
				
					|  |  |  |  | const pi = math.pi; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | typedef LabelBuilder = Widget Function(double value); | 
			
		
	
		
			
				
					|  |  |  |  | typedef LabelBuilder = Iterable<Widget> Function(List<LevelValue> values); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | extension LevelValueExt on List<LevelValue> { | 
			
		
	
		
			
				
					|  |  |  |  |   double? level(int level) { | 
			
		
	
		
			
				
					|  |  |  |  |     for (var element in this) { | 
			
		
	
		
			
				
					|  |  |  |  |       if (element.level == level) return element.value; | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  |     return null; | 
			
		
	
		
			
				
					|  |  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | @immutable | 
			
		
	
		
			
				
					|  |  |  |  | class LevelValue { | 
			
		
	
		
			
				
					|  |  |  |  |   final double value; | 
			
		
	
		
			
				
					|  |  |  |  |   final int level; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   const LevelValue(this.value) : level = 0; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   const LevelValue._withLevel(this.value, this.level); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   LevelValue incrementLevel() => LevelValue._withLevel(value, level + 1); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | class RingIndicator extends StatefulWidget { | 
			
		
	
		
			
				
					|  |  |  |  |   const RingIndicator({ | 
			
		
	
		
			
				
					|  |  |  |  |     Key? key, | 
			
		
	
		
			
				
					|  |  |  |  |     this.backgroundColor = Colors.grey, | 
			
		
	
		
			
				
					|  |  |  |  |     this.backgroundColor = Colors.white12, | 
			
		
	
		
			
				
					|  |  |  |  |     this.ringWidth = 10, | 
			
		
	
		
			
				
					|  |  |  |  |     this.startAngel = 0, | 
			
		
	
		
			
				
					|  |  |  |  |     this.endAngel = pi * 2, | 
			
		
	
	
		
			
				
					|  |  |  | @ -21,7 +42,9 @@ class RingIndicator extends StatefulWidget { | 
			
		
	
		
			
				
					|  |  |  |  |     required this.value, | 
			
		
	
		
			
				
					|  |  |  |  |     this.innerRing, | 
			
		
	
		
			
				
					|  |  |  |  |     this.labelBuilder, | 
			
		
	
		
			
				
					|  |  |  |  |   }) : super(key: key); | 
			
		
	
		
			
				
					|  |  |  |  |     double? gap, | 
			
		
	
		
			
				
					|  |  |  |  |   })  : gap = gap ?? ringWidth / 2, | 
			
		
	
		
			
				
					|  |  |  |  |         super(key: key); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   final Color backgroundColor; | 
			
		
	
		
			
				
					|  |  |  |  |   final double ringWidth; | 
			
		
	
	
		
			
				
					|  |  |  | @ -33,19 +56,22 @@ class RingIndicator extends StatefulWidget { | 
			
		
	
		
			
				
					|  |  |  |  |   final double value; | 
			
		
	
		
			
				
					|  |  |  |  |   final RingIndicator? innerRing; | 
			
		
	
		
			
				
					|  |  |  |  |   final LabelBuilder? labelBuilder; | 
			
		
	
		
			
				
					|  |  |  |  |   final double gap; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   @override | 
			
		
	
		
			
				
					|  |  |  |  |   State<RingIndicator> createState() => _RingIndicatorState(); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | class _RingIndicatorState extends State<RingIndicator> { | 
			
		
	
		
			
				
					|  |  |  |  |   double? _value = 0; | 
			
		
	
		
			
				
					|  |  |  |  |   double _value = 0; | 
			
		
	
		
			
				
					|  |  |  |  |   Map<int, LevelValue> values = {}; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   _RingIndicatorState? parent; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   @override | 
			
		
	
		
			
				
					|  |  |  |  |   Widget build(BuildContext context) { | 
			
		
	
		
			
				
					|  |  |  |  |     var value = _value ?? widget.value; | 
			
		
	
		
			
				
					|  |  |  |  |     var fillAngel = | 
			
		
	
		
			
				
					|  |  |  |  |         ((value - widget.minValue) / (widget.maxValue - widget.minValue)) * (widget.endAngel - widget.startAngel); | 
			
		
	
		
			
				
					|  |  |  |  |         ((_value - widget.minValue) / (widget.maxValue - widget.minValue)) * (widget.endAngel - widget.startAngel); | 
			
		
	
		
			
				
					|  |  |  |  |     return Center( | 
			
		
	
		
			
				
					|  |  |  |  |       child: SizedBox.expand( | 
			
		
	
		
			
				
					|  |  |  |  |         child: CustomPaint( | 
			
		
	
	
		
			
				
					|  |  |  | @ -59,7 +85,12 @@ class _RingIndicatorState extends State<RingIndicator> { | 
			
		
	
		
			
				
					|  |  |  |  |           ), | 
			
		
	
		
			
				
					|  |  |  |  |           child: Stack( | 
			
		
	
		
			
				
					|  |  |  |  |             children: [ | 
			
		
	
		
			
				
					|  |  |  |  |               if (widget.labelBuilder != null) widget.labelBuilder!(value), | 
			
		
	
		
			
				
					|  |  |  |  |               if (widget.innerRing != null) | 
			
		
	
		
			
				
					|  |  |  |  |                 Padding( | 
			
		
	
		
			
				
					|  |  |  |  |                   padding: EdgeInsets.all(widget.ringWidth + widget.gap), | 
			
		
	
		
			
				
					|  |  |  |  |                   child: widget.innerRing, | 
			
		
	
		
			
				
					|  |  |  |  |                 ), | 
			
		
	
		
			
				
					|  |  |  |  |               if (widget.labelBuilder != null) ...widget.labelBuilder!(values.values.toList()), | 
			
		
	
		
			
				
					|  |  |  |  |             ], | 
			
		
	
		
			
				
					|  |  |  |  |           ), | 
			
		
	
		
			
				
					|  |  |  |  |         ), | 
			
		
	
	
		
			
				
					|  |  |  | @ -69,9 +100,7 @@ class _RingIndicatorState extends State<RingIndicator> { | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   Ticker? ticker; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   @override | 
			
		
	
		
			
				
					|  |  |  |  |   void didUpdateWidget(RingIndicator oldWidget) { | 
			
		
	
		
			
				
					|  |  |  |  |     super.didUpdateWidget(oldWidget); | 
			
		
	
		
			
				
					|  |  |  |  |   _handleValueChange(double newValue, double oldValue) { | 
			
		
	
		
			
				
					|  |  |  |  |     var startTime = DateTime.now(); | 
			
		
	
		
			
				
					|  |  |  |  |     ticker?.stop(); | 
			
		
	
		
			
				
					|  |  |  |  |     ticker = Ticker((_) { | 
			
		
	
	
		
			
				
					|  |  |  | @ -81,12 +110,43 @@ class _RingIndicatorState extends State<RingIndicator> { | 
			
		
	
		
			
				
					|  |  |  |  |       } | 
			
		
	
		
			
				
					|  |  |  |  |       if (mounted) { | 
			
		
	
		
			
				
					|  |  |  |  |         setState(() { | 
			
		
	
		
			
				
					|  |  |  |  |           _value = oldWidget.value + (widget.value - oldWidget.value) * (diff / 300); | 
			
		
	
		
			
				
					|  |  |  |  |           _value = oldValue + (newValue - oldValue) * (diff / 300); | 
			
		
	
		
			
				
					|  |  |  |  |           values[0] = LevelValue(_value); | 
			
		
	
		
			
				
					|  |  |  |  |         }); | 
			
		
	
		
			
				
					|  |  |  |  |         if (parent != null) { | 
			
		
	
		
			
				
					|  |  |  |  |           for (var value in values.values) { | 
			
		
	
		
			
				
					|  |  |  |  |             parent!.updateValue(value.incrementLevel()); | 
			
		
	
		
			
				
					|  |  |  |  |           } | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |       } | 
			
		
	
		
			
				
					|  |  |  |  |     }) | 
			
		
	
		
			
				
					|  |  |  |  |       ..start(); | 
			
		
	
		
			
				
					|  |  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   @override | 
			
		
	
		
			
				
					|  |  |  |  |   void initState() { | 
			
		
	
		
			
				
					|  |  |  |  |     super.initState(); | 
			
		
	
		
			
				
					|  |  |  |  |     _handleValueChange(widget.value, 0); | 
			
		
	
		
			
				
					|  |  |  |  |     parent = context.findAncestorStateOfType<_RingIndicatorState>(); | 
			
		
	
		
			
				
					|  |  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   @override | 
			
		
	
		
			
				
					|  |  |  |  |   void didUpdateWidget(RingIndicator oldWidget) { | 
			
		
	
		
			
				
					|  |  |  |  |     super.didUpdateWidget(oldWidget); | 
			
		
	
		
			
				
					|  |  |  |  |     _handleValueChange(widget.value, oldWidget.value); | 
			
		
	
		
			
				
					|  |  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   void updateValue(LevelValue value) { | 
			
		
	
		
			
				
					|  |  |  |  |     values[value.level] = value; | 
			
		
	
		
			
				
					|  |  |  |  |     if (parent != null && parent!.mounted) { | 
			
		
	
		
			
				
					|  |  |  |  |       for (var value in values.values) { | 
			
		
	
		
			
				
					|  |  |  |  |         parent!.updateValue(value.incrementLevel()); | 
			
		
	
		
			
				
					|  |  |  |  |       } | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  |     if (mounted) { | 
			
		
	
		
			
				
					|  |  |  |  |       setState(() {}); | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | class _RingIndicatorPainter extends CustomPainter { | 
			
		
	
	
		
			
				
					|  |  |  | 
 |