spend utxo improvements

This commit is contained in:
Craig Raw 2020-08-23 15:47:43 +02:00
parent 189ac75467
commit 53a590140d
8 changed files with 122 additions and 36 deletions

2
drongo

@ -1 +1 @@
Subproject commit e8bb733ea8a6e476982e5ea78c288105d0bd8644 Subproject commit 0fbce035a3083f1cd5dc9f168b0cd4365a75ce40

View file

@ -58,7 +58,7 @@ public class CoinLabel extends CopyableLabel {
setTooltip(tooltip); setTooltip(tooltip);
setContextMenu(contextMenu); setContextMenu(contextMenu);
String satsValue = String.format(Locale.ENGLISH, "%,d",value) + " sats"; String satsValue = String.format(Locale.ENGLISH, "%,d", value) + " sats";
String btcValue = BTC_FORMAT.format(value.doubleValue() / Transaction.SATOSHIS_PER_BITCOIN) + " BTC"; String btcValue = BTC_FORMAT.format(value.doubleValue() / Transaction.SATOSHIS_PER_BITCOIN) + " BTC";
BitcoinUnit unit = bitcoinUnit; BitcoinUnit unit = bitcoinUnit;

View file

@ -34,7 +34,7 @@ public class DateCell extends TreeTableCell<Entry, Entry> {
if(entry instanceof UtxoEntry) { if(entry instanceof UtxoEntry) {
UtxoEntry utxoEntry = (UtxoEntry)entry; UtxoEntry utxoEntry = (UtxoEntry)entry;
if(utxoEntry.getHashIndex().getHeight() <= 0) { if(utxoEntry.getHashIndex().getHeight() <= 0) {
setText("Unconfirmed"); setText("Unconfirmed " + (utxoEntry.isSpendable() ? "(Spendable)" : "(Not yet spendable)"));
} else { } else {
String date = DATE_FORMAT.format(utxoEntry.getHashIndex().getDate()); String date = DATE_FORMAT.format(utxoEntry.getHashIndex().getDate());
setText(date); setText(date);

View file

@ -225,9 +225,11 @@ class EntryCell extends TreeTableCell<Entry, Entry> {
public static void applyRowStyles(TreeTableCell<?, ?> cell, Entry entry) { public static void applyRowStyles(TreeTableCell<?, ?> cell, Entry entry) {
cell.getStyleClass().remove("transaction-row"); cell.getStyleClass().remove("transaction-row");
cell.getStyleClass().remove("node-row"); cell.getStyleClass().remove("node-row");
cell.getStyleClass().remove("utxo-row");
cell.getStyleClass().remove("address-cell"); cell.getStyleClass().remove("address-cell");
cell.getStyleClass().remove("hashindex-row"); cell.getStyleClass().remove("hashindex-row");
cell.getStyleClass().remove("spent"); cell.getStyleClass().remove("spent");
cell.getStyleClass().remove("unspendable");
if(entry != null) { if(entry != null) {
if(entry instanceof TransactionEntry) { if(entry instanceof TransactionEntry) {
@ -245,6 +247,10 @@ class EntryCell extends TreeTableCell<Entry, Entry> {
cell.getStyleClass().add("node-row"); cell.getStyleClass().add("node-row");
} else if(entry instanceof UtxoEntry) { } else if(entry instanceof UtxoEntry) {
cell.getStyleClass().add("utxo-row"); cell.getStyleClass().add("utxo-row");
UtxoEntry utxoEntry = (UtxoEntry)entry;
if(!utxoEntry.isSpendable()) {
cell.getStyleClass().add("unspendable");
}
} else if(entry instanceof HashIndexEntry) { } else if(entry instanceof HashIndexEntry) {
cell.getStyleClass().add("hashindex-row"); cell.getStyleClass().add("hashindex-row");
HashIndexEntry hashIndexEntry = (HashIndexEntry)entry; HashIndexEntry hashIndexEntry = (HashIndexEntry)entry;

View file

@ -1,19 +1,24 @@
package com.sparrowwallet.sparrow.wallet; package com.sparrowwallet.sparrow.wallet;
import com.google.common.eventbus.Subscribe; import com.google.common.eventbus.Subscribe;
import com.sparrowwallet.drongo.BitcoinUnit;
import com.sparrowwallet.drongo.protocol.Transaction;
import com.sparrowwallet.sparrow.EventManager; import com.sparrowwallet.sparrow.EventManager;
import com.sparrowwallet.sparrow.control.CoinLabel;
import com.sparrowwallet.sparrow.control.UtxosChart; import com.sparrowwallet.sparrow.control.UtxosChart;
import com.sparrowwallet.sparrow.control.UtxosTreeTable; import com.sparrowwallet.sparrow.control.UtxosTreeTable;
import com.sparrowwallet.sparrow.event.BitcoinUnitChangedEvent; import com.sparrowwallet.sparrow.event.*;
import com.sparrowwallet.sparrow.event.WalletEntryLabelChangedEvent; import com.sparrowwallet.sparrow.io.Config;
import com.sparrowwallet.sparrow.event.WalletHistoryChangedEvent; import javafx.application.Platform;
import com.sparrowwallet.sparrow.event.WalletNodesChangedEvent;
import javafx.collections.ListChangeListener; import javafx.collections.ListChangeListener;
import javafx.event.ActionEvent;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.fxml.Initializable; import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import java.net.URL; import java.net.URL;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.ResourceBundle; import java.util.ResourceBundle;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -22,6 +27,9 @@ public class UtxosController extends WalletFormController implements Initializab
@FXML @FXML
private UtxosTreeTable utxosTable; private UtxosTreeTable utxosTable;
@FXML
private Button sendSelected;
@FXML @FXML
private UtxosChart utxosChart; private UtxosChart utxosChart;
@ -34,13 +42,53 @@ public class UtxosController extends WalletFormController implements Initializab
public void initializeView() { public void initializeView() {
utxosTable.initialize(getWalletForm().getWalletUtxosEntry()); utxosTable.initialize(getWalletForm().getWalletUtxosEntry());
utxosChart.initialize(getWalletForm().getWalletUtxosEntry()); utxosChart.initialize(getWalletForm().getWalletUtxosEntry());
sendSelected.setDisable(true);
utxosTable.getSelectionModel().getSelectedIndices().addListener((ListChangeListener<Integer>) c -> { utxosTable.getSelectionModel().getSelectedIndices().addListener((ListChangeListener<Integer>) c -> {
List<Entry> selectedEntries = utxosTable.getSelectionModel().getSelectedCells().stream().map(tp -> tp.getTreeItem().getValue()).collect(Collectors.toList()); List<Entry> selectedEntries = utxosTable.getSelectionModel().getSelectedCells().stream().map(tp -> tp.getTreeItem().getValue()).collect(Collectors.toList());
utxosChart.select(selectedEntries); utxosChart.select(selectedEntries);
updateSendSelected(Config.get().getBitcoinUnit());
}); });
} }
private void updateSendSelected(BitcoinUnit unit) {
List<Entry> selectedEntries = utxosTable.getSelectionModel().getSelectedCells().stream().map(tp -> tp.getTreeItem().getValue())
.filter(entry -> ((HashIndexEntry)entry).isSpendable())
.collect(Collectors.toList());
sendSelected.setDisable(selectedEntries.isEmpty());
long selectedTotal = selectedEntries.stream().mapToLong(Entry::getValue).sum();
if(selectedTotal > 0) {
if(unit == null || unit.equals(BitcoinUnit.AUTO)) {
unit = (selectedTotal >= BitcoinUnit.getAutoThreshold() ? BitcoinUnit.BTC : BitcoinUnit.SATOSHIS);
}
if(unit.equals(BitcoinUnit.BTC)) {
sendSelected.setText("Send Selected (" + CoinLabel.getBTCFormat().format((double)selectedTotal / Transaction.SATOSHIS_PER_BITCOIN) + " BTC)");
} else {
sendSelected.setText("Send Selected (" + String.format(Locale.ENGLISH, "%,d", selectedTotal) + " sats)");
}
} else {
sendSelected.setText("Send Selected");
}
}
public void sendSelected(ActionEvent event) {
List<HashIndexEntry> utxoEntries = utxosTable.getSelectionModel().getSelectedCells().stream()
.map(tp -> tp.getTreeItem().getValue())
.filter(e -> e instanceof HashIndexEntry)
.map(e -> (HashIndexEntry)e)
.filter(e -> e.getType().equals(HashIndexEntry.Type.OUTPUT) && e.isSpendable())
.collect(Collectors.toList());
EventManager.get().post(new SendActionEvent(utxoEntries));
Platform.runLater(() -> EventManager.get().post(new SpendUtxoEvent(utxoEntries)));
}
public void clear(ActionEvent event) {
utxosTable.getSelectionModel().clearSelection();
}
@Subscribe @Subscribe
public void walletNodesChanged(WalletNodesChangedEvent event) { public void walletNodesChanged(WalletNodesChangedEvent event) {
if(event.getWallet().equals(walletForm.getWallet())) { if(event.getWallet().equals(walletForm.getWallet())) {
@ -75,5 +123,6 @@ public class UtxosController extends WalletFormController implements Initializab
public void bitcoinUnitChanged(BitcoinUnitChangedEvent event) { public void bitcoinUnitChanged(BitcoinUnitChangedEvent event) {
utxosTable.setBitcoinUnit(getWalletForm().getWallet(), event.getBitcoinUnit()); utxosTable.setBitcoinUnit(getWalletForm().getWallet(), event.getBitcoinUnit());
utxosChart.setBitcoinUnit(getWalletForm().getWallet(), event.getBitcoinUnit()); utxosChart.setBitcoinUnit(getWalletForm().getWallet(), event.getBitcoinUnit());
updateSendSelected(event.getBitcoinUnit());
} }
} }

View file

@ -4,6 +4,10 @@
-fx-padding: 10 0 10 0; -fx-padding: 10 0 10 0;
} }
.utxos-buttons-box {
-fx-padding: 15 0 0 0;
}
.chart-bar { .chart-bar {
-fx-bar-fill: rgba(105, 108, 119, 0.6); -fx-bar-fill: rgba(105, 108, 119, 0.6);
} }

View file

@ -12,17 +12,20 @@
<?import javafx.scene.chart.CategoryAxis?> <?import javafx.scene.chart.CategoryAxis?>
<?import javafx.scene.chart.NumberAxis?> <?import javafx.scene.chart.NumberAxis?>
<?import com.sparrowwallet.sparrow.control.UtxosChart?> <?import com.sparrowwallet.sparrow.control.UtxosChart?>
<?import org.controlsfx.glyphfont.Glyph?>
<GridPane hgap="10.0" vgap="10.0" stylesheets="@utxos.css, @wallet.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.UtxosController"> <BorderPane stylesheets="@utxos.css, @wallet.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.UtxosController">
<padding> <padding>
<Insets left="25.0" right="25.0" top="15.0" bottom="25.0" /> <Insets left="25.0" right="25.0" top="15.0" bottom="25.0" />
</padding> </padding>
<center>
<GridPane hgap="10.0" vgap="10.0">
<columnConstraints> <columnConstraints>
<ColumnConstraints percentWidth="100.0" /> <ColumnConstraints percentWidth="100.0" />
</columnConstraints> </columnConstraints>
<rowConstraints> <rowConstraints>
<RowConstraints percentHeight="50" /> <RowConstraints percentHeight="60" />
<RowConstraints percentHeight="50" /> <RowConstraints percentHeight="40" />
</rowConstraints> </rowConstraints>
<BorderPane GridPane.columnIndex="0" GridPane.rowIndex="0"> <BorderPane GridPane.columnIndex="0" GridPane.rowIndex="0">
<top> <top>
@ -31,6 +34,16 @@
<center> <center>
<UtxosTreeTable fx:id="utxosTable" /> <UtxosTreeTable fx:id="utxosTable" />
</center> </center>
<bottom>
<HBox styleClass="utxos-buttons-box" spacing="20" alignment="BOTTOM_RIGHT">
<Button text="Clear" onAction="#clear"/>
<Button fx:id="sendSelected" text="Send Selected" graphicTextGap="5" onAction="#sendSelected">
<graphic>
<Glyph fontFamily="FontAwesome" icon="SEND" fontSize="12" />
</graphic>
</Button>
</HBox>
</bottom>
</BorderPane> </BorderPane>
<BorderPane GridPane.columnIndex="0" GridPane.rowIndex="1"> <BorderPane GridPane.columnIndex="0" GridPane.rowIndex="1">
<center> <center>
@ -44,4 +57,6 @@
</UtxosChart> </UtxosChart>
</center> </center>
</BorderPane> </BorderPane>
</GridPane> </GridPane>
</center>
</BorderPane>

View file

@ -45,6 +45,18 @@
-fx-text-fill: #696c77; -fx-text-fill: #696c77;
} }
.utxo-row.unspendable {
-fx-text-fill: #a0a1a7;
}
.tree-table-row-cell:selected .utxo-row.unspendable {
-fx-text-fill: #696c77;
}
.tree-table-view:focused:row-selection .tree-table-row-cell:selected .utxo-row.unspendable {
-fx-text-fill: derive(white, -15%);
}
.tree-table-row-cell:selected .hashindex-row, .tree-table-row-cell:selected .transaction-row { .tree-table-row-cell:selected .hashindex-row, .tree-table-row-cell:selected .transaction-row {
-fx-text-fill: white; -fx-text-fill: white;
} }