LCOV - code coverage report
Current view: top level - lib - rate.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 46 46 100.0 %
Date: 2022-06-20 19:19:46 Functions: 0 0 -

          Line data    Source code
       1             : library rate;
       2             : 
       3             : import 'package:flutter/material.dart';
       4             : 
       5             : typedef IconBuilder = Icon Function(double value, int index);
       6             : 
       7             : class Rate extends StatefulWidget {
       8             :   /// Allows half a start to be selectable, like 2.5 stars. Defaults to `false`
       9             :   final bool allowHalf;
      10             : 
      11             :   /// Allows clearing if clicked in the same points. Defaults to `true`
      12             :   final bool allowClear;
      13             : 
      14             :   /// If read only, click is blocked
      15             :   final bool readOnly;
      16             : 
      17             :   /// Size of the icon
      18             :   final double iconSize;
      19             : 
      20             :   /// Color of the icon
      21             :   final Color color;
      22             : 
      23             :   /// Initial value, defaults to `0`
      24             :   final double initialValue;
      25             : 
      26             :   /// Function called whenever the rating changes
      27             :   final void Function(double value)? onChange;
      28             : 
      29             :   /// Custom icon builder, in case you need something more customizable
      30             :   final IconBuilder? iconBuilder;
      31             : 
      32           1 :   const Rate({
      33             :     Key? key,
      34             :     this.allowHalf = false,
      35             :     this.allowClear = true,
      36             :     this.readOnly = false,
      37             :     this.iconSize = 24,
      38             :     this.color = Colors.yellow,
      39             :     this.initialValue = 0.0,
      40             :     this.onChange,
      41             :     this.iconBuilder,
      42             :   }) : super(key: key); // coverage:ignore-line
      43             : 
      44           1 :   @override
      45           1 :   State<Rate> createState() => _RateState();
      46             : }
      47             : 
      48             : class _RateState extends State<Rate> {
      49             :   double _value = 0;
      50             :   double? _hoverValue;
      51             : 
      52           1 :   @override
      53             :   void initState() {
      54           1 :     super.initState();
      55           3 :     _value = widget.initialValue;
      56             :   }
      57             : 
      58           1 :   void _valueChangeAction(double value) {
      59           4 :     final newValue = widget.allowClear && _value == value ? 0.0 : value;
      60             : 
      61           1 :     if (mounted) {
      62           3 :       setState(() => _value = newValue);
      63             :     }
      64             : 
      65           2 :     widget.onChange?.call(newValue);
      66             :   }
      67             : 
      68           1 :   @override
      69             :   Widget build(BuildContext context) {
      70           1 :     return Row(
      71             :       mainAxisSize: MainAxisSize.min,
      72           1 :       children: [
      73           1 :         _buildStar(0),
      74           1 :         _buildStar(1),
      75           1 :         _buildStar(2),
      76           1 :         _buildStar(3),
      77           1 :         _buildStar(4),
      78             :       ],
      79             :     );
      80             :   }
      81             : 
      82           1 :   Widget _buildStar(int index) {
      83             :     var icon =
      84           3 :         widget.iconBuilder?.call(_value, index) ?? _defaultIconBuilder(index);
      85             : 
      86           1 :     final iconSize = icon.size ?? widget.iconSize;
      87             : 
      88           1 :     return GestureDetector(
      89           2 :       key: Key('star_rate_$index'),
      90           2 :       onTapDown: widget.readOnly
      91             :           ? null
      92           1 :           : (details) {
      93           5 :               if (details.localPosition.dx < ((iconSize / 2) + 1) &&
      94           2 :                   widget.allowHalf) {
      95           2 :                 _valueChangeAction(index + 0.5);
      96             :               } else {
      97           2 :                 _valueChangeAction(index + 1);
      98             :               }
      99             :             },
     100           1 :       child: MouseRegion(
     101           2 :         cursor: widget.readOnly ? MouseCursor.defer : SystemMouseCursors.click,
     102           2 :         onHover: widget.readOnly
     103             :             ? null
     104           1 :             : (event) {
     105           5 :                 if (event.localPosition.dx < ((iconSize / 2) + 1) &&
     106           2 :                     widget.allowHalf) {
     107           4 :                   setState(() => _hoverValue = index + 0.5);
     108             :                 } else {
     109           4 :                   setState(() => _hoverValue = index + 1);
     110             :                 }
     111             :               },
     112           2 :         onExit: widget.readOnly
     113             :             ? null
     114           1 :             : (_) {
     115           2 :                 setState(() {
     116           1 :                   _hoverValue = null;
     117             :                 });
     118             :               },
     119             :         child: icon,
     120             :       ),
     121             :     );
     122             :   }
     123             : 
     124           1 :   Icon _defaultIconBuilder(int index) {
     125           4 :     var icon = (_hoverValue ?? _value) > index.toDouble()
     126             :         ? Icons.star
     127             :         : Icons.star_border;
     128             : 
     129           6 :     if (widget.allowHalf && (_hoverValue ?? _value) == (index + 0.5)) {
     130             :       icon = Icons.star_half;
     131             :     }
     132             : 
     133           5 :     return Icon(icon, size: widget.iconSize, color: widget.color);
     134             :   }
     135             : }

Generated by: LCOV version 1.15