mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2024-12-25 13:16:44 +00:00
improve encapsulation and binding lifecycle of cell confirmation listeners
This commit is contained in:
parent
4b32eb397e
commit
6ac294920e
5 changed files with 128 additions and 31 deletions
|
@ -2,11 +2,14 @@ package com.sparrowwallet.sparrow.control;
|
||||||
|
|
||||||
import com.sparrowwallet.drongo.BitcoinUnit;
|
import com.sparrowwallet.drongo.BitcoinUnit;
|
||||||
import com.sparrowwallet.drongo.protocol.Transaction;
|
import com.sparrowwallet.drongo.protocol.Transaction;
|
||||||
|
import com.sparrowwallet.drongo.wallet.BlockTransactionHash;
|
||||||
import com.sparrowwallet.sparrow.UnitFormat;
|
import com.sparrowwallet.sparrow.UnitFormat;
|
||||||
import com.sparrowwallet.sparrow.wallet.Entry;
|
import com.sparrowwallet.sparrow.wallet.Entry;
|
||||||
import com.sparrowwallet.sparrow.wallet.HashIndexEntry;
|
import com.sparrowwallet.sparrow.wallet.HashIndexEntry;
|
||||||
import com.sparrowwallet.sparrow.wallet.TransactionEntry;
|
import com.sparrowwallet.sparrow.wallet.TransactionEntry;
|
||||||
import com.sparrowwallet.sparrow.wallet.UtxoEntry;
|
import com.sparrowwallet.sparrow.wallet.UtxoEntry;
|
||||||
|
import javafx.beans.property.IntegerProperty;
|
||||||
|
import javafx.beans.property.SimpleIntegerProperty;
|
||||||
import javafx.scene.control.ContentDisplay;
|
import javafx.scene.control.ContentDisplay;
|
||||||
import javafx.scene.control.Tooltip;
|
import javafx.scene.control.Tooltip;
|
||||||
import javafx.scene.control.TreeTableCell;
|
import javafx.scene.control.TreeTableCell;
|
||||||
|
@ -16,12 +19,14 @@ import org.controlsfx.tools.Platform;
|
||||||
|
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
|
|
||||||
class CoinCell extends TreeTableCell<Entry, Number> {
|
class CoinCell extends TreeTableCell<Entry, Number> implements ConfirmationsListener {
|
||||||
private final Tooltip tooltip;
|
private final CoinTooltip tooltip;
|
||||||
|
|
||||||
|
private IntegerProperty confirmationsProperty;
|
||||||
|
|
||||||
public CoinCell() {
|
public CoinCell() {
|
||||||
super();
|
super();
|
||||||
tooltip = new Tooltip();
|
tooltip = new CoinTooltip();
|
||||||
tooltip.setShowDelay(Duration.millis(500));
|
tooltip.setShowDelay(Duration.millis(500));
|
||||||
getStyleClass().add("coin-cell");
|
getStyleClass().add("coin-cell");
|
||||||
if(Platform.getCurrent() == Platform.OSX) {
|
if(Platform.getCurrent() == Platform.OSX) {
|
||||||
|
@ -50,21 +55,16 @@ class CoinCell extends TreeTableCell<Entry, Number> {
|
||||||
final String btcValue = decimalFormat.format(amount.doubleValue() / Transaction.SATOSHIS_PER_BITCOIN);
|
final String btcValue = decimalFormat.format(amount.doubleValue() / Transaction.SATOSHIS_PER_BITCOIN);
|
||||||
|
|
||||||
if(unit.equals(BitcoinUnit.BTC)) {
|
if(unit.equals(BitcoinUnit.BTC)) {
|
||||||
tooltip.setText(satsValue + " " + BitcoinUnit.SATOSHIS.getLabel());
|
tooltip.setValue(satsValue + " " + BitcoinUnit.SATOSHIS.getLabel());
|
||||||
setText(btcValue);
|
setText(btcValue);
|
||||||
} else {
|
} else {
|
||||||
tooltip.setText(btcValue + " " + BitcoinUnit.BTC.getLabel());
|
tooltip.setValue(btcValue + " " + BitcoinUnit.BTC.getLabel());
|
||||||
setText(satsValue);
|
setText(satsValue);
|
||||||
}
|
}
|
||||||
setTooltip(tooltip);
|
setTooltip(tooltip);
|
||||||
String tooltipValue = tooltip.getText();
|
|
||||||
|
|
||||||
if(entry instanceof TransactionEntry transactionEntry) {
|
if(entry instanceof TransactionEntry transactionEntry) {
|
||||||
tooltip.setText(tooltipValue + " (" + transactionEntry.getConfirmationsDescription() + ")");
|
tooltip.showConfirmations(transactionEntry.confirmationsProperty());
|
||||||
|
|
||||||
transactionEntry.confirmationsProperty().addListener((observable, oldValue, newValue) -> {
|
|
||||||
tooltip.setText(tooltipValue + " (" + transactionEntry.getConfirmationsDescription() + ")");
|
|
||||||
});
|
|
||||||
|
|
||||||
if(transactionEntry.isConfirming()) {
|
if(transactionEntry.isConfirming()) {
|
||||||
ConfirmationProgressIndicator arc = new ConfirmationProgressIndicator(transactionEntry.getConfirmations());
|
ConfirmationProgressIndicator arc = new ConfirmationProgressIndicator(transactionEntry.getConfirmations());
|
||||||
|
@ -94,4 +94,65 @@ class CoinCell extends TreeTableCell<Entry, Number> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IntegerProperty getConfirmationsProperty() {
|
||||||
|
if(confirmationsProperty == null) {
|
||||||
|
confirmationsProperty = new SimpleIntegerProperty();
|
||||||
|
confirmationsProperty.addListener((observable, oldValue, newValue) -> {
|
||||||
|
if(newValue.intValue() >= BlockTransactionHash.BLOCKS_TO_CONFIRM) {
|
||||||
|
getStyleClass().remove("confirming");
|
||||||
|
confirmationsProperty.unbind();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return confirmationsProperty;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class CoinTooltip extends Tooltip {
|
||||||
|
private final IntegerProperty confirmationsProperty = new SimpleIntegerProperty();
|
||||||
|
private boolean showConfirmations;
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
public void setValue(String value) {
|
||||||
|
this.value = value;
|
||||||
|
setTooltipText();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void showConfirmations(IntegerProperty txEntryConfirmationsProperty) {
|
||||||
|
showConfirmations = true;
|
||||||
|
|
||||||
|
int confirmations = txEntryConfirmationsProperty.get();
|
||||||
|
if(confirmations < BlockTransactionHash.BLOCKS_TO_FULLY_CONFIRM) {
|
||||||
|
confirmationsProperty.bind(txEntryConfirmationsProperty);
|
||||||
|
confirmationsProperty.addListener((observable, oldValue, newValue) -> {
|
||||||
|
setTooltipText();
|
||||||
|
if(newValue.intValue() >= BlockTransactionHash.BLOCKS_TO_FULLY_CONFIRM) {
|
||||||
|
confirmationsProperty.unbind();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
confirmationsProperty.unbind();
|
||||||
|
confirmationsProperty.set(confirmations);
|
||||||
|
}
|
||||||
|
|
||||||
|
setTooltipText();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setTooltipText() {
|
||||||
|
setText(value + (showConfirmations ? " (" + getConfirmationsDescription() + ")" : ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getConfirmationsDescription() {
|
||||||
|
int confirmations = confirmationsProperty.get();
|
||||||
|
if(confirmations == 0) {
|
||||||
|
return "Unconfirmed in mempool";
|
||||||
|
} else if(confirmations < BlockTransactionHash.BLOCKS_TO_FULLY_CONFIRM) {
|
||||||
|
return confirmations + " confirmation" + (confirmations == 1 ? "" : "s");
|
||||||
|
} else {
|
||||||
|
return BlockTransactionHash.BLOCKS_TO_FULLY_CONFIRM + "+ confirmations";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
package com.sparrowwallet.sparrow.control;
|
||||||
|
|
||||||
|
import javafx.beans.property.IntegerProperty;
|
||||||
|
|
||||||
|
public interface ConfirmationsListener {
|
||||||
|
IntegerProperty getConfirmationsProperty();
|
||||||
|
}
|
|
@ -12,6 +12,8 @@ import com.sparrowwallet.sparrow.glyphfont.FontAwesome5;
|
||||||
import com.sparrowwallet.sparrow.io.Config;
|
import com.sparrowwallet.sparrow.io.Config;
|
||||||
import com.sparrowwallet.sparrow.wallet.*;
|
import com.sparrowwallet.sparrow.wallet.*;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
|
import javafx.beans.property.IntegerProperty;
|
||||||
|
import javafx.beans.property.SimpleIntegerProperty;
|
||||||
import javafx.geometry.Pos;
|
import javafx.geometry.Pos;
|
||||||
import javafx.scene.control.*;
|
import javafx.scene.control.*;
|
||||||
import javafx.scene.input.Clipboard;
|
import javafx.scene.input.Clipboard;
|
||||||
|
@ -30,7 +32,7 @@ import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class EntryCell extends TreeTableCell<Entry, Entry> {
|
public class EntryCell extends TreeTableCell<Entry, Entry> implements ConfirmationsListener {
|
||||||
private static final Logger log = LoggerFactory.getLogger(EntryCell.class);
|
private static final Logger log = LoggerFactory.getLogger(EntryCell.class);
|
||||||
|
|
||||||
public static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm");
|
public static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm");
|
||||||
|
@ -38,6 +40,8 @@ public class EntryCell extends TreeTableCell<Entry, Entry> {
|
||||||
|
|
||||||
private static EntryCell lastCell;
|
private static EntryCell lastCell;
|
||||||
|
|
||||||
|
private IntegerProperty confirmationsProperty;
|
||||||
|
|
||||||
public EntryCell() {
|
public EntryCell() {
|
||||||
super();
|
super();
|
||||||
setAlignment(Pos.CENTER_LEFT);
|
setAlignment(Pos.CENTER_LEFT);
|
||||||
|
@ -189,6 +193,21 @@ public class EntryCell extends TreeTableCell<Entry, Entry> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IntegerProperty getConfirmationsProperty() {
|
||||||
|
if(confirmationsProperty == null) {
|
||||||
|
confirmationsProperty = new SimpleIntegerProperty();
|
||||||
|
confirmationsProperty.addListener((observable, oldValue, newValue) -> {
|
||||||
|
if(newValue.intValue() >= BlockTransactionHash.BLOCKS_TO_CONFIRM) {
|
||||||
|
getStyleClass().remove("confirming");
|
||||||
|
confirmationsProperty.unbind();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return confirmationsProperty;
|
||||||
|
}
|
||||||
|
|
||||||
private static void increaseFee(TransactionEntry transactionEntry, boolean cancelTransaction) {
|
private static void increaseFee(TransactionEntry transactionEntry, boolean cancelTransaction) {
|
||||||
BlockTransaction blockTransaction = transactionEntry.getBlockTransaction();
|
BlockTransaction blockTransaction = transactionEntry.getBlockTransaction();
|
||||||
Map<BlockTransactionHashIndex, WalletNode> walletTxos = transactionEntry.getWallet().getWalletTxos();
|
Map<BlockTransactionHashIndex, WalletNode> walletTxos = transactionEntry.getWallet().getWalletTxos();
|
||||||
|
@ -722,13 +741,14 @@ public class EntryCell extends TreeTableCell<Entry, Entry> {
|
||||||
if(entry instanceof TransactionEntry) {
|
if(entry instanceof TransactionEntry) {
|
||||||
cell.getStyleClass().add("transaction-row");
|
cell.getStyleClass().add("transaction-row");
|
||||||
TransactionEntry transactionEntry = (TransactionEntry)entry;
|
TransactionEntry transactionEntry = (TransactionEntry)entry;
|
||||||
|
|
||||||
|
if(cell instanceof ConfirmationsListener confirmationsListener) {
|
||||||
if(transactionEntry.isConfirming()) {
|
if(transactionEntry.isConfirming()) {
|
||||||
cell.getStyleClass().add("confirming");
|
cell.getStyleClass().add("confirming");
|
||||||
transactionEntry.confirmationsProperty().addListener((observable, oldValue, newValue) -> {
|
confirmationsListener.getConfirmationsProperty().bind(transactionEntry.confirmationsProperty());
|
||||||
if(!transactionEntry.isConfirming()) {
|
} else {
|
||||||
cell.getStyleClass().remove("confirming");
|
confirmationsListener.getConfirmationsProperty().unbind();
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
} else if(entry instanceof NodeEntry) {
|
} else if(entry instanceof NodeEntry) {
|
||||||
cell.getStyleClass().add("node-row");
|
cell.getStyleClass().add("node-row");
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
package com.sparrowwallet.sparrow.control;
|
package com.sparrowwallet.sparrow.control;
|
||||||
|
|
||||||
|
import com.sparrowwallet.drongo.wallet.BlockTransactionHash;
|
||||||
import com.sparrowwallet.sparrow.wallet.Entry;
|
import com.sparrowwallet.sparrow.wallet.Entry;
|
||||||
|
import javafx.beans.property.IntegerProperty;
|
||||||
|
import javafx.beans.property.SimpleIntegerProperty;
|
||||||
import javafx.event.Event;
|
import javafx.event.Event;
|
||||||
import javafx.scene.control.*;
|
import javafx.scene.control.*;
|
||||||
import javafx.scene.control.cell.TextFieldTreeTableCell;
|
import javafx.scene.control.cell.TextFieldTreeTableCell;
|
||||||
|
@ -13,9 +16,11 @@ import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
class LabelCell extends TextFieldTreeTableCell<Entry, String> {
|
class LabelCell extends TextFieldTreeTableCell<Entry, String> implements ConfirmationsListener {
|
||||||
private static final Logger log = LoggerFactory.getLogger(LabelCell.class);
|
private static final Logger log = LoggerFactory.getLogger(LabelCell.class);
|
||||||
|
|
||||||
|
private IntegerProperty confirmationsProperty;
|
||||||
|
|
||||||
public LabelCell() {
|
public LabelCell() {
|
||||||
super(new DefaultStringConverter());
|
super(new DefaultStringConverter());
|
||||||
getStyleClass().add("label-cell");
|
getStyleClass().add("label-cell");
|
||||||
|
@ -81,6 +86,21 @@ class LabelCell extends TextFieldTreeTableCell<Entry, String> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IntegerProperty getConfirmationsProperty() {
|
||||||
|
if(confirmationsProperty == null) {
|
||||||
|
confirmationsProperty = new SimpleIntegerProperty();
|
||||||
|
confirmationsProperty.addListener((observable, oldValue, newValue) -> {
|
||||||
|
if(newValue.intValue() >= BlockTransactionHash.BLOCKS_TO_CONFIRM) {
|
||||||
|
getStyleClass().remove("confirming");
|
||||||
|
confirmationsProperty.unbind();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return confirmationsProperty;
|
||||||
|
}
|
||||||
|
|
||||||
private static class LabelContextMenu extends ContextMenu {
|
private static class LabelContextMenu extends ContextMenu {
|
||||||
public LabelContextMenu(Entry entry, String label) {
|
public LabelContextMenu(Entry entry, String label) {
|
||||||
MenuItem copyLabel = new MenuItem("Copy Label");
|
MenuItem copyLabel = new MenuItem("Copy Label");
|
||||||
|
|
|
@ -97,17 +97,6 @@ public class TransactionEntry extends Entry implements Comparable<TransactionEnt
|
||||||
return blockTransaction.getConfirmations(AppServices.getCurrentBlockHeight() == null ? getWallet().getStoredBlockHeight() : AppServices.getCurrentBlockHeight());
|
return blockTransaction.getConfirmations(AppServices.getCurrentBlockHeight() == null ? getWallet().getStoredBlockHeight() : AppServices.getCurrentBlockHeight());
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getConfirmationsDescription() {
|
|
||||||
int confirmations = getConfirmations();
|
|
||||||
if(confirmations == 0) {
|
|
||||||
return "Unconfirmed in mempool";
|
|
||||||
} else if(confirmations < BlockTransactionHash.BLOCKS_TO_FULLY_CONFIRM) {
|
|
||||||
return confirmations + " confirmation" + (confirmations == 1 ? "" : "s");
|
|
||||||
} else {
|
|
||||||
return BlockTransactionHash.BLOCKS_TO_FULLY_CONFIRM + "+ confirmations";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isComplete(Map<HashIndex, BlockTransactionHashIndex> walletTxos) {
|
public boolean isComplete(Map<HashIndex, BlockTransactionHashIndex> walletTxos) {
|
||||||
int validEntries = 0;
|
int validEntries = 0;
|
||||||
for(TransactionInput txInput : blockTransaction.getTransaction().getInputs()) {
|
for(TransactionInput txInput : blockTransaction.getTransaction().getInputs()) {
|
||||||
|
|
Loading…
Reference in a new issue