LCOV - code coverage report
Current view: top level - lib/util - decimal_text_formatter.dart (source / functions) Hit Total Coverage
Test: Folly Fields Lines: 2 53 3.8 %
Date: 2023-05-18 02:05:34 Functions: 0 0 -

          Line data    Source code
       1             : import 'package:flutter/services.dart';
       2             : 
       3             : ///
       4             : ///
       5             : ///
       6             : class DecimalTextFormatter extends TextInputFormatter {
       7             :   final int precision;
       8             :   final String decimalSeparator;
       9             :   final String thousandSeparator;
      10             :   final RegExp allow;
      11             : 
      12             :   ///
      13             :   ///
      14             :   ///
      15           1 :   DecimalTextFormatter({
      16             :     required this.precision,
      17             :     this.decimalSeparator = ',',
      18             :     this.thousandSeparator = '.',
      19           2 :   }) : allow = RegExp('[0-9$decimalSeparator$thousandSeparator]');
      20             : 
      21             :   ///
      22             :   ///
      23             :   ///
      24           0 :   @override
      25             :   TextEditingValue formatEditUpdate(
      26             :     TextEditingValue oldValue,
      27             :     TextEditingValue newValue,
      28             :   ) {
      29             :     // if (kDebugMode) {
      30             :     //   print('old: ${oldValue.toJSON()}');
      31             :     //   print('new: ${newValue.toJSON()}');
      32             :     // }
      33             : 
      34           0 :     String newText = newValue.text;
      35             : 
      36             :     /// Empty value
      37           0 :     if (newText.isEmpty ||
      38           0 :         newText == decimalSeparator ||
      39           0 :         newText == thousandSeparator) {
      40             :       // if (kDebugMode) {
      41             :       //   print('New value is empty or equals to "$decimalSeparator" '
      42             :       //       'or equals to "$thousandSeparator"');
      43             :       //   print('\n');
      44             :       // }
      45             : 
      46           0 :       return TextEditingValue(
      47           0 :         text: '0$decimalSeparator'.padRight(precision + 2, '0'),
      48             :         selection: const TextSelection.collapsed(offset: 1),
      49             :       );
      50             :     }
      51             : 
      52             :     /// Char not allowed.
      53           0 :     if (allow.allMatches(newText).length != newText.length) {
      54             :       // if (kDebugMode) {
      55             :       //   print('Char not allowed.');
      56             :       //   print('\n');
      57             :       // }
      58             : 
      59             :       return oldValue;
      60             :     }
      61             : 
      62           0 :     int oldDecimalCount = oldValue.text.split(decimalSeparator).length;
      63           0 :     int oldThousandCount = oldValue.text.split(thousandSeparator).length;
      64             : 
      65           0 :     int newDecimalCount = newText.split(decimalSeparator).length;
      66           0 :     int newThousandCount = newText.split(thousandSeparator).length;
      67             : 
      68           0 :     if (oldDecimalCount < newDecimalCount ||
      69           0 :         oldThousandCount < newThousandCount) {
      70           0 :       int curPos = oldValue.text.indexOf(decimalSeparator) + 1;
      71             : 
      72             :       // if (kDebugMode) {
      73             :       //   print('curPos: $curPos');
      74             :       // }
      75             : 
      76           0 :       if (newValue.selection.baseOffset <= curPos) {
      77           0 :         Map<String, dynamic> oldValueJson = oldValue.toJSON();
      78           0 :         oldValueJson['selectionBase'] = curPos;
      79           0 :         oldValueJson['selectionExtent'] = curPos;
      80             : 
      81             :         // if (kDebugMode) {
      82             :         //   print('\n');
      83             :         // }
      84             : 
      85           0 :         return TextEditingValue.fromJSON(oldValueJson);
      86             :       }
      87             : 
      88             :       // if (kDebugMode) {
      89             :       //   print('\n');
      90             :       // }
      91             : 
      92             :       return oldValue;
      93             :     }
      94             : 
      95             :     /// Decimal Part
      96           0 :     if (newText.contains(decimalSeparator)) {
      97           0 :       List<String> parts = newText.split(decimalSeparator);
      98             : 
      99             :       // if (kDebugMode) {
     100             :       //   print('Integer Part: ${parts.first}');
     101             :       //   print('Decimal Part: ${parts.last}');
     102             :       // }
     103             : 
     104           0 :       String decimalPart = parts.last;
     105             : 
     106           0 :       decimalPart = decimalPart.length > precision
     107           0 :           ? decimalPart.substring(0, precision)
     108           0 :           : decimalPart.padRight(precision, '0');
     109             : 
     110           0 :       newText = '${parts.first}$decimalSeparator$decimalPart';
     111             :     } else {
     112           0 :       if (newText.length == 1) {
     113           0 :         newText += decimalSeparator.padRight(precision + 1, '0');
     114             :       } else {
     115           0 :         int pos = newText.length - precision;
     116           0 :         newText = newText.substring(0, pos) +
     117           0 :             decimalSeparator +
     118           0 :             newText.substring(pos);
     119             :       }
     120             :     }
     121             : 
     122           0 :     int firstLength = newText.length;
     123             : 
     124             :     /// Integer Part
     125           0 :     List<String> parts = newText.split(decimalSeparator);
     126             : 
     127             :     int integerPart =
     128           0 :         int.tryParse(parts.first.replaceAll(thousandSeparator, '')) ?? 0;
     129             : 
     130           0 :     List<String> numbers = integerPart.toString().split('').reversed.toList();
     131             : 
     132           0 :     for (int pos = 3; pos < numbers.length; pos += 4) {
     133           0 :       numbers.insert(pos, thousandSeparator);
     134             :     }
     135             : 
     136           0 :     newText = numbers.reversed.join() + decimalSeparator + parts.last;
     137             : 
     138           0 :     Map<String, dynamic> newValueJson = newValue.toJSON();
     139             : 
     140           0 :     newValueJson['text'] = newText;
     141             : 
     142             :     /// Cursor Positioning
     143           0 :     int newTextLength = newText.length;
     144             : 
     145           0 :     int newPos = newValue.selection.baseOffset;
     146             : 
     147           0 :     int delta = newTextLength - firstLength;
     148             : 
     149             :     // if (kDebugMode) {
     150             :     //   print('delta: $delta');
     151             :     // }
     152             : 
     153           0 :     newPos += delta;
     154             : 
     155           0 :     if (newValue.selection.baseOffset > newTextLength) {
     156             :       newPos = newTextLength;
     157             :     }
     158             : 
     159           0 :     if (newPos < 1) {
     160             :       newPos = 0;
     161             :     }
     162             : 
     163           0 :     newValueJson['selectionBase'] = newPos;
     164           0 :     newValueJson['selectionExtent'] = newPos;
     165             : 
     166             :     // if (kDebugMode) {
     167             :     //   print('newValueJson: $newValueJson');
     168             :     //   print('\n');
     169             :     // }
     170             : 
     171           0 :     return TextEditingValue.fromJSON(newValueJson);
     172             :   }
     173             : }

Generated by: LCOV version 1.14