LCOV - code coverage report
Current view: top level - lib/util - decimal_text_formatter.dart (source / functions) Hit Total Coverage
Test: Folly Fields Lines: 2 69 2.9 %
Date: 2023-05-11 23:59:26 Functions: 0 0 -

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

Generated by: LCOV version 1.14