mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2024-12-23 20:36:44 +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.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);
|
||||
Scene scene = new Scene(root);
|
||||
AppServices.onEscapePressed(scene, stage::close);
|
||||
|
|
|
@ -6,6 +6,7 @@ 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.Label;
|
||||
import javafx.scene.control.MenuItem;
|
||||
import javafx.scene.control.Tooltip;
|
||||
import javafx.scene.input.Clipboard;
|
||||
|
@ -15,7 +16,7 @@ import java.text.DecimalFormat;
|
|||
import java.text.DecimalFormatSymbols;
|
||||
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));
|
||||
|
||||
private final LongProperty valueProperty = new SimpleLongProperty(-1);
|
||||
|
@ -28,7 +29,6 @@ public class CoinLabel extends CopyableLabel {
|
|||
|
||||
public CoinLabel(String text) {
|
||||
super(text);
|
||||
BTC_FORMAT.setMaximumFractionDigits(8);
|
||||
valueProperty().addListener((observable, oldValue, newValue) -> setValueAsText((Long)newValue, Config.get().getBitcoinUnit()));
|
||||
tooltip = new Tooltip();
|
||||
contextMenu = new CoinContextMenu();
|
||||
|
@ -77,7 +77,7 @@ public class CoinLabel extends CopyableLabel {
|
|||
|
||||
private class CoinContextMenu extends ContextMenu {
|
||||
public CoinContextMenu() {
|
||||
MenuItem copySatsValue = new MenuItem("Copy Value in Satoshis");
|
||||
MenuItem copySatsValue = new MenuItem("Copy Value in sats");
|
||||
copySatsValue.setOnAction(AE -> {
|
||||
hide();
|
||||
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);
|
||||
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.SimpleBooleanProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.Group;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.ContentDisplay;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.Tooltip;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
import javafx.scene.layout.*;
|
||||
import javafx.scene.shape.Circle;
|
||||
import javafx.scene.shape.CubicCurve;
|
||||
import javafx.scene.shape.Line;
|
||||
import javafx.stage.Modality;
|
||||
import javafx.stage.Stage;
|
||||
import javafx.stage.StageStyle;
|
||||
import javafx.util.Duration;
|
||||
import org.controlsfx.glyphfont.FontAwesome;
|
||||
import org.controlsfx.glyphfont.Glyph;
|
||||
|
@ -40,16 +46,68 @@ import java.util.stream.Collectors;
|
|||
public class TransactionDiagram extends GridPane {
|
||||
private static final int MAX_UTXOS = 8;
|
||||
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 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 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 RELATIVE_SIZE_MAX_RADIUS = 7;
|
||||
private static final int ROW_HEIGHT = 27;
|
||||
|
||||
private WalletTransaction walletTx;
|
||||
private final BooleanProperty finalProperty = new SimpleBooleanProperty(false);
|
||||
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) {
|
||||
setMinHeight(getDiagramHeight());
|
||||
|
@ -60,6 +118,10 @@ public class TransactionDiagram extends GridPane {
|
|||
} else {
|
||||
this.walletTx = walletTx;
|
||||
update();
|
||||
setOnMouseClicked(expandedDiagramHandler);
|
||||
if(expandedDiagram != null) {
|
||||
updateExpandedDiagram();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,6 +149,24 @@ public class TransactionDiagram extends GridPane {
|
|||
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() {
|
||||
List<Map<BlockTransactionHashIndex, WalletNode>> displayedUtxoSets = getDisplayedUtxoSets();
|
||||
|
||||
|
@ -287,17 +367,19 @@ public class TransactionDiagram extends GridPane {
|
|||
|
||||
private Pane getInputsLabels(List<Map<BlockTransactionHashIndex, WalletNode>> displayedUtxoSets) {
|
||||
VBox inputsBox = new VBox();
|
||||
inputsBox.setMaxWidth(150);
|
||||
inputsBox.setPrefWidth(150);
|
||||
inputsBox.setMaxWidth(isExpanded() ? 300 : 150);
|
||||
inputsBox.setPrefWidth(isExpanded() ? 230 : 150);
|
||||
inputsBox.setPadding(new Insets(0, 10, 0, 10));
|
||||
inputsBox.minHeightProperty().bind(minHeightProperty());
|
||||
inputsBox.setAlignment(Pos.CENTER_RIGHT);
|
||||
inputsBox.getChildren().add(createSpacer());
|
||||
double labelHeight = TextUtils.computeTextHeight(AppServices.getMonospaceFont(), "0") + 1;
|
||||
for(Map<BlockTransactionHashIndex, WalletNode> displayedUtxos : displayedUtxoSets) {
|
||||
for(BlockTransactionHashIndex input : displayedUtxos.keySet()) {
|
||||
WalletNode walletNode = displayedUtxos.get(input);
|
||||
String desc = getInputDescription(input);
|
||||
Label label = new Label(desc);
|
||||
label.setPrefHeight(labelHeight);
|
||||
label.getStyleClass().add("utxo-label");
|
||||
|
||||
Button excludeUtxoButton = new Button("");
|
||||
|
@ -307,8 +389,10 @@ public class TransactionDiagram extends GridPane {
|
|||
});
|
||||
|
||||
Tooltip tooltip = new Tooltip();
|
||||
Long inputValue = 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");
|
||||
|
||||
if(input.getLabel() == null || input.getLabel().isEmpty()) {
|
||||
|
@ -335,13 +419,16 @@ public class TransactionDiagram extends GridPane {
|
|||
label.setGraphic(walletTx.isTwoPersonCoinjoin() ? getQuestionGlyph() : getWarningGlyph());
|
||||
label.setOnMouseClicked(event -> {
|
||||
EventManager.get().post(new SorobanInitiatedEvent(walletTx.getWallet()));
|
||||
closeExpanded();
|
||||
event.consume();
|
||||
});
|
||||
} else {
|
||||
if(walletTx.getInputTransactions() != null && walletTx.getInputTransactions().get(input.getHash()) != null) {
|
||||
BlockTransaction blockTransaction = walletTx.getInputTransactions().get(input.getHash());
|
||||
TransactionOutput txOutput = blockTransaction.getTransaction().getOutputs().get((int) input.getIndex());
|
||||
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 {
|
||||
tooltip.setText(input.getHashAsString() + ":" + input.getIndex());
|
||||
}
|
||||
|
@ -355,7 +442,21 @@ public class TransactionDiagram extends GridPane {
|
|||
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());
|
||||
}
|
||||
}
|
||||
|
@ -505,7 +606,8 @@ public class TransactionDiagram extends GridPane {
|
|||
|
||||
private Pane getOutputsLabels(List<Payment> displayedPayments) {
|
||||
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.setAlignment(Pos.CENTER_LEFT);
|
||||
outputsBox.getChildren().add(createSpacer());
|
||||
|
@ -527,7 +629,20 @@ public class TransactionDiagram extends GridPane {
|
|||
recipientTooltip.setShowDelay(new Duration(TOOLTIP_SHOW_DELAY));
|
||||
recipientTooltip.setShowDuration(Duration.INDEFINITE);
|
||||
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()) {
|
||||
|
@ -536,6 +651,7 @@ public class TransactionDiagram extends GridPane {
|
|||
boolean overGapLimit = (changeNode.getIndex() - defaultChangeNode.getIndex()) > walletTx.getWallet().getGapLimit();
|
||||
|
||||
HBox actionBox = new HBox();
|
||||
actionBox.setAlignment(Pos.CENTER_LEFT);
|
||||
Address changeAddress = walletTx.getChangeAddress(changeNode);
|
||||
String changeDesc = changeAddress.toString().substring(0, 8) + "...";
|
||||
Label changeLabel = new Label(changeDesc, overGapLimit ? getChangeWarningGlyph() : getChangeGlyph());
|
||||
|
@ -563,6 +679,17 @@ public class TransactionDiagram extends GridPane {
|
|||
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()));
|
||||
}
|
||||
|
||||
|
@ -584,7 +711,21 @@ public class TransactionDiagram extends GridPane {
|
|||
feeTooltip.setShowDelay(new Duration(TOOLTIP_SHOW_DELAY));
|
||||
feeTooltip.setShowDuration(Duration.INDEFINITE);
|
||||
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());
|
||||
|
||||
return outputsBox;
|
||||
|
@ -613,6 +754,10 @@ public class TransactionDiagram extends GridPane {
|
|||
}
|
||||
|
||||
public double getDiagramHeight() {
|
||||
if(isExpanded()) {
|
||||
return getMaxHeight();
|
||||
}
|
||||
|
||||
if(isReducedHeight()) {
|
||||
return REDUCED_DIAGRAM_HEIGHT;
|
||||
}
|
||||
|
@ -621,6 +766,10 @@ public class TransactionDiagram extends GridPane {
|
|||
}
|
||||
|
||||
private int getMaxUtxos() {
|
||||
if(isExpanded()) {
|
||||
return EXPANDED_MAX_UTXOS;
|
||||
}
|
||||
|
||||
if(isReducedHeight()) {
|
||||
return REDUCED_MAX_UTXOS;
|
||||
}
|
||||
|
@ -629,6 +778,10 @@ public class TransactionDiagram extends GridPane {
|
|||
}
|
||||
|
||||
private int getMaxPayments() {
|
||||
if(isExpanded()) {
|
||||
return EXPANDED_MAX_PAYMENTS;
|
||||
}
|
||||
|
||||
if(isReducedHeight()) {
|
||||
return REDUCED_MAX_PAYMENTS;
|
||||
}
|
||||
|
@ -834,6 +987,8 @@ public class TransactionDiagram extends GridPane {
|
|||
});
|
||||
userAddGlyph.setOnMouseClicked(event -> {
|
||||
EventManager.get().post(new SorobanInitiatedEvent(walletTx.getWallet()));
|
||||
closeExpanded();
|
||||
event.consume();
|
||||
});
|
||||
return userAddGlyph;
|
||||
}
|
||||
|
@ -853,6 +1008,8 @@ public class TransactionDiagram extends GridPane {
|
|||
});
|
||||
coinsGlyph.setOnMouseClicked(event -> {
|
||||
EventManager.get().post(new SorobanInitiatedEvent(walletTx.getWallet()));
|
||||
closeExpanded();
|
||||
event.consume();
|
||||
});
|
||||
} else {
|
||||
coinsGlyph.getStyleClass().add("coins-icon");
|
||||
|
@ -861,6 +1018,12 @@ public class TransactionDiagram extends GridPane {
|
|||
return coinsGlyph;
|
||||
}
|
||||
|
||||
private void closeExpanded() {
|
||||
if(isExpanded() && this.getScene() != null && this.getScene().getWindow() instanceof Stage stage) {
|
||||
stage.close();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isFinal() {
|
||||
return finalProperty.get();
|
||||
}
|
||||
|
@ -885,6 +1048,14 @@ public class TransactionDiagram extends GridPane {
|
|||
this.optimizationStrategyProperty.set(optimizationStrategy);
|
||||
}
|
||||
|
||||
public boolean isExpanded() {
|
||||
return expanded;
|
||||
}
|
||||
|
||||
public void setExpanded(boolean expanded) {
|
||||
this.expanded = expanded;
|
||||
}
|
||||
|
||||
private static class PayjoinBlockTransactionHashIndex extends BlockTransactionHashIndex {
|
||||
public PayjoinBlockTransactionHashIndex() {
|
||||
super(Sha256Hash.ZERO_HASH, 0, new Date(), 0L, 0, 0);
|
||||
|
|
|
@ -132,7 +132,7 @@ public class HeadersController extends TransactionFormController implements Init
|
|||
private CopyableLabel virtualSize;
|
||||
|
||||
@FXML
|
||||
private CoinLabel fee;
|
||||
private CopyableCoinLabel fee;
|
||||
|
||||
@FXML
|
||||
private CopyableLabel feeRate;
|
||||
|
|
|
@ -44,7 +44,7 @@ public class InputController extends TransactionFormController implements Initia
|
|||
private Hyperlink linkedOutpoint;
|
||||
|
||||
@FXML
|
||||
private CoinLabel spends;
|
||||
private CopyableCoinLabel spends;
|
||||
|
||||
@FXML
|
||||
private CopyableLabel from;
|
||||
|
|
|
@ -7,7 +7,7 @@ import com.sparrowwallet.drongo.psbt.PSBTInput;
|
|||
import com.sparrowwallet.drongo.wallet.BlockTransaction;
|
||||
import com.sparrowwallet.drongo.wallet.Keystore;
|
||||
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.event.BitcoinUnitChangedEvent;
|
||||
import com.sparrowwallet.sparrow.event.BlockTransactionFetchedEvent;
|
||||
|
@ -31,7 +31,7 @@ public class InputsController extends TransactionFormController implements Initi
|
|||
private CopyableLabel count;
|
||||
|
||||
@FXML
|
||||
private CoinLabel total;
|
||||
private CopyableCoinLabel total;
|
||||
|
||||
@FXML
|
||||
private CopyableLabel signatures;
|
||||
|
|
|
@ -31,7 +31,7 @@ public class OutputController extends TransactionFormController implements Initi
|
|||
private Fieldset outputFieldset;
|
||||
|
||||
@FXML
|
||||
private CoinLabel value;
|
||||
private CopyableCoinLabel value;
|
||||
|
||||
@FXML
|
||||
private CopyableLabel to;
|
||||
|
|
|
@ -4,7 +4,7 @@ import com.google.common.eventbus.Subscribe;
|
|||
import com.sparrowwallet.drongo.protocol.Transaction;
|
||||
import com.sparrowwallet.drongo.protocol.TransactionOutput;
|
||||
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.event.BitcoinUnitChangedEvent;
|
||||
import javafx.fxml.FXML;
|
||||
|
@ -21,7 +21,7 @@ public class OutputsController extends TransactionFormController implements Init
|
|||
private CopyableLabel count;
|
||||
|
||||
@FXML
|
||||
private CoinLabel total;
|
||||
private CopyableCoinLabel total;
|
||||
|
||||
@FXML
|
||||
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]");
|
||||
|
||||
@FXML
|
||||
private CoinLabel balance;
|
||||
private CopyableCoinLabel balance;
|
||||
|
||||
@FXML
|
||||
private FiatLabel fiatBalance;
|
||||
|
||||
@FXML
|
||||
private CoinLabel mempoolBalance;
|
||||
private CopyableCoinLabel mempoolBalance;
|
||||
|
||||
@FXML
|
||||
private FiatLabel fiatMempoolBalance;
|
||||
|
@ -228,7 +228,7 @@ public class TransactionsController extends WalletFormController implements Init
|
|||
public void walletHistoryStatus(WalletHistoryStatusEvent 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();
|
||||
if(logMessage == null) {
|
||||
if(event instanceof WalletHistoryFinishedEvent) {
|
||||
|
|
|
@ -53,13 +53,13 @@ public class UtxosController extends WalletFormController implements Initializab
|
|||
private static final Logger log = LoggerFactory.getLogger(UtxosController.class);
|
||||
|
||||
@FXML
|
||||
private CoinLabel balance;
|
||||
private CopyableCoinLabel balance;
|
||||
|
||||
@FXML
|
||||
private FiatLabel fiatBalance;
|
||||
|
||||
@FXML
|
||||
private CoinLabel mempoolBalance;
|
||||
private CopyableCoinLabel mempoolBalance;
|
||||
|
||||
@FXML
|
||||
private FiatLabel fiatMempoolBalance;
|
||||
|
|
|
@ -11,6 +11,7 @@ import com.sparrowwallet.drongo.wallet.Wallet;
|
|||
import com.sparrowwallet.sparrow.AppServices;
|
||||
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.event.WalletMasterMixConfigChangedEvent;
|
||||
import com.sparrowwallet.sparrow.io.Config;
|
||||
|
@ -62,7 +63,7 @@ public class WhirlpoolController {
|
|||
private VBox selectedPool;
|
||||
|
||||
@FXML
|
||||
private CoinLabel poolFee;
|
||||
private CopyableCoinLabel poolFee;
|
||||
|
||||
@FXML
|
||||
private Label poolInsufficient;
|
||||
|
@ -83,7 +84,7 @@ public class WhirlpoolController {
|
|||
private Label nbOutputs;
|
||||
|
||||
@FXML
|
||||
private CoinLabel discountFee;
|
||||
private CopyableCoinLabel discountFee;
|
||||
|
||||
private String walletId;
|
||||
private Wallet wallet;
|
||||
|
@ -273,7 +274,7 @@ public class WhirlpoolController {
|
|||
OptionalLong optMinValue = allPoolsService.getValue().stream().mapToLong(pool1 -> pool1.getPremixValueMin() + pool1.getFeeValue()).min();
|
||||
if(optMinValue.isPresent() && totalUtxoValue < optMinValue.getAsLong()) {
|
||||
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) + ".");
|
||||
}
|
||||
});
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
<HBox><Label text="If you find Sparrow useful, consider donating at "/><Hyperlink text="https://sparrowwallet.com/donate" onAction="#openDonate"/></HBox>
|
||||
</VBox>
|
||||
<HBox styleClass="button-area" alignment="BOTTOM_RIGHT" VBox.vgrow="SOMETIMES">
|
||||
<Button text="Done" onAction="#close" />
|
||||
<Button text="Close" onAction="#close" />
|
||||
</HBox>
|
||||
</VBox>
|
||||
</StackPane>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<?import org.controlsfx.control.SegmentedButton?>
|
||||
<?import com.sparrowwallet.sparrow.control.CopyableLabel?>
|
||||
<?import com.sparrowwallet.sparrow.control.IdLabel?>
|
||||
<?import com.sparrowwallet.sparrow.control.CoinLabel?>
|
||||
<?import com.sparrowwallet.sparrow.control.CopyableCoinLabel?>
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import org.controlsfx.glyphfont.Glyph?>
|
||||
<?import javafx.scene.control.ComboBox?>
|
||||
|
@ -143,7 +143,7 @@
|
|||
<Form GridPane.columnIndex="1" GridPane.rowIndex="2" styleClass="details-lower">
|
||||
<Fieldset text="Fee" inputGrow="SOMETIMES">
|
||||
<Field text="Amount:">
|
||||
<CoinLabel fx:id="fee" />
|
||||
<CopyableCoinLabel fx:id="fee" />
|
||||
</Field>
|
||||
<Field text="Rate:">
|
||||
<CopyableLabel fx:id="feeRate" />
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<?import com.sparrowwallet.sparrow.control.RelativeTimelockSpinner?>
|
||||
<?import com.sparrowwallet.sparrow.control.CopyableLabel?>
|
||||
<?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.UnlabeledToggleSwitch?>
|
||||
<?import com.sparrowwallet.sparrow.control.ScriptArea?>
|
||||
|
@ -37,7 +37,7 @@
|
|||
<Hyperlink fx:id="linkedOutpoint" styleClass="id" visible="false" />
|
||||
</Field>
|
||||
<Field text="Spends:">
|
||||
<CoinLabel fx:id="spends" />
|
||||
<CopyableCoinLabel fx:id="spends" />
|
||||
<CopyableLabel fx:id="from" text="from" />
|
||||
<AddressLabel fx:id="address" />
|
||||
</Field>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<?import tornadofx.control.*?>
|
||||
<?import javafx.scene.chart.PieChart?>
|
||||
<?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">
|
||||
<padding>
|
||||
|
@ -25,7 +25,7 @@
|
|||
<CopyableLabel fx:id="count" />
|
||||
</Field>
|
||||
<Field text="Total:">
|
||||
<CoinLabel fx:id="total" />
|
||||
<CopyableCoinLabel fx:id="total" />
|
||||
</Field>
|
||||
</Fieldset>
|
||||
</Form>
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<?import tornadofx.control.Form?>
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?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.ScriptArea?>
|
||||
|
||||
|
@ -31,7 +31,7 @@
|
|||
<Form GridPane.columnIndex="0" GridPane.columnSpan="2" GridPane.rowIndex="0">
|
||||
<Fieldset fx:id="outputFieldset" inputGrow="SOMETIMES" text="Output">
|
||||
<Field text="Sends:">
|
||||
<CoinLabel fx:id="value"/>
|
||||
<CopyableCoinLabel fx:id="value"/>
|
||||
<CopyableLabel fx:id="to" text="to" />
|
||||
<AddressLabel fx:id="address" />
|
||||
</Field>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<?import tornadofx.control.*?>
|
||||
<?import javafx.scene.chart.PieChart?>
|
||||
<?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">
|
||||
<padding>
|
||||
|
@ -25,7 +25,7 @@
|
|||
<CopyableLabel fx:id="count" />
|
||||
</Field>
|
||||
<Field text="Total:">
|
||||
<CoinLabel fx:id="total" />
|
||||
<CopyableCoinLabel fx:id="total" />
|
||||
</Field>
|
||||
</Fieldset>
|
||||
</Form>
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<?import tornadofx.control.Form?>
|
||||
<?import tornadofx.control.Fieldset?>
|
||||
<?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.CopyableLabel?>
|
||||
<?import org.controlsfx.glyphfont.Glyph?>
|
||||
|
@ -35,10 +35,10 @@
|
|||
<Form GridPane.columnIndex="0" GridPane.rowIndex="0">
|
||||
<Fieldset inputGrow="SOMETIMES" text="Transactions" styleClass="header">
|
||||
<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 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 text="Transactions:">
|
||||
<CopyableLabel fx:id="transactionCount" />
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<?import tornadofx.control.Form?>
|
||||
<?import tornadofx.control.Fieldset?>
|
||||
<?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.CopyableLabel?>
|
||||
|
||||
|
@ -35,10 +35,10 @@
|
|||
<Form GridPane.columnIndex="0" GridPane.rowIndex="0">
|
||||
<Fieldset inputGrow="SOMETIMES" text="Unspent Transaction Outputs" styleClass="header">
|
||||
<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 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 text="UTXOs:">
|
||||
<CopyableLabel fx:id="utxoCount" />
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<?import javafx.scene.image.ImageView?>
|
||||
<?import javafx.scene.image.Image?>
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import com.sparrowwallet.sparrow.control.CoinLabel?>
|
||||
<?import com.sparrowwallet.sparrow.control.CopyableCoinLabel?>
|
||||
<?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">
|
||||
<VBox spacing="20">
|
||||
|
@ -131,10 +131,10 @@
|
|||
</HBox>
|
||||
<HBox styleClass="field-box">
|
||||
<Label text="Pool Fee:" styleClass="field-label" />
|
||||
<CoinLabel fx:id="poolFee" />
|
||||
<CopyableCoinLabel fx:id="poolFee" />
|
||||
<HBox fx:id="discountFeeBox" alignment="CENTER_LEFT">
|
||||
<Label text=" (discounted to " />
|
||||
<CoinLabel fx:id="discountFee" />
|
||||
<CopyableCoinLabel fx:id="discountFee" />
|
||||
<Label text=")" />
|
||||
</HBox>
|
||||
</HBox>
|
||||
|
|
Loading…
Reference in a new issue