amount formatter, send final tweaks

This commit is contained in:
Craig Raw 2020-07-08 14:18:07 +02:00
parent 6ecebd9cf6
commit 6a5b346608
3 changed files with 109 additions and 7 deletions

View file

@ -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<String> {
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<Change> {
@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;
}
}
}
}

View file

@ -86,9 +86,13 @@ public class SendController extends WalletFormController implements Initializabl
private final BooleanProperty insufficientInputsProperty = new SimpleBooleanProperty(false);
private final ChangeListener<String> amountListener = new ChangeListener<String>() {
private final ChangeListener<String> amountListener = new ChangeListener<>() {
@Override
public void changed(ObservableValue<? extends String> 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);
}

View file

@ -22,7 +22,7 @@
<BorderPane stylesheets="@send.css, @wallet.css, @../script.css, @../general.css" styleClass="wallet-pane" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.sparrowwallet.sparrow.wallet.SendController">
<center>
<VBox>
<VBox spacing="10">
<GridPane styleClass="send-form" hgap="10.0" vgap="10.0">
<padding>
<Insets left="25.0" right="25.0" top="25.0" />