mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2024-12-24 12:46:45 +00:00
expand transaction diagram in popup on click
This commit is contained in:
parent
9bf53ab0cd
commit
ca928fc136
22 changed files with 329 additions and 47 deletions
|
@ -424,7 +424,9 @@ public class AppController implements Initializable {
|
||||||
|
|
||||||
Stage stage = new Stage();
|
Stage stage = new Stage();
|
||||||
stage.setTitle("About " + MainApp.APP_NAME);
|
stage.setTitle("About " + MainApp.APP_NAME);
|
||||||
stage.initStyle(org.controlsfx.tools.Platform.getCurrent() == org.controlsfx.tools.Platform.OSX ? StageStyle.UNDECORATED : StageStyle.DECORATED);
|
stage.initStyle(StageStyle.UNDECORATED);
|
||||||
|
stage.initOwner(tabs.getScene().getWindow());
|
||||||
|
stage.initModality(Modality.WINDOW_MODAL);
|
||||||
stage.setResizable(false);
|
stage.setResizable(false);
|
||||||
Scene scene = new Scene(root);
|
Scene scene = new Scene(root);
|
||||||
AppServices.onEscapePressed(scene, stage::close);
|
AppServices.onEscapePressed(scene, stage::close);
|
||||||
|
|
|
@ -6,6 +6,7 @@ import com.sparrowwallet.sparrow.io.Config;
|
||||||
import javafx.beans.property.LongProperty;
|
import javafx.beans.property.LongProperty;
|
||||||
import javafx.beans.property.SimpleLongProperty;
|
import javafx.beans.property.SimpleLongProperty;
|
||||||
import javafx.scene.control.ContextMenu;
|
import javafx.scene.control.ContextMenu;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
import javafx.scene.control.MenuItem;
|
import javafx.scene.control.MenuItem;
|
||||||
import javafx.scene.control.Tooltip;
|
import javafx.scene.control.Tooltip;
|
||||||
import javafx.scene.input.Clipboard;
|
import javafx.scene.input.Clipboard;
|
||||||
|
@ -15,7 +16,7 @@ import java.text.DecimalFormat;
|
||||||
import java.text.DecimalFormatSymbols;
|
import java.text.DecimalFormatSymbols;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
public class CoinLabel extends CopyableLabel {
|
public class CoinLabel extends Label {
|
||||||
public static final DecimalFormat BTC_FORMAT = new DecimalFormat("0", DecimalFormatSymbols.getInstance(Locale.ENGLISH));
|
public static final DecimalFormat BTC_FORMAT = new DecimalFormat("0", DecimalFormatSymbols.getInstance(Locale.ENGLISH));
|
||||||
|
|
||||||
private final LongProperty valueProperty = new SimpleLongProperty(-1);
|
private final LongProperty valueProperty = new SimpleLongProperty(-1);
|
||||||
|
@ -28,7 +29,6 @@ public class CoinLabel extends CopyableLabel {
|
||||||
|
|
||||||
public CoinLabel(String text) {
|
public CoinLabel(String text) {
|
||||||
super(text);
|
super(text);
|
||||||
BTC_FORMAT.setMaximumFractionDigits(8);
|
|
||||||
valueProperty().addListener((observable, oldValue, newValue) -> setValueAsText((Long)newValue, Config.get().getBitcoinUnit()));
|
valueProperty().addListener((observable, oldValue, newValue) -> setValueAsText((Long)newValue, Config.get().getBitcoinUnit()));
|
||||||
tooltip = new Tooltip();
|
tooltip = new Tooltip();
|
||||||
contextMenu = new CoinContextMenu();
|
contextMenu = new CoinContextMenu();
|
||||||
|
@ -77,7 +77,7 @@ public class CoinLabel extends CopyableLabel {
|
||||||
|
|
||||||
private class CoinContextMenu extends ContextMenu {
|
private class CoinContextMenu extends ContextMenu {
|
||||||
public CoinContextMenu() {
|
public CoinContextMenu() {
|
||||||
MenuItem copySatsValue = new MenuItem("Copy Value in Satoshis");
|
MenuItem copySatsValue = new MenuItem("Copy Value in sats");
|
||||||
copySatsValue.setOnAction(AE -> {
|
copySatsValue.setOnAction(AE -> {
|
||||||
hide();
|
hide();
|
||||||
ClipboardContent content = new ClipboardContent();
|
ClipboardContent content = new ClipboardContent();
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
package com.sparrowwallet.sparrow.control;
|
||||||
|
|
||||||
|
import com.sparrowwallet.drongo.BitcoinUnit;
|
||||||
|
import com.sparrowwallet.drongo.protocol.Transaction;
|
||||||
|
import com.sparrowwallet.sparrow.io.Config;
|
||||||
|
import javafx.beans.property.LongProperty;
|
||||||
|
import javafx.beans.property.SimpleLongProperty;
|
||||||
|
import javafx.scene.control.ContextMenu;
|
||||||
|
import javafx.scene.control.MenuItem;
|
||||||
|
import javafx.scene.control.Tooltip;
|
||||||
|
import javafx.scene.input.Clipboard;
|
||||||
|
import javafx.scene.input.ClipboardContent;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
public class CopyableCoinLabel extends CopyableLabel {
|
||||||
|
private final LongProperty valueProperty = new SimpleLongProperty(-1);
|
||||||
|
private final Tooltip tooltip;
|
||||||
|
private final CoinContextMenu contextMenu;
|
||||||
|
|
||||||
|
public CopyableCoinLabel() {
|
||||||
|
this("Unknown");
|
||||||
|
}
|
||||||
|
|
||||||
|
public CopyableCoinLabel(String text) {
|
||||||
|
super(text);
|
||||||
|
valueProperty().addListener((observable, oldValue, newValue) -> setValueAsText((Long)newValue, Config.get().getBitcoinUnit()));
|
||||||
|
tooltip = new Tooltip();
|
||||||
|
contextMenu = new CoinContextMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
public final LongProperty valueProperty() {
|
||||||
|
return valueProperty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final long getValue() {
|
||||||
|
return valueProperty.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void setValue(long value) {
|
||||||
|
this.valueProperty.set(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void refresh() {
|
||||||
|
refresh(Config.get().getBitcoinUnit());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void refresh(BitcoinUnit bitcoinUnit) {
|
||||||
|
setValueAsText(getValue(), bitcoinUnit);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setValueAsText(Long value, BitcoinUnit bitcoinUnit) {
|
||||||
|
setTooltip(tooltip);
|
||||||
|
setContextMenu(contextMenu);
|
||||||
|
|
||||||
|
String satsValue = String.format(Locale.ENGLISH, "%,d", value) + " sats";
|
||||||
|
String btcValue = CoinLabel.getBTCFormat().format(value.doubleValue() / Transaction.SATOSHIS_PER_BITCOIN) + " BTC";
|
||||||
|
|
||||||
|
BitcoinUnit unit = bitcoinUnit;
|
||||||
|
if(unit == null || unit.equals(BitcoinUnit.AUTO)) {
|
||||||
|
unit = (value >= BitcoinUnit.getAutoThreshold() ? BitcoinUnit.BTC : BitcoinUnit.SATOSHIS);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(unit.equals(BitcoinUnit.BTC)) {
|
||||||
|
tooltip.setText(satsValue);
|
||||||
|
setText(btcValue);
|
||||||
|
} else {
|
||||||
|
tooltip.setText(btcValue);
|
||||||
|
setText(satsValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class CoinContextMenu extends ContextMenu {
|
||||||
|
public CoinContextMenu() {
|
||||||
|
MenuItem copySatsValue = new MenuItem("Copy Value in sats");
|
||||||
|
copySatsValue.setOnAction(AE -> {
|
||||||
|
hide();
|
||||||
|
ClipboardContent content = new ClipboardContent();
|
||||||
|
content.putString(Long.toString(getValue()));
|
||||||
|
Clipboard.getSystemClipboard().setContent(content);
|
||||||
|
});
|
||||||
|
|
||||||
|
MenuItem copyBtcValue = new MenuItem("Copy Value in BTC");
|
||||||
|
copyBtcValue.setOnAction(AE -> {
|
||||||
|
hide();
|
||||||
|
ClipboardContent content = new ClipboardContent();
|
||||||
|
content.putString(CoinLabel.getBTCFormat().format((double)getValue() / Transaction.SATOSHIS_PER_BITCOIN));
|
||||||
|
Clipboard.getSystemClipboard().setContent(content);
|
||||||
|
});
|
||||||
|
|
||||||
|
getItems().addAll(copySatsValue, copyBtcValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -34,4 +34,18 @@ public class TextUtils {
|
||||||
helper.setText(DEFAULT_TEXT);
|
helper.setText(DEFAULT_TEXT);
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static double computeTextHeight(Font font, String text) {
|
||||||
|
helper.setText(text);
|
||||||
|
helper.setFont(font);
|
||||||
|
|
||||||
|
helper.setWrappingWidth(0.0D);
|
||||||
|
helper.setLineSpacing(0.0D);
|
||||||
|
double d = Math.ceil(helper.getLayoutBounds().getHeight());
|
||||||
|
|
||||||
|
helper.setWrappingWidth(DEFAULT_WRAPPING_WIDTH);
|
||||||
|
helper.setLineSpacing(DEFAULT_LINE_SPACING);
|
||||||
|
helper.setText(DEFAULT_TEXT);
|
||||||
|
return d;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,18 +18,24 @@ import javafx.beans.property.BooleanProperty;
|
||||||
import javafx.beans.property.ObjectProperty;
|
import javafx.beans.property.ObjectProperty;
|
||||||
import javafx.beans.property.SimpleBooleanProperty;
|
import javafx.beans.property.SimpleBooleanProperty;
|
||||||
import javafx.beans.property.SimpleObjectProperty;
|
import javafx.beans.property.SimpleObjectProperty;
|
||||||
|
import javafx.event.EventHandler;
|
||||||
import javafx.geometry.Insets;
|
import javafx.geometry.Insets;
|
||||||
import javafx.geometry.Pos;
|
import javafx.geometry.Pos;
|
||||||
import javafx.scene.Group;
|
import javafx.scene.Group;
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
|
import javafx.scene.Scene;
|
||||||
import javafx.scene.control.Button;
|
import javafx.scene.control.Button;
|
||||||
import javafx.scene.control.ContentDisplay;
|
import javafx.scene.control.ContentDisplay;
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
import javafx.scene.control.Tooltip;
|
import javafx.scene.control.Tooltip;
|
||||||
|
import javafx.scene.input.MouseEvent;
|
||||||
import javafx.scene.layout.*;
|
import javafx.scene.layout.*;
|
||||||
import javafx.scene.shape.Circle;
|
import javafx.scene.shape.Circle;
|
||||||
import javafx.scene.shape.CubicCurve;
|
import javafx.scene.shape.CubicCurve;
|
||||||
import javafx.scene.shape.Line;
|
import javafx.scene.shape.Line;
|
||||||
|
import javafx.stage.Modality;
|
||||||
|
import javafx.stage.Stage;
|
||||||
|
import javafx.stage.StageStyle;
|
||||||
import javafx.util.Duration;
|
import javafx.util.Duration;
|
||||||
import org.controlsfx.glyphfont.FontAwesome;
|
import org.controlsfx.glyphfont.FontAwesome;
|
||||||
import org.controlsfx.glyphfont.Glyph;
|
import org.controlsfx.glyphfont.Glyph;
|
||||||
|
@ -40,16 +46,68 @@ import java.util.stream.Collectors;
|
||||||
public class TransactionDiagram extends GridPane {
|
public class TransactionDiagram extends GridPane {
|
||||||
private static final int MAX_UTXOS = 8;
|
private static final int MAX_UTXOS = 8;
|
||||||
private static final int REDUCED_MAX_UTXOS = MAX_UTXOS - 2;
|
private static final int REDUCED_MAX_UTXOS = MAX_UTXOS - 2;
|
||||||
|
private static final int EXPANDED_MAX_UTXOS = 20;
|
||||||
private static final int MAX_PAYMENTS = 6;
|
private static final int MAX_PAYMENTS = 6;
|
||||||
private static final int REDUCED_MAX_PAYMENTS = MAX_PAYMENTS - 2;
|
private static final int REDUCED_MAX_PAYMENTS = MAX_PAYMENTS - 2;
|
||||||
|
private static final int EXPANDED_MAX_PAYMENTS = 18;
|
||||||
private static final double DIAGRAM_HEIGHT = 210.0;
|
private static final double DIAGRAM_HEIGHT = 210.0;
|
||||||
private static final double REDUCED_DIAGRAM_HEIGHT = DIAGRAM_HEIGHT - 60;
|
private static final double REDUCED_DIAGRAM_HEIGHT = DIAGRAM_HEIGHT - 60;
|
||||||
|
private static final double EXPANDED_DIAGRAM_HEIGHT = 500;
|
||||||
private static final int TOOLTIP_SHOW_DELAY = 50;
|
private static final int TOOLTIP_SHOW_DELAY = 50;
|
||||||
private static final int RELATIVE_SIZE_MAX_RADIUS = 7;
|
private static final int RELATIVE_SIZE_MAX_RADIUS = 7;
|
||||||
|
private static final int ROW_HEIGHT = 27;
|
||||||
|
|
||||||
private WalletTransaction walletTx;
|
private WalletTransaction walletTx;
|
||||||
private final BooleanProperty finalProperty = new SimpleBooleanProperty(false);
|
private final BooleanProperty finalProperty = new SimpleBooleanProperty(false);
|
||||||
private final ObjectProperty<OptimizationStrategy> optimizationStrategyProperty = new SimpleObjectProperty<>(OptimizationStrategy.EFFICIENCY);
|
private final ObjectProperty<OptimizationStrategy> optimizationStrategyProperty = new SimpleObjectProperty<>(OptimizationStrategy.EFFICIENCY);
|
||||||
|
private boolean expanded;
|
||||||
|
private TransactionDiagram expandedDiagram;
|
||||||
|
|
||||||
|
private final EventHandler<MouseEvent> expandedDiagramHandler = new EventHandler<>() {
|
||||||
|
@Override
|
||||||
|
public void handle(MouseEvent event) {
|
||||||
|
if(!event.isConsumed()) {
|
||||||
|
Stage stage = new Stage();
|
||||||
|
stage.setTitle(walletTx.getPayments().iterator().next().getLabel());
|
||||||
|
stage.initStyle(StageStyle.UNDECORATED);
|
||||||
|
stage.initOwner(TransactionDiagram.this.getScene().getWindow());
|
||||||
|
stage.initModality(Modality.WINDOW_MODAL);
|
||||||
|
stage.setResizable(false);
|
||||||
|
|
||||||
|
VBox vBox = new VBox(20);
|
||||||
|
vBox.getStylesheets().add(AppServices.class.getResource("general.css").toExternalForm());
|
||||||
|
vBox.getStylesheets().add(AppServices.class.getResource("wallet/wallet.css").toExternalForm());
|
||||||
|
vBox.getStylesheets().add(AppServices.class.getResource("wallet/send.css").toExternalForm());
|
||||||
|
vBox.setPadding(new Insets(20, 40, 20, 50));
|
||||||
|
|
||||||
|
expandedDiagram = new TransactionDiagram();
|
||||||
|
expandedDiagram.setId("transactionDiagram");
|
||||||
|
expandedDiagram.setExpanded(true);
|
||||||
|
updateExpandedDiagram();
|
||||||
|
|
||||||
|
HBox buttonBox = new HBox();
|
||||||
|
buttonBox.setAlignment(Pos.CENTER_RIGHT);
|
||||||
|
Button button = new Button("Close");
|
||||||
|
button.setOnAction(e -> {
|
||||||
|
stage.close();
|
||||||
|
});
|
||||||
|
buttonBox.getChildren().add(button);
|
||||||
|
vBox.getChildren().addAll(expandedDiagram, buttonBox);
|
||||||
|
|
||||||
|
Scene scene = new Scene(vBox);
|
||||||
|
AppServices.onEscapePressed(scene, stage::close);
|
||||||
|
AppServices.setStageIcon(stage);
|
||||||
|
stage.setScene(scene);
|
||||||
|
stage.setOnShowing(e -> {
|
||||||
|
AppServices.moveToActiveWindowScreen(stage, 600, 460);
|
||||||
|
});
|
||||||
|
stage.setOnHidden(e -> {
|
||||||
|
expandedDiagram = null;
|
||||||
|
});
|
||||||
|
stage.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
public void update(WalletTransaction walletTx) {
|
public void update(WalletTransaction walletTx) {
|
||||||
setMinHeight(getDiagramHeight());
|
setMinHeight(getDiagramHeight());
|
||||||
|
@ -60,6 +118,10 @@ public class TransactionDiagram extends GridPane {
|
||||||
} else {
|
} else {
|
||||||
this.walletTx = walletTx;
|
this.walletTx = walletTx;
|
||||||
update();
|
update();
|
||||||
|
setOnMouseClicked(expandedDiagramHandler);
|
||||||
|
if(expandedDiagram != null) {
|
||||||
|
updateExpandedDiagram();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,6 +149,24 @@ public class TransactionDiagram extends GridPane {
|
||||||
getChildren().clear();
|
getChildren().clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateExpandedDiagram() {
|
||||||
|
expandedDiagram.setFinal(isFinal());
|
||||||
|
expandedDiagram.setOptimizationStrategy(getOptimizationStrategy());
|
||||||
|
expandedDiagram.walletTx = walletTx;
|
||||||
|
|
||||||
|
List<Map<BlockTransactionHashIndex, WalletNode>> utxoSets = expandedDiagram.getDisplayedUtxoSets();
|
||||||
|
int maxSetSize = utxoSets.stream().mapToInt(Map::size).max().orElse(0);
|
||||||
|
int maxRows = Math.max(maxSetSize * utxoSets.size(), walletTx.getPayments().size() + 2);
|
||||||
|
double diagramHeight = Math.max(DIAGRAM_HEIGHT, Math.min(EXPANDED_DIAGRAM_HEIGHT, maxRows * ROW_HEIGHT));
|
||||||
|
expandedDiagram.setMinHeight(diagramHeight);
|
||||||
|
expandedDiagram.setMaxHeight(diagramHeight);
|
||||||
|
expandedDiagram.update();
|
||||||
|
|
||||||
|
if(expandedDiagram.getScene() != null && expandedDiagram.getScene().getWindow() instanceof Stage stage) {
|
||||||
|
stage.sizeToScene();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void update() {
|
public void update() {
|
||||||
List<Map<BlockTransactionHashIndex, WalletNode>> displayedUtxoSets = getDisplayedUtxoSets();
|
List<Map<BlockTransactionHashIndex, WalletNode>> displayedUtxoSets = getDisplayedUtxoSets();
|
||||||
|
|
||||||
|
@ -287,17 +367,19 @@ public class TransactionDiagram extends GridPane {
|
||||||
|
|
||||||
private Pane getInputsLabels(List<Map<BlockTransactionHashIndex, WalletNode>> displayedUtxoSets) {
|
private Pane getInputsLabels(List<Map<BlockTransactionHashIndex, WalletNode>> displayedUtxoSets) {
|
||||||
VBox inputsBox = new VBox();
|
VBox inputsBox = new VBox();
|
||||||
inputsBox.setMaxWidth(150);
|
inputsBox.setMaxWidth(isExpanded() ? 300 : 150);
|
||||||
inputsBox.setPrefWidth(150);
|
inputsBox.setPrefWidth(isExpanded() ? 230 : 150);
|
||||||
inputsBox.setPadding(new Insets(0, 10, 0, 10));
|
inputsBox.setPadding(new Insets(0, 10, 0, 10));
|
||||||
inputsBox.minHeightProperty().bind(minHeightProperty());
|
inputsBox.minHeightProperty().bind(minHeightProperty());
|
||||||
inputsBox.setAlignment(Pos.CENTER_RIGHT);
|
inputsBox.setAlignment(Pos.CENTER_RIGHT);
|
||||||
inputsBox.getChildren().add(createSpacer());
|
inputsBox.getChildren().add(createSpacer());
|
||||||
|
double labelHeight = TextUtils.computeTextHeight(AppServices.getMonospaceFont(), "0") + 1;
|
||||||
for(Map<BlockTransactionHashIndex, WalletNode> displayedUtxos : displayedUtxoSets) {
|
for(Map<BlockTransactionHashIndex, WalletNode> displayedUtxos : displayedUtxoSets) {
|
||||||
for(BlockTransactionHashIndex input : displayedUtxos.keySet()) {
|
for(BlockTransactionHashIndex input : displayedUtxos.keySet()) {
|
||||||
WalletNode walletNode = displayedUtxos.get(input);
|
WalletNode walletNode = displayedUtxos.get(input);
|
||||||
String desc = getInputDescription(input);
|
String desc = getInputDescription(input);
|
||||||
Label label = new Label(desc);
|
Label label = new Label(desc);
|
||||||
|
label.setPrefHeight(labelHeight);
|
||||||
label.getStyleClass().add("utxo-label");
|
label.getStyleClass().add("utxo-label");
|
||||||
|
|
||||||
Button excludeUtxoButton = new Button("");
|
Button excludeUtxoButton = new Button("");
|
||||||
|
@ -307,8 +389,10 @@ public class TransactionDiagram extends GridPane {
|
||||||
});
|
});
|
||||||
|
|
||||||
Tooltip tooltip = new Tooltip();
|
Tooltip tooltip = new Tooltip();
|
||||||
|
Long inputValue = null;
|
||||||
if(walletNode != null) {
|
if(walletNode != null) {
|
||||||
tooltip.setText("Spending " + getSatsValue(input.getValue()) + " sats from " + (isFinal() ? walletTx.getWallet().getFullDisplayName() : "") + " " + walletNode + "\n" + input.getHashAsString() + ":" + input.getIndex() + "\n" + walletTx.getWallet().getAddress(walletNode));
|
inputValue = input.getValue();
|
||||||
|
tooltip.setText("Spending " + getSatsValue(inputValue) + " sats from " + (isFinal() ? walletTx.getWallet().getFullDisplayName() : "") + " " + walletNode + "\n" + input.getHashAsString() + ":" + input.getIndex() + "\n" + walletTx.getWallet().getAddress(walletNode));
|
||||||
tooltip.getStyleClass().add("input-label");
|
tooltip.getStyleClass().add("input-label");
|
||||||
|
|
||||||
if(input.getLabel() == null || input.getLabel().isEmpty()) {
|
if(input.getLabel() == null || input.getLabel().isEmpty()) {
|
||||||
|
@ -335,13 +419,16 @@ public class TransactionDiagram extends GridPane {
|
||||||
label.setGraphic(walletTx.isTwoPersonCoinjoin() ? getQuestionGlyph() : getWarningGlyph());
|
label.setGraphic(walletTx.isTwoPersonCoinjoin() ? getQuestionGlyph() : getWarningGlyph());
|
||||||
label.setOnMouseClicked(event -> {
|
label.setOnMouseClicked(event -> {
|
||||||
EventManager.get().post(new SorobanInitiatedEvent(walletTx.getWallet()));
|
EventManager.get().post(new SorobanInitiatedEvent(walletTx.getWallet()));
|
||||||
|
closeExpanded();
|
||||||
|
event.consume();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
if(walletTx.getInputTransactions() != null && walletTx.getInputTransactions().get(input.getHash()) != null) {
|
if(walletTx.getInputTransactions() != null && walletTx.getInputTransactions().get(input.getHash()) != null) {
|
||||||
BlockTransaction blockTransaction = walletTx.getInputTransactions().get(input.getHash());
|
BlockTransaction blockTransaction = walletTx.getInputTransactions().get(input.getHash());
|
||||||
TransactionOutput txOutput = blockTransaction.getTransaction().getOutputs().get((int) input.getIndex());
|
TransactionOutput txOutput = blockTransaction.getTransaction().getOutputs().get((int) input.getIndex());
|
||||||
Address fromAddress = txOutput.getScript().getToAddress();
|
Address fromAddress = txOutput.getScript().getToAddress();
|
||||||
tooltip.setText("Input of " + getSatsValue(txOutput.getValue()) + " sats\n" + input.getHashAsString() + ":" + input.getIndex() + (fromAddress != null ? "\n" + fromAddress : ""));
|
inputValue = txOutput.getValue();
|
||||||
|
tooltip.setText("Input of " + getSatsValue(inputValue) + " sats\n" + input.getHashAsString() + ":" + input.getIndex() + (fromAddress != null ? "\n" + fromAddress : ""));
|
||||||
} else {
|
} else {
|
||||||
tooltip.setText(input.getHashAsString() + ":" + input.getIndex());
|
tooltip.setText(input.getHashAsString() + ":" + input.getIndex());
|
||||||
}
|
}
|
||||||
|
@ -355,7 +442,21 @@ public class TransactionDiagram extends GridPane {
|
||||||
label.setTooltip(tooltip);
|
label.setTooltip(tooltip);
|
||||||
}
|
}
|
||||||
|
|
||||||
inputsBox.getChildren().add(label);
|
HBox inputBox = new HBox();
|
||||||
|
inputBox.setAlignment(Pos.CENTER_RIGHT);
|
||||||
|
inputBox.getChildren().add(label);
|
||||||
|
|
||||||
|
if(isExpanded() && inputValue != null) {
|
||||||
|
label.setMinWidth(120);
|
||||||
|
Region region = new Region();
|
||||||
|
HBox.setHgrow(region, Priority.ALWAYS);
|
||||||
|
CoinLabel amountLabel = new CoinLabel();
|
||||||
|
amountLabel.setValue(inputValue);
|
||||||
|
amountLabel.setMinWidth(TextUtils.computeTextWidth(amountLabel.getFont(), amountLabel.getText(), 0.0D) + 2);
|
||||||
|
inputBox.getChildren().addAll(region, amountLabel);
|
||||||
|
}
|
||||||
|
|
||||||
|
inputsBox.getChildren().add(inputBox);
|
||||||
inputsBox.getChildren().add(createSpacer());
|
inputsBox.getChildren().add(createSpacer());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -505,7 +606,8 @@ public class TransactionDiagram extends GridPane {
|
||||||
|
|
||||||
private Pane getOutputsLabels(List<Payment> displayedPayments) {
|
private Pane getOutputsLabels(List<Payment> displayedPayments) {
|
||||||
VBox outputsBox = new VBox();
|
VBox outputsBox = new VBox();
|
||||||
outputsBox.setMaxWidth(150);
|
outputsBox.setMaxWidth(isExpanded() ? 350 : 150);
|
||||||
|
outputsBox.setPrefWidth(isExpanded() ? 230 : 150);
|
||||||
outputsBox.setPadding(new Insets(0, 20, 0, 10));
|
outputsBox.setPadding(new Insets(0, 20, 0, 10));
|
||||||
outputsBox.setAlignment(Pos.CENTER_LEFT);
|
outputsBox.setAlignment(Pos.CENTER_LEFT);
|
||||||
outputsBox.getChildren().add(createSpacer());
|
outputsBox.getChildren().add(createSpacer());
|
||||||
|
@ -527,7 +629,20 @@ public class TransactionDiagram extends GridPane {
|
||||||
recipientTooltip.setShowDelay(new Duration(TOOLTIP_SHOW_DELAY));
|
recipientTooltip.setShowDelay(new Duration(TOOLTIP_SHOW_DELAY));
|
||||||
recipientTooltip.setShowDuration(Duration.INDEFINITE);
|
recipientTooltip.setShowDuration(Duration.INDEFINITE);
|
||||||
recipientLabel.setTooltip(recipientTooltip);
|
recipientLabel.setTooltip(recipientTooltip);
|
||||||
outputNodes.add(new OutputNode(recipientLabel, payment.getAddress(), payment.getAmount()));
|
HBox paymentBox = new HBox();
|
||||||
|
paymentBox.setAlignment(Pos.CENTER_LEFT);
|
||||||
|
paymentBox.getChildren().add(recipientLabel);
|
||||||
|
if(isExpanded()) {
|
||||||
|
Region region = new Region();
|
||||||
|
region.setMinWidth(20);
|
||||||
|
HBox.setHgrow(region, Priority.ALWAYS);
|
||||||
|
CoinLabel amountLabel = new CoinLabel();
|
||||||
|
amountLabel.setValue(payment.getAmount());
|
||||||
|
amountLabel.setMinWidth(TextUtils.computeTextWidth(amountLabel.getFont(), amountLabel.getText(), 0.0D) + 2);
|
||||||
|
paymentBox.getChildren().addAll(region, amountLabel);
|
||||||
|
}
|
||||||
|
|
||||||
|
outputNodes.add(new OutputNode(paymentBox, payment.getAddress(), payment.getAmount()));
|
||||||
}
|
}
|
||||||
|
|
||||||
for(Map.Entry<WalletNode, Long> changeEntry : walletTx.getChangeMap().entrySet()) {
|
for(Map.Entry<WalletNode, Long> changeEntry : walletTx.getChangeMap().entrySet()) {
|
||||||
|
@ -536,6 +651,7 @@ public class TransactionDiagram extends GridPane {
|
||||||
boolean overGapLimit = (changeNode.getIndex() - defaultChangeNode.getIndex()) > walletTx.getWallet().getGapLimit();
|
boolean overGapLimit = (changeNode.getIndex() - defaultChangeNode.getIndex()) > walletTx.getWallet().getGapLimit();
|
||||||
|
|
||||||
HBox actionBox = new HBox();
|
HBox actionBox = new HBox();
|
||||||
|
actionBox.setAlignment(Pos.CENTER_LEFT);
|
||||||
Address changeAddress = walletTx.getChangeAddress(changeNode);
|
Address changeAddress = walletTx.getChangeAddress(changeNode);
|
||||||
String changeDesc = changeAddress.toString().substring(0, 8) + "...";
|
String changeDesc = changeAddress.toString().substring(0, 8) + "...";
|
||||||
Label changeLabel = new Label(changeDesc, overGapLimit ? getChangeWarningGlyph() : getChangeGlyph());
|
Label changeLabel = new Label(changeDesc, overGapLimit ? getChangeWarningGlyph() : getChangeGlyph());
|
||||||
|
@ -563,6 +679,17 @@ public class TransactionDiagram extends GridPane {
|
||||||
actionBox.getChildren().add(replaceChangeLabel);
|
actionBox.getChildren().add(replaceChangeLabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(isExpanded()) {
|
||||||
|
changeLabel.setMinWidth(120);
|
||||||
|
Region region = new Region();
|
||||||
|
region.setMinWidth(20);
|
||||||
|
HBox.setHgrow(region, Priority.ALWAYS);
|
||||||
|
CoinLabel amountLabel = new CoinLabel();
|
||||||
|
amountLabel.setValue(changeEntry.getValue());
|
||||||
|
amountLabel.setMinWidth(TextUtils.computeTextWidth(amountLabel.getFont(), amountLabel.getText(), 0.0D) + 2);
|
||||||
|
actionBox.getChildren().addAll(region, amountLabel);
|
||||||
|
}
|
||||||
|
|
||||||
outputNodes.add(new OutputNode(actionBox, changeAddress, changeEntry.getValue()));
|
outputNodes.add(new OutputNode(actionBox, changeAddress, changeEntry.getValue()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -584,7 +711,21 @@ public class TransactionDiagram extends GridPane {
|
||||||
feeTooltip.setShowDelay(new Duration(TOOLTIP_SHOW_DELAY));
|
feeTooltip.setShowDelay(new Duration(TOOLTIP_SHOW_DELAY));
|
||||||
feeTooltip.setShowDuration(Duration.INDEFINITE);
|
feeTooltip.setShowDuration(Duration.INDEFINITE);
|
||||||
feeLabel.setTooltip(feeTooltip);
|
feeLabel.setTooltip(feeTooltip);
|
||||||
outputsBox.getChildren().add(feeLabel);
|
|
||||||
|
HBox feeBox = new HBox();
|
||||||
|
feeBox.setAlignment(Pos.CENTER_LEFT);
|
||||||
|
feeBox.getChildren().add(feeLabel);
|
||||||
|
if(isExpanded()) {
|
||||||
|
Region region = new Region();
|
||||||
|
region.setMinWidth(20);
|
||||||
|
HBox.setHgrow(region, Priority.ALWAYS);
|
||||||
|
CoinLabel amountLabel = new CoinLabel();
|
||||||
|
amountLabel.setValue(walletTx.getFee());
|
||||||
|
amountLabel.setMinWidth(TextUtils.computeTextWidth(amountLabel.getFont(), amountLabel.getText(), 0.0D) + 2);
|
||||||
|
feeBox.getChildren().addAll(region, amountLabel);
|
||||||
|
}
|
||||||
|
|
||||||
|
outputsBox.getChildren().add(feeBox);
|
||||||
outputsBox.getChildren().add(createSpacer());
|
outputsBox.getChildren().add(createSpacer());
|
||||||
|
|
||||||
return outputsBox;
|
return outputsBox;
|
||||||
|
@ -613,6 +754,10 @@ public class TransactionDiagram extends GridPane {
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getDiagramHeight() {
|
public double getDiagramHeight() {
|
||||||
|
if(isExpanded()) {
|
||||||
|
return getMaxHeight();
|
||||||
|
}
|
||||||
|
|
||||||
if(isReducedHeight()) {
|
if(isReducedHeight()) {
|
||||||
return REDUCED_DIAGRAM_HEIGHT;
|
return REDUCED_DIAGRAM_HEIGHT;
|
||||||
}
|
}
|
||||||
|
@ -621,6 +766,10 @@ public class TransactionDiagram extends GridPane {
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getMaxUtxos() {
|
private int getMaxUtxos() {
|
||||||
|
if(isExpanded()) {
|
||||||
|
return EXPANDED_MAX_UTXOS;
|
||||||
|
}
|
||||||
|
|
||||||
if(isReducedHeight()) {
|
if(isReducedHeight()) {
|
||||||
return REDUCED_MAX_UTXOS;
|
return REDUCED_MAX_UTXOS;
|
||||||
}
|
}
|
||||||
|
@ -629,6 +778,10 @@ public class TransactionDiagram extends GridPane {
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getMaxPayments() {
|
private int getMaxPayments() {
|
||||||
|
if(isExpanded()) {
|
||||||
|
return EXPANDED_MAX_PAYMENTS;
|
||||||
|
}
|
||||||
|
|
||||||
if(isReducedHeight()) {
|
if(isReducedHeight()) {
|
||||||
return REDUCED_MAX_PAYMENTS;
|
return REDUCED_MAX_PAYMENTS;
|
||||||
}
|
}
|
||||||
|
@ -834,6 +987,8 @@ public class TransactionDiagram extends GridPane {
|
||||||
});
|
});
|
||||||
userAddGlyph.setOnMouseClicked(event -> {
|
userAddGlyph.setOnMouseClicked(event -> {
|
||||||
EventManager.get().post(new SorobanInitiatedEvent(walletTx.getWallet()));
|
EventManager.get().post(new SorobanInitiatedEvent(walletTx.getWallet()));
|
||||||
|
closeExpanded();
|
||||||
|
event.consume();
|
||||||
});
|
});
|
||||||
return userAddGlyph;
|
return userAddGlyph;
|
||||||
}
|
}
|
||||||
|
@ -853,6 +1008,8 @@ public class TransactionDiagram extends GridPane {
|
||||||
});
|
});
|
||||||
coinsGlyph.setOnMouseClicked(event -> {
|
coinsGlyph.setOnMouseClicked(event -> {
|
||||||
EventManager.get().post(new SorobanInitiatedEvent(walletTx.getWallet()));
|
EventManager.get().post(new SorobanInitiatedEvent(walletTx.getWallet()));
|
||||||
|
closeExpanded();
|
||||||
|
event.consume();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
coinsGlyph.getStyleClass().add("coins-icon");
|
coinsGlyph.getStyleClass().add("coins-icon");
|
||||||
|
@ -861,6 +1018,12 @@ public class TransactionDiagram extends GridPane {
|
||||||
return coinsGlyph;
|
return coinsGlyph;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void closeExpanded() {
|
||||||
|
if(isExpanded() && this.getScene() != null && this.getScene().getWindow() instanceof Stage stage) {
|
||||||
|
stage.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isFinal() {
|
public boolean isFinal() {
|
||||||
return finalProperty.get();
|
return finalProperty.get();
|
||||||
}
|
}
|
||||||
|
@ -885,6 +1048,14 @@ public class TransactionDiagram extends GridPane {
|
||||||
this.optimizationStrategyProperty.set(optimizationStrategy);
|
this.optimizationStrategyProperty.set(optimizationStrategy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isExpanded() {
|
||||||
|
return expanded;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExpanded(boolean expanded) {
|
||||||
|
this.expanded = expanded;
|
||||||
|
}
|
||||||
|
|
||||||
private static class PayjoinBlockTransactionHashIndex extends BlockTransactionHashIndex {
|
private static class PayjoinBlockTransactionHashIndex extends BlockTransactionHashIndex {
|
||||||
public PayjoinBlockTransactionHashIndex() {
|
public PayjoinBlockTransactionHashIndex() {
|
||||||
super(Sha256Hash.ZERO_HASH, 0, new Date(), 0L, 0, 0);
|
super(Sha256Hash.ZERO_HASH, 0, new Date(), 0L, 0, 0);
|
||||||
|
|
|
@ -132,7 +132,7 @@ public class HeadersController extends TransactionFormController implements Init
|
||||||
private CopyableLabel virtualSize;
|
private CopyableLabel virtualSize;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private CoinLabel fee;
|
private CopyableCoinLabel fee;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private CopyableLabel feeRate;
|
private CopyableLabel feeRate;
|
||||||
|
|
|
@ -44,7 +44,7 @@ public class InputController extends TransactionFormController implements Initia
|
||||||
private Hyperlink linkedOutpoint;
|
private Hyperlink linkedOutpoint;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private CoinLabel spends;
|
private CopyableCoinLabel spends;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private CopyableLabel from;
|
private CopyableLabel from;
|
||||||
|
|
|
@ -7,7 +7,7 @@ import com.sparrowwallet.drongo.psbt.PSBTInput;
|
||||||
import com.sparrowwallet.drongo.wallet.BlockTransaction;
|
import com.sparrowwallet.drongo.wallet.BlockTransaction;
|
||||||
import com.sparrowwallet.drongo.wallet.Keystore;
|
import com.sparrowwallet.drongo.wallet.Keystore;
|
||||||
import com.sparrowwallet.sparrow.EventManager;
|
import com.sparrowwallet.sparrow.EventManager;
|
||||||
import com.sparrowwallet.sparrow.control.CoinLabel;
|
import com.sparrowwallet.sparrow.control.CopyableCoinLabel;
|
||||||
import com.sparrowwallet.sparrow.control.CopyableLabel;
|
import com.sparrowwallet.sparrow.control.CopyableLabel;
|
||||||
import com.sparrowwallet.sparrow.event.BitcoinUnitChangedEvent;
|
import com.sparrowwallet.sparrow.event.BitcoinUnitChangedEvent;
|
||||||
import com.sparrowwallet.sparrow.event.BlockTransactionFetchedEvent;
|
import com.sparrowwallet.sparrow.event.BlockTransactionFetchedEvent;
|
||||||
|
@ -31,7 +31,7 @@ public class InputsController extends TransactionFormController implements Initi
|
||||||
private CopyableLabel count;
|
private CopyableLabel count;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private CoinLabel total;
|
private CopyableCoinLabel total;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private CopyableLabel signatures;
|
private CopyableLabel signatures;
|
||||||
|
|
|
@ -31,7 +31,7 @@ public class OutputController extends TransactionFormController implements Initi
|
||||||
private Fieldset outputFieldset;
|
private Fieldset outputFieldset;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private CoinLabel value;
|
private CopyableCoinLabel value;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private CopyableLabel to;
|
private CopyableLabel to;
|
||||||
|
|
|
@ -4,7 +4,7 @@ import com.google.common.eventbus.Subscribe;
|
||||||
import com.sparrowwallet.drongo.protocol.Transaction;
|
import com.sparrowwallet.drongo.protocol.Transaction;
|
||||||
import com.sparrowwallet.drongo.protocol.TransactionOutput;
|
import com.sparrowwallet.drongo.protocol.TransactionOutput;
|
||||||
import com.sparrowwallet.sparrow.EventManager;
|
import com.sparrowwallet.sparrow.EventManager;
|
||||||
import com.sparrowwallet.sparrow.control.CoinLabel;
|
import com.sparrowwallet.sparrow.control.CopyableCoinLabel;
|
||||||
import com.sparrowwallet.sparrow.control.CopyableLabel;
|
import com.sparrowwallet.sparrow.control.CopyableLabel;
|
||||||
import com.sparrowwallet.sparrow.event.BitcoinUnitChangedEvent;
|
import com.sparrowwallet.sparrow.event.BitcoinUnitChangedEvent;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
|
@ -21,7 +21,7 @@ public class OutputsController extends TransactionFormController implements Init
|
||||||
private CopyableLabel count;
|
private CopyableLabel count;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private CoinLabel total;
|
private CopyableCoinLabel total;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private PieChart outputsPie;
|
private PieChart outputsPie;
|
||||||
|
|
|
@ -42,13 +42,13 @@ public class TransactionsController extends WalletFormController implements Init
|
||||||
private static final DateFormat LOG_DATE_FORMAT = new SimpleDateFormat("[MMM dd HH:mm:ss]");
|
private static final DateFormat LOG_DATE_FORMAT = new SimpleDateFormat("[MMM dd HH:mm:ss]");
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private CoinLabel balance;
|
private CopyableCoinLabel balance;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private FiatLabel fiatBalance;
|
private FiatLabel fiatBalance;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private CoinLabel mempoolBalance;
|
private CopyableCoinLabel mempoolBalance;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private FiatLabel fiatMempoolBalance;
|
private FiatLabel fiatMempoolBalance;
|
||||||
|
@ -228,7 +228,7 @@ public class TransactionsController extends WalletFormController implements Init
|
||||||
public void walletHistoryStatus(WalletHistoryStatusEvent event) {
|
public void walletHistoryStatus(WalletHistoryStatusEvent event) {
|
||||||
transactionsTable.updateHistoryStatus(event);
|
transactionsTable.updateHistoryStatus(event);
|
||||||
|
|
||||||
if(event.getWallet() != null && getWalletForm().getWallet() == event.getWallet()) {
|
if(event.getWallet() != null && getWalletForm() != null && getWalletForm().getWallet() == event.getWallet()) {
|
||||||
String logMessage = event.getStatusMessage();
|
String logMessage = event.getStatusMessage();
|
||||||
if(logMessage == null) {
|
if(logMessage == null) {
|
||||||
if(event instanceof WalletHistoryFinishedEvent) {
|
if(event instanceof WalletHistoryFinishedEvent) {
|
||||||
|
|
|
@ -53,13 +53,13 @@ public class UtxosController extends WalletFormController implements Initializab
|
||||||
private static final Logger log = LoggerFactory.getLogger(UtxosController.class);
|
private static final Logger log = LoggerFactory.getLogger(UtxosController.class);
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private CoinLabel balance;
|
private CopyableCoinLabel balance;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private FiatLabel fiatBalance;
|
private FiatLabel fiatBalance;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private CoinLabel mempoolBalance;
|
private CopyableCoinLabel mempoolBalance;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private FiatLabel fiatMempoolBalance;
|
private FiatLabel fiatMempoolBalance;
|
||||||
|
|
|
@ -11,6 +11,7 @@ import com.sparrowwallet.drongo.wallet.Wallet;
|
||||||
import com.sparrowwallet.sparrow.AppServices;
|
import com.sparrowwallet.sparrow.AppServices;
|
||||||
import com.sparrowwallet.sparrow.EventManager;
|
import com.sparrowwallet.sparrow.EventManager;
|
||||||
import com.sparrowwallet.sparrow.control.CoinLabel;
|
import com.sparrowwallet.sparrow.control.CoinLabel;
|
||||||
|
import com.sparrowwallet.sparrow.control.CopyableCoinLabel;
|
||||||
import com.sparrowwallet.sparrow.control.CopyableLabel;
|
import com.sparrowwallet.sparrow.control.CopyableLabel;
|
||||||
import com.sparrowwallet.sparrow.event.WalletMasterMixConfigChangedEvent;
|
import com.sparrowwallet.sparrow.event.WalletMasterMixConfigChangedEvent;
|
||||||
import com.sparrowwallet.sparrow.io.Config;
|
import com.sparrowwallet.sparrow.io.Config;
|
||||||
|
@ -62,7 +63,7 @@ public class WhirlpoolController {
|
||||||
private VBox selectedPool;
|
private VBox selectedPool;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private CoinLabel poolFee;
|
private CopyableCoinLabel poolFee;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private Label poolInsufficient;
|
private Label poolInsufficient;
|
||||||
|
@ -83,7 +84,7 @@ public class WhirlpoolController {
|
||||||
private Label nbOutputs;
|
private Label nbOutputs;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private CoinLabel discountFee;
|
private CopyableCoinLabel discountFee;
|
||||||
|
|
||||||
private String walletId;
|
private String walletId;
|
||||||
private Wallet wallet;
|
private Wallet wallet;
|
||||||
|
@ -273,7 +274,7 @@ public class WhirlpoolController {
|
||||||
OptionalLong optMinValue = allPoolsService.getValue().stream().mapToLong(pool1 -> pool1.getPremixValueMin() + pool1.getFeeValue()).min();
|
OptionalLong optMinValue = allPoolsService.getValue().stream().mapToLong(pool1 -> pool1.getPremixValueMin() + pool1.getFeeValue()).min();
|
||||||
if(optMinValue.isPresent() && totalUtxoValue < optMinValue.getAsLong()) {
|
if(optMinValue.isPresent() && totalUtxoValue < optMinValue.getAsLong()) {
|
||||||
String satsValue = String.format(Locale.ENGLISH, "%,d", optMinValue.getAsLong()) + " sats";
|
String satsValue = String.format(Locale.ENGLISH, "%,d", optMinValue.getAsLong()) + " sats";
|
||||||
String btcValue = CoinLabel.BTC_FORMAT.format((double)optMinValue.getAsLong() / Transaction.SATOSHIS_PER_BITCOIN) + " BTC";
|
String btcValue = CoinLabel.getBTCFormat().format((double)optMinValue.getAsLong() / Transaction.SATOSHIS_PER_BITCOIN) + " BTC";
|
||||||
poolInsufficient.setText("No available pools. Select a value over " + (Config.get().getBitcoinUnit() == BitcoinUnit.BTC ? btcValue : satsValue) + ".");
|
poolInsufficient.setText("No available pools. Select a value over " + (Config.get().getBitcoinUnit() == BitcoinUnit.BTC ? btcValue : satsValue) + ".");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
<HBox><Label text="If you find Sparrow useful, consider donating at "/><Hyperlink text="https://sparrowwallet.com/donate" onAction="#openDonate"/></HBox>
|
<HBox><Label text="If you find Sparrow useful, consider donating at "/><Hyperlink text="https://sparrowwallet.com/donate" onAction="#openDonate"/></HBox>
|
||||||
</VBox>
|
</VBox>
|
||||||
<HBox styleClass="button-area" alignment="BOTTOM_RIGHT" VBox.vgrow="SOMETIMES">
|
<HBox styleClass="button-area" alignment="BOTTOM_RIGHT" VBox.vgrow="SOMETIMES">
|
||||||
<Button text="Done" onAction="#close" />
|
<Button text="Close" onAction="#close" />
|
||||||
</HBox>
|
</HBox>
|
||||||
</VBox>
|
</VBox>
|
||||||
</StackPane>
|
</StackPane>
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
<?import org.controlsfx.control.SegmentedButton?>
|
<?import org.controlsfx.control.SegmentedButton?>
|
||||||
<?import com.sparrowwallet.sparrow.control.CopyableLabel?>
|
<?import com.sparrowwallet.sparrow.control.CopyableLabel?>
|
||||||
<?import com.sparrowwallet.sparrow.control.IdLabel?>
|
<?import com.sparrowwallet.sparrow.control.IdLabel?>
|
||||||
<?import com.sparrowwallet.sparrow.control.CoinLabel?>
|
<?import com.sparrowwallet.sparrow.control.CopyableCoinLabel?>
|
||||||
<?import javafx.scene.control.Button?>
|
<?import javafx.scene.control.Button?>
|
||||||
<?import org.controlsfx.glyphfont.Glyph?>
|
<?import org.controlsfx.glyphfont.Glyph?>
|
||||||
<?import javafx.scene.control.ComboBox?>
|
<?import javafx.scene.control.ComboBox?>
|
||||||
|
@ -143,7 +143,7 @@
|
||||||
<Form GridPane.columnIndex="1" GridPane.rowIndex="2" styleClass="details-lower">
|
<Form GridPane.columnIndex="1" GridPane.rowIndex="2" styleClass="details-lower">
|
||||||
<Fieldset text="Fee" inputGrow="SOMETIMES">
|
<Fieldset text="Fee" inputGrow="SOMETIMES">
|
||||||
<Field text="Amount:">
|
<Field text="Amount:">
|
||||||
<CoinLabel fx:id="fee" />
|
<CopyableCoinLabel fx:id="fee" />
|
||||||
</Field>
|
</Field>
|
||||||
<Field text="Rate:">
|
<Field text="Rate:">
|
||||||
<CopyableLabel fx:id="feeRate" />
|
<CopyableLabel fx:id="feeRate" />
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
<?import com.sparrowwallet.sparrow.control.RelativeTimelockSpinner?>
|
<?import com.sparrowwallet.sparrow.control.RelativeTimelockSpinner?>
|
||||||
<?import com.sparrowwallet.sparrow.control.CopyableLabel?>
|
<?import com.sparrowwallet.sparrow.control.CopyableLabel?>
|
||||||
<?import com.sparrowwallet.sparrow.control.IdLabel?>
|
<?import com.sparrowwallet.sparrow.control.IdLabel?>
|
||||||
<?import com.sparrowwallet.sparrow.control.CoinLabel?>
|
<?import com.sparrowwallet.sparrow.control.CopyableCoinLabel?>
|
||||||
<?import com.sparrowwallet.sparrow.control.AddressLabel?>
|
<?import com.sparrowwallet.sparrow.control.AddressLabel?>
|
||||||
<?import com.sparrowwallet.sparrow.control.UnlabeledToggleSwitch?>
|
<?import com.sparrowwallet.sparrow.control.UnlabeledToggleSwitch?>
|
||||||
<?import com.sparrowwallet.sparrow.control.ScriptArea?>
|
<?import com.sparrowwallet.sparrow.control.ScriptArea?>
|
||||||
|
@ -37,7 +37,7 @@
|
||||||
<Hyperlink fx:id="linkedOutpoint" styleClass="id" visible="false" />
|
<Hyperlink fx:id="linkedOutpoint" styleClass="id" visible="false" />
|
||||||
</Field>
|
</Field>
|
||||||
<Field text="Spends:">
|
<Field text="Spends:">
|
||||||
<CoinLabel fx:id="spends" />
|
<CopyableCoinLabel fx:id="spends" />
|
||||||
<CopyableLabel fx:id="from" text="from" />
|
<CopyableLabel fx:id="from" text="from" />
|
||||||
<AddressLabel fx:id="address" />
|
<AddressLabel fx:id="address" />
|
||||||
</Field>
|
</Field>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<?import tornadofx.control.*?>
|
<?import tornadofx.control.*?>
|
||||||
<?import javafx.scene.chart.PieChart?>
|
<?import javafx.scene.chart.PieChart?>
|
||||||
<?import com.sparrowwallet.sparrow.control.CopyableLabel?>
|
<?import com.sparrowwallet.sparrow.control.CopyableLabel?>
|
||||||
<?import com.sparrowwallet.sparrow.control.CoinLabel?>
|
<?import com.sparrowwallet.sparrow.control.CopyableCoinLabel?>
|
||||||
|
|
||||||
<GridPane hgap="10.0" vgap="10.0" styleClass="tx-pane" stylesheets="@inputs.css, @transaction.css, @../general.css" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.sparrowwallet.sparrow.transaction.InputsController">
|
<GridPane hgap="10.0" vgap="10.0" styleClass="tx-pane" stylesheets="@inputs.css, @transaction.css, @../general.css" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.sparrowwallet.sparrow.transaction.InputsController">
|
||||||
<padding>
|
<padding>
|
||||||
|
@ -25,7 +25,7 @@
|
||||||
<CopyableLabel fx:id="count" />
|
<CopyableLabel fx:id="count" />
|
||||||
</Field>
|
</Field>
|
||||||
<Field text="Total:">
|
<Field text="Total:">
|
||||||
<CoinLabel fx:id="total" />
|
<CopyableCoinLabel fx:id="total" />
|
||||||
</Field>
|
</Field>
|
||||||
</Fieldset>
|
</Fieldset>
|
||||||
</Form>
|
</Form>
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<?import tornadofx.control.Form?>
|
<?import tornadofx.control.Form?>
|
||||||
<?import javafx.geometry.Insets?>
|
<?import javafx.geometry.Insets?>
|
||||||
<?import com.sparrowwallet.sparrow.control.CopyableLabel?>
|
<?import com.sparrowwallet.sparrow.control.CopyableLabel?>
|
||||||
<?import com.sparrowwallet.sparrow.control.CoinLabel?>
|
<?import com.sparrowwallet.sparrow.control.CopyableCoinLabel?>
|
||||||
<?import com.sparrowwallet.sparrow.control.AddressLabel?>
|
<?import com.sparrowwallet.sparrow.control.AddressLabel?>
|
||||||
<?import com.sparrowwallet.sparrow.control.ScriptArea?>
|
<?import com.sparrowwallet.sparrow.control.ScriptArea?>
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@
|
||||||
<Form GridPane.columnIndex="0" GridPane.columnSpan="2" GridPane.rowIndex="0">
|
<Form GridPane.columnIndex="0" GridPane.columnSpan="2" GridPane.rowIndex="0">
|
||||||
<Fieldset fx:id="outputFieldset" inputGrow="SOMETIMES" text="Output">
|
<Fieldset fx:id="outputFieldset" inputGrow="SOMETIMES" text="Output">
|
||||||
<Field text="Sends:">
|
<Field text="Sends:">
|
||||||
<CoinLabel fx:id="value"/>
|
<CopyableCoinLabel fx:id="value"/>
|
||||||
<CopyableLabel fx:id="to" text="to" />
|
<CopyableLabel fx:id="to" text="to" />
|
||||||
<AddressLabel fx:id="address" />
|
<AddressLabel fx:id="address" />
|
||||||
</Field>
|
</Field>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<?import tornadofx.control.*?>
|
<?import tornadofx.control.*?>
|
||||||
<?import javafx.scene.chart.PieChart?>
|
<?import javafx.scene.chart.PieChart?>
|
||||||
<?import com.sparrowwallet.sparrow.control.CopyableLabel?>
|
<?import com.sparrowwallet.sparrow.control.CopyableLabel?>
|
||||||
<?import com.sparrowwallet.sparrow.control.CoinLabel?>
|
<?import com.sparrowwallet.sparrow.control.CopyableCoinLabel?>
|
||||||
|
|
||||||
<GridPane hgap="10.0" vgap="10.0" styleClass="tx-pane" stylesheets="@outputs.css, @transaction.css, @../general.css" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.sparrowwallet.sparrow.transaction.OutputsController">
|
<GridPane hgap="10.0" vgap="10.0" styleClass="tx-pane" stylesheets="@outputs.css, @transaction.css, @../general.css" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.sparrowwallet.sparrow.transaction.OutputsController">
|
||||||
<padding>
|
<padding>
|
||||||
|
@ -25,7 +25,7 @@
|
||||||
<CopyableLabel fx:id="count" />
|
<CopyableLabel fx:id="count" />
|
||||||
</Field>
|
</Field>
|
||||||
<Field text="Total:">
|
<Field text="Total:">
|
||||||
<CoinLabel fx:id="total" />
|
<CopyableCoinLabel fx:id="total" />
|
||||||
</Field>
|
</Field>
|
||||||
</Fieldset>
|
</Fieldset>
|
||||||
</Form>
|
</Form>
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<?import tornadofx.control.Form?>
|
<?import tornadofx.control.Form?>
|
||||||
<?import tornadofx.control.Fieldset?>
|
<?import tornadofx.control.Fieldset?>
|
||||||
<?import tornadofx.control.Field?>
|
<?import tornadofx.control.Field?>
|
||||||
<?import com.sparrowwallet.sparrow.control.CoinLabel?>
|
<?import com.sparrowwallet.sparrow.control.CopyableCoinLabel?>
|
||||||
<?import com.sparrowwallet.sparrow.control.FiatLabel?>
|
<?import com.sparrowwallet.sparrow.control.FiatLabel?>
|
||||||
<?import com.sparrowwallet.sparrow.control.CopyableLabel?>
|
<?import com.sparrowwallet.sparrow.control.CopyableLabel?>
|
||||||
<?import org.controlsfx.glyphfont.Glyph?>
|
<?import org.controlsfx.glyphfont.Glyph?>
|
||||||
|
@ -35,10 +35,10 @@
|
||||||
<Form GridPane.columnIndex="0" GridPane.rowIndex="0">
|
<Form GridPane.columnIndex="0" GridPane.rowIndex="0">
|
||||||
<Fieldset inputGrow="SOMETIMES" text="Transactions" styleClass="header">
|
<Fieldset inputGrow="SOMETIMES" text="Transactions" styleClass="header">
|
||||||
<Field text="Balance:">
|
<Field text="Balance:">
|
||||||
<CoinLabel fx:id="balance"/><Region HBox.hgrow="ALWAYS"/><FiatLabel fx:id="fiatBalance" minWidth="110" />
|
<CopyableCoinLabel fx:id="balance"/><Region HBox.hgrow="ALWAYS"/><FiatLabel fx:id="fiatBalance" minWidth="110" />
|
||||||
</Field>
|
</Field>
|
||||||
<Field text="Mempool:">
|
<Field text="Mempool:">
|
||||||
<CoinLabel fx:id="mempoolBalance" /><Region HBox.hgrow="ALWAYS"/><FiatLabel fx:id="fiatMempoolBalance" minWidth="110" />
|
<CopyableCoinLabel fx:id="mempoolBalance" /><Region HBox.hgrow="ALWAYS"/><FiatLabel fx:id="fiatMempoolBalance" minWidth="110" />
|
||||||
</Field>
|
</Field>
|
||||||
<Field text="Transactions:">
|
<Field text="Transactions:">
|
||||||
<CopyableLabel fx:id="transactionCount" />
|
<CopyableLabel fx:id="transactionCount" />
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
<?import tornadofx.control.Form?>
|
<?import tornadofx.control.Form?>
|
||||||
<?import tornadofx.control.Fieldset?>
|
<?import tornadofx.control.Fieldset?>
|
||||||
<?import tornadofx.control.Field?>
|
<?import tornadofx.control.Field?>
|
||||||
<?import com.sparrowwallet.sparrow.control.CoinLabel?>
|
<?import com.sparrowwallet.sparrow.control.CopyableCoinLabel?>
|
||||||
<?import com.sparrowwallet.sparrow.control.FiatLabel?>
|
<?import com.sparrowwallet.sparrow.control.FiatLabel?>
|
||||||
<?import com.sparrowwallet.sparrow.control.CopyableLabel?>
|
<?import com.sparrowwallet.sparrow.control.CopyableLabel?>
|
||||||
|
|
||||||
|
@ -35,10 +35,10 @@
|
||||||
<Form GridPane.columnIndex="0" GridPane.rowIndex="0">
|
<Form GridPane.columnIndex="0" GridPane.rowIndex="0">
|
||||||
<Fieldset inputGrow="SOMETIMES" text="Unspent Transaction Outputs" styleClass="header">
|
<Fieldset inputGrow="SOMETIMES" text="Unspent Transaction Outputs" styleClass="header">
|
||||||
<Field text="Balance:">
|
<Field text="Balance:">
|
||||||
<CoinLabel fx:id="balance"/><Region HBox.hgrow="ALWAYS"/><FiatLabel fx:id="fiatBalance" minWidth="110" />
|
<CopyableCoinLabel fx:id="balance"/><Region HBox.hgrow="ALWAYS"/><FiatLabel fx:id="fiatBalance" minWidth="110" />
|
||||||
</Field>
|
</Field>
|
||||||
<Field text="Mempool:">
|
<Field text="Mempool:">
|
||||||
<CoinLabel fx:id="mempoolBalance" /><Region HBox.hgrow="ALWAYS"/><FiatLabel fx:id="fiatMempoolBalance" minWidth="110" />
|
<CopyableCoinLabel fx:id="mempoolBalance" /><Region HBox.hgrow="ALWAYS"/><FiatLabel fx:id="fiatMempoolBalance" minWidth="110" />
|
||||||
</Field>
|
</Field>
|
||||||
<Field text="UTXOs:">
|
<Field text="UTXOs:">
|
||||||
<CopyableLabel fx:id="utxoCount" />
|
<CopyableLabel fx:id="utxoCount" />
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
<?import javafx.scene.image.ImageView?>
|
<?import javafx.scene.image.ImageView?>
|
||||||
<?import javafx.scene.image.Image?>
|
<?import javafx.scene.image.Image?>
|
||||||
<?import javafx.geometry.Insets?>
|
<?import javafx.geometry.Insets?>
|
||||||
<?import com.sparrowwallet.sparrow.control.CoinLabel?>
|
<?import com.sparrowwallet.sparrow.control.CopyableCoinLabel?>
|
||||||
<?import com.sparrowwallet.sparrow.control.CopyableLabel?>
|
<?import com.sparrowwallet.sparrow.control.CopyableLabel?>
|
||||||
<StackPane prefHeight="460.0" prefWidth="600.0" stylesheets="@whirlpool.css, @../general.css" styleClass="whirlpool-pane" fx:controller="com.sparrowwallet.sparrow.whirlpool.WhirlpoolController" xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml">
|
<StackPane prefHeight="460.0" prefWidth="600.0" stylesheets="@whirlpool.css, @../general.css" styleClass="whirlpool-pane" fx:controller="com.sparrowwallet.sparrow.whirlpool.WhirlpoolController" xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml">
|
||||||
<VBox spacing="20">
|
<VBox spacing="20">
|
||||||
|
@ -131,10 +131,10 @@
|
||||||
</HBox>
|
</HBox>
|
||||||
<HBox styleClass="field-box">
|
<HBox styleClass="field-box">
|
||||||
<Label text="Pool Fee:" styleClass="field-label" />
|
<Label text="Pool Fee:" styleClass="field-label" />
|
||||||
<CoinLabel fx:id="poolFee" />
|
<CopyableCoinLabel fx:id="poolFee" />
|
||||||
<HBox fx:id="discountFeeBox" alignment="CENTER_LEFT">
|
<HBox fx:id="discountFeeBox" alignment="CENTER_LEFT">
|
||||||
<Label text=" (discounted to " />
|
<Label text=" (discounted to " />
|
||||||
<CoinLabel fx:id="discountFee" />
|
<CopyableCoinLabel fx:id="discountFee" />
|
||||||
<Label text=")" />
|
<Label text=")" />
|
||||||
</HBox>
|
</HBox>
|
||||||
</HBox>
|
</HBox>
|
||||||
|
|
Loading…
Reference in a new issue