add context menus to transaction diagram labels to copy addresses and values

This commit is contained in:
Craig Raw 2022-07-11 15:24:55 +02:00
parent 94c5920c27
commit f8fce02a3d

View file

@ -3,6 +3,7 @@ package com.sparrowwallet.sparrow.control;
import com.sparrowwallet.drongo.KeyPurpose; import com.sparrowwallet.drongo.KeyPurpose;
import com.sparrowwallet.drongo.address.Address; import com.sparrowwallet.drongo.address.Address;
import com.sparrowwallet.drongo.protocol.Sha256Hash; import com.sparrowwallet.drongo.protocol.Sha256Hash;
import com.sparrowwallet.drongo.protocol.Transaction;
import com.sparrowwallet.drongo.protocol.TransactionOutput; import com.sparrowwallet.drongo.protocol.TransactionOutput;
import com.sparrowwallet.drongo.uri.BitcoinURI; import com.sparrowwallet.drongo.uri.BitcoinURI;
import com.sparrowwallet.drongo.wallet.*; import com.sparrowwallet.drongo.wallet.*;
@ -26,10 +27,10 @@ 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.Scene;
import javafx.scene.control.Button; import javafx.scene.control.*;
import javafx.scene.control.ContentDisplay; import javafx.scene.input.Clipboard;
import javafx.scene.control.Label; import javafx.scene.input.ClipboardContent;
import javafx.scene.control.Tooltip; import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent; import javafx.scene.input.MouseEvent;
import javafx.scene.layout.*; import javafx.scene.layout.*;
import javafx.scene.paint.Color; import javafx.scene.paint.Color;
@ -47,6 +48,8 @@ import org.controlsfx.tools.Platform;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static com.sparrowwallet.sparrow.control.CoinLabel.BTC_FORMAT;
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;
@ -70,7 +73,7 @@ public class TransactionDiagram extends GridPane {
private final EventHandler<MouseEvent> expandedDiagramHandler = new EventHandler<>() { private final EventHandler<MouseEvent> expandedDiagramHandler = new EventHandler<>() {
@Override @Override
public void handle(MouseEvent event) { public void handle(MouseEvent event) {
if(!event.isConsumed()) { if(!event.isConsumed() && event.getButton() != MouseButton.SECONDARY) {
Stage stage = new Stage(StageStyle.UNDECORATED); Stage stage = new Stage(StageStyle.UNDECORATED);
stage.setTitle(walletTx.getPayments().iterator().next().getLabel()); stage.setTitle(walletTx.getPayments().iterator().next().getLabel());
stage.initOwner(TransactionDiagram.this.getScene().getWindow()); stage.initOwner(TransactionDiagram.this.getScene().getWindow());
@ -420,6 +423,9 @@ public class TransactionDiagram extends GridPane {
label.setGraphic(excludeUtxoButton); label.setGraphic(excludeUtxoButton);
label.setContentDisplay(ContentDisplay.LEFT); label.setContentDisplay(ContentDisplay.LEFT);
} }
ContextMenu contextMenu = new LabelContextMenu(walletNode.getAddress(), inputValue);
label.setContextMenu(contextMenu);
} else { } else {
if(input instanceof PayjoinBlockTransactionHashIndex) { if(input instanceof PayjoinBlockTransactionHashIndex) {
tooltip.setText("Added once transaction is signed and sent to the payjoin server"); tooltip.setText("Added once transaction is signed and sent to the payjoin server");
@ -448,6 +454,9 @@ public class TransactionDiagram extends GridPane {
Address fromAddress = txOutput.getScript().getToAddress(); Address fromAddress = txOutput.getScript().getToAddress();
inputValue = txOutput.getValue(); inputValue = txOutput.getValue();
tooltip.setText("Input of " + getSatsValue(inputValue) + " sats\n" + input.getHashAsString() + ":" + input.getIndex() + (fromAddress != null ? "\n" + fromAddress : "")); tooltip.setText("Input of " + getSatsValue(inputValue) + " sats\n" + input.getHashAsString() + ":" + input.getIndex() + (fromAddress != null ? "\n" + fromAddress : ""));
ContextMenu contextMenu = new LabelContextMenu(fromAddress, inputValue);
label.setContextMenu(contextMenu);
} else { } else {
tooltip.setText(input.getHashAsString() + ":" + input.getIndex()); tooltip.setText(input.getHashAsString() + ":" + input.getIndex());
} }
@ -731,6 +740,11 @@ public class TransactionDiagram extends GridPane {
for(OutputNode outputNode : outputNodes) { for(OutputNode outputNode : outputNodes) {
outputsBox.getChildren().add(outputNode.outputLabel); outputsBox.getChildren().add(outputNode.outputLabel);
outputsBox.getChildren().add(createSpacer()); outputsBox.getChildren().add(createSpacer());
ContextMenu contextMenu = new LabelContextMenu(outputNode.address, outputNode.amount);
if(!outputNode.outputLabel.getChildren().isEmpty() && outputNode.outputLabel.getChildren().get(0) instanceof Label outputLabelControl) {
outputLabelControl.setContextMenu(contextMenu);
}
} }
boolean highFee = (walletTx.getFeePercentage() > 0.1); boolean highFee = (walletTx.getFeePercentage() > 0.1);
@ -759,6 +773,11 @@ public class TransactionDiagram extends GridPane {
outputsBox.getChildren().add(feeBox); outputsBox.getChildren().add(feeBox);
outputsBox.getChildren().add(createSpacer()); outputsBox.getChildren().add(createSpacer());
if(walletTx.getFee() >= 0) {
ContextMenu contextMenu = new LabelContextMenu(null, walletTx.getFee());
feeLabel.setContextMenu(contextMenu);
}
return outputsBox; return outputsBox;
} }
@ -1194,11 +1213,11 @@ public class TransactionDiagram extends GridPane {
} }
private class OutputNode implements Comparable<OutputNode> { private class OutputNode implements Comparable<OutputNode> {
public Node outputLabel; public Pane outputLabel;
public Address address; public Address address;
public long amount; public long amount;
public OutputNode(Node outputLabel, Address address, long amount) { public OutputNode(Pane outputLabel, Address address, long amount) {
this.outputLabel = outputLabel; this.outputLabel = outputLabel;
this.address = address; this.address = address;
this.amount = amount; this.amount = amount;
@ -1213,4 +1232,35 @@ public class TransactionDiagram extends GridPane {
} }
} }
} }
private static class LabelContextMenu extends ContextMenu {
public LabelContextMenu(Address address, long value) {
if(address != null) {
MenuItem copyAddress = new MenuItem("Copy Address");
copyAddress.setOnAction(event -> {
hide();
ClipboardContent content = new ClipboardContent();
content.putString(address.toString());
Clipboard.getSystemClipboard().setContent(content);
});
getItems().add(copyAddress);
}
MenuItem copySatsValue = new MenuItem("Copy Value in sats");
copySatsValue.setOnAction(event -> {
hide();
ClipboardContent content = new ClipboardContent();
content.putString(Long.toString(value));
Clipboard.getSystemClipboard().setContent(content);
});
MenuItem copyBtcValue = new MenuItem("Copy Value in BTC");
copyBtcValue.setOnAction(event -> {
hide();
ClipboardContent content = new ClipboardContent();
content.putString(BTC_FORMAT.format((double)value / Transaction.SATOSHIS_PER_BITCOIN));
Clipboard.getSystemClipboard().setContent(content);
});
getItems().addAll(copySatsValue, copyBtcValue);
}
}
} }