From 6a5b346608e4948bf45e95f1c85f07058437d56f Mon Sep 17 00:00:00 2001 From: Craig Raw Date: Wed, 8 Jul 2020 14:18:07 +0200 Subject: [PATCH] amount formatter, send final tweaks --- .../sparrow/control/AmountFormatter.java | 96 +++++++++++++++++++ .../sparrow/wallet/SendController.java | 18 ++-- .../sparrowwallet/sparrow/wallet/send.fxml | 2 +- 3 files changed, 109 insertions(+), 7 deletions(-) create mode 100644 src/main/java/com/sparrowwallet/sparrow/control/AmountFormatter.java diff --git a/src/main/java/com/sparrowwallet/sparrow/control/AmountFormatter.java b/src/main/java/com/sparrowwallet/sparrow/control/AmountFormatter.java new file mode 100644 index 00000000..83d5ba59 --- /dev/null +++ b/src/main/java/com/sparrowwallet/sparrow/control/AmountFormatter.java @@ -0,0 +1,96 @@ +package com.sparrowwallet.sparrow.control; + +import javafx.scene.control.TextFormatter; +import javafx.scene.control.TextInputControl; + +import java.text.DecimalFormat; +import java.text.ParseException; +import java.util.function.UnaryOperator; +import java.util.regex.Pattern; + +public class AmountFormatter extends TextFormatter { + private static final Pattern AMOUNT_VALIDATION = Pattern.compile("[\\d,]*(\\.\\d{0,8})?"); + private static final DecimalFormat AMOUNT_FORMAT = new DecimalFormat("###,###.########"); + + public AmountFormatter() { + super(new AmountFilter()); + } + + private static class AmountFilter implements UnaryOperator { + @Override + public Change apply(Change change) { + String oldText = change.getControlText(); + String newText = change.getControlNewText(); + String deleted = null; + if(change.isDeleted()) { + deleted = oldText.substring(change.getRangeStart(), change.getRangeEnd()); + } + + String noFractionCommaText = newText; + int commasRemoved = 0; + int dotIndex = newText.indexOf("."); + if(dotIndex > -1) { + noFractionCommaText = newText.substring(0, dotIndex) + newText.substring(dotIndex).replaceAll(",", ""); + commasRemoved = newText.length() - noFractionCommaText.length(); + } + + if(!AMOUNT_VALIDATION.matcher(noFractionCommaText).matches()) { + return null; + } + + if(",".equals(change.getText())) { + return null; + } + + if("".equals(newText)) { + return change; + } + + if(change.isDeleted() && ",".equals(deleted) && change.getRangeStart() > 0) { + noFractionCommaText = noFractionCommaText.substring(0, change.getRangeStart() - 1) + noFractionCommaText.substring(change.getRangeEnd() - 1); + } + + try { + Number value = AMOUNT_FORMAT.parse(noFractionCommaText); + String correct = AMOUNT_FORMAT.format(value.doubleValue()); + + String compare = newText; + if(compare.contains(".") && compare.endsWith("0")) { + compare = compare.replaceAll("0*$", ""); + } + + if(compare.endsWith(".")) { + compare = compare.substring(0, compare.length() - 1); + } + + if(correct.equals(compare)) { + return change; + } + + if(value.doubleValue() == 0.0 && "0".equals(correct)) { + return change; + } + + TextInputControl control = (TextInputControl)change.getControl(); + change.setText(correct); + change.setRange(0, control.getLength()); + + if(correct.length() != newText.length()) { + String postCorrect = correct.substring(Math.min(change.getCaretPosition(), correct.length())); + int commasAfter = postCorrect.length() - postCorrect.replace(",", "").length(); + int caretShift = change.isDeleted() && ".".equals(deleted) ? commasAfter : 0; + + int caret = change.getCaretPosition() + (correct.length() - newText.length() - caretShift) + commasRemoved; + if(caret >= 0) { + change.setCaretPosition(caret); + change.setAnchor(caret); + } + } + + return change; + } catch (ParseException e) { + return null; + } + } + } +} diff --git a/src/main/java/com/sparrowwallet/sparrow/wallet/SendController.java b/src/main/java/com/sparrowwallet/sparrow/wallet/SendController.java index 38ccd0d1..00020233 100644 --- a/src/main/java/com/sparrowwallet/sparrow/wallet/SendController.java +++ b/src/main/java/com/sparrowwallet/sparrow/wallet/SendController.java @@ -86,9 +86,13 @@ public class SendController extends WalletFormController implements Initializabl private final BooleanProperty insufficientInputsProperty = new SimpleBooleanProperty(false); - private final ChangeListener amountListener = new ChangeListener() { + private final ChangeListener amountListener = new ChangeListener<>() { @Override public void changed(ObservableValue observable, String oldValue, String newValue) { + if(utxoSelectorProperty.get() instanceof MaxUtxoSelector) { + utxoSelectorProperty.setValue(null); + } + updateTransaction(); } }; @@ -137,7 +141,7 @@ public class SendController extends WalletFormController implements Initializabl updateTransaction(); }); - amount.setTextFormatter(new TextFieldValidator(TextFieldValidator.ValidationModus.MAX_FRACTION_DIGITS, 8).getFormatter()); + amount.setTextFormatter(new AmountFormatter()); amount.textProperty().addListener(amountListener); amountUnit.getSelectionModel().select(1); @@ -193,7 +197,7 @@ public class SendController extends WalletFormController implements Initializabl setTargetBlocks(5); - fee.setTextFormatter(new TextFieldValidator(TextFieldValidator.ValidationModus.MAX_FRACTION_DIGITS, 8).getFormatter()); + fee.setTextFormatter(new AmountFormatter()); fee.textProperty().addListener(feeListener); feeAmountUnit.getSelectionModel().select(1); @@ -232,7 +236,9 @@ public class SendController extends WalletFormController implements Initializabl walletTransactionProperty.addListener((observable, oldValue, walletTransaction) -> { if(walletTransaction != null) { - setRecipientValueSats(walletTransaction.getRecipientAmount()); + if(getRecipientValueSats() == null || walletTransaction.getRecipientAmount() != getRecipientValueSats()) { + setRecipientValueSats(walletTransaction.getRecipientAmount()); + } double feeRate = (double)walletTransaction.getFee() / walletTransaction.getTransaction().getVirtualSize(); if(userFeeSet.get()) { @@ -323,7 +329,7 @@ public class SendController extends WalletFormController implements Initializabl private Long getRecipientValueSats(BitcoinUnit bitcoinUnit) { if(amount.getText() != null && !amount.getText().isEmpty()) { - double fieldValue = Double.parseDouble(amount.getText()); + double fieldValue = Double.parseDouble(amount.getText().replaceAll(",", "")); return bitcoinUnit.getSatsValue(fieldValue); } @@ -344,7 +350,7 @@ public class SendController extends WalletFormController implements Initializabl private Long getFeeValueSats(BitcoinUnit bitcoinUnit) { if(fee.getText() != null && !fee.getText().isEmpty()) { - double fieldValue = Double.parseDouble(fee.getText()); + double fieldValue = Double.parseDouble(fee.getText().replaceAll(",", "")); return bitcoinUnit.getSatsValue(fieldValue); } diff --git a/src/main/resources/com/sparrowwallet/sparrow/wallet/send.fxml b/src/main/resources/com/sparrowwallet/sparrow/wallet/send.fxml index a5205ff2..850d0e0a 100644 --- a/src/main/resources/com/sparrowwallet/sparrow/wallet/send.fxml +++ b/src/main/resources/com/sparrowwallet/sparrow/wallet/send.fxml @@ -22,7 +22,7 @@
- +