mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2024-12-25 21:26:43 +00:00
transaction tab: rearrange via transaction tree
This commit is contained in:
parent
bb32a1e7b1
commit
85eb4df7e9
8 changed files with 149 additions and 13 deletions
2
drongo
2
drongo
|
@ -1 +1 @@
|
||||||
Subproject commit 0815484c4cb384522cf215ef18fc69a666b43c37
|
Subproject commit 0bb5b75be52ca4ee9dc771dae30d2b7cb9a49bd2
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.sparrowwallet.sparrow.event;
|
||||||
|
|
||||||
|
import com.sparrowwallet.drongo.psbt.PSBT;
|
||||||
|
|
||||||
|
public class PSBTReorderedEvent {
|
||||||
|
private final PSBT psbt;
|
||||||
|
|
||||||
|
public PSBTReorderedEvent(PSBT psbt) {
|
||||||
|
this.psbt = psbt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PSBT getPsbt() {
|
||||||
|
return psbt;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1593,6 +1593,14 @@ public class HeadersController extends TransactionFormController implements Init
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void psbtReordered(PSBTReorderedEvent event) {
|
||||||
|
if(event.getPsbt().equals(headersForm.getPsbt())) {
|
||||||
|
updateTxId();
|
||||||
|
transactionDiagram.update(getWalletTransaction(headersForm.getInputTransactions()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static class WalletSignComparator implements Comparator<Wallet> {
|
private static class WalletSignComparator implements Comparator<Wallet> {
|
||||||
private static final List<KeystoreSource> sourceOrder = List.of(KeystoreSource.SW_WATCH, KeystoreSource.HW_AIRGAPPED, KeystoreSource.HW_USB, KeystoreSource.SW_SEED);
|
private static final List<KeystoreSource> sourceOrder = List.of(KeystoreSource.SW_WATCH, KeystoreSource.HW_AIRGAPPED, KeystoreSource.HW_USB, KeystoreSource.SW_SEED);
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package com.sparrowwallet.sparrow.transaction;
|
package com.sparrowwallet.sparrow.transaction;
|
||||||
|
|
||||||
public abstract class IndexedTransactionForm extends TransactionForm {
|
public abstract class IndexedTransactionForm extends TransactionForm {
|
||||||
private final int index;
|
private int index;
|
||||||
|
|
||||||
public IndexedTransactionForm(TransactionData txdata, int index) {
|
public IndexedTransactionForm(TransactionData txdata, int index) {
|
||||||
super(txdata);
|
super(txdata);
|
||||||
|
@ -11,4 +11,8 @@ public abstract class IndexedTransactionForm extends TransactionForm {
|
||||||
public int getIndex() {
|
public int getIndex() {
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setIndex(int index) {
|
||||||
|
this.index = index;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -570,4 +570,11 @@ public class InputController extends TransactionFormController implements Initia
|
||||||
updateScriptFields(event.getFinalTransaction().getInputs().get(inputForm.getIndex()), null);
|
updateScriptFields(event.getFinalTransaction().getInputs().get(inputForm.getIndex()), null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void psbtReordered(PSBTReorderedEvent event) {
|
||||||
|
if(event.getPsbt().equals(inputForm.getPsbt())) {
|
||||||
|
updateInputLegendFromWallet(inputForm.getTransactionInput(), null);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import com.sparrowwallet.drongo.wallet.BlockTransaction;
|
||||||
import com.sparrowwallet.drongo.wallet.Wallet;
|
import com.sparrowwallet.drongo.wallet.Wallet;
|
||||||
import com.sparrowwallet.sparrow.EventManager;
|
import com.sparrowwallet.sparrow.EventManager;
|
||||||
import com.sparrowwallet.sparrow.control.*;
|
import com.sparrowwallet.sparrow.control.*;
|
||||||
|
import com.sparrowwallet.sparrow.event.PSBTReorderedEvent;
|
||||||
import com.sparrowwallet.sparrow.event.UnitFormatChangedEvent;
|
import com.sparrowwallet.sparrow.event.UnitFormatChangedEvent;
|
||||||
import com.sparrowwallet.sparrow.event.BlockTransactionOutputsFetchedEvent;
|
import com.sparrowwallet.sparrow.event.BlockTransactionOutputsFetchedEvent;
|
||||||
import com.sparrowwallet.sparrow.event.ViewTransactionEvent;
|
import com.sparrowwallet.sparrow.event.ViewTransactionEvent;
|
||||||
|
@ -178,4 +179,11 @@ public class OutputController extends TransactionFormController implements Initi
|
||||||
public void unitFormatChanged(UnitFormatChangedEvent event) {
|
public void unitFormatChanged(UnitFormatChangedEvent event) {
|
||||||
value.refresh(event.getUnitFormat(), event.getBitcoinUnit());
|
value.refresh(event.getUnitFormat(), event.getBitcoinUnit());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void psbtReordered(PSBTReorderedEvent event) {
|
||||||
|
if(event.getPsbt().equals(outputForm.getPsbt())) {
|
||||||
|
updateOutputLegendFromWallet(outputForm.getTransactionOutput(), null);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,26 +9,20 @@ import javafx.scene.Node;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
public class OutputForm extends IndexedTransactionForm {
|
public class OutputForm extends IndexedTransactionForm {
|
||||||
private final TransactionOutput transactionOutput;
|
|
||||||
private PSBTOutput psbtOutput;
|
|
||||||
|
|
||||||
public OutputForm(TransactionData txdata, PSBTOutput psbtOutput) {
|
public OutputForm(TransactionData txdata, PSBTOutput psbtOutput) {
|
||||||
super(txdata, txdata.getPsbt().getPsbtOutputs().indexOf(psbtOutput));
|
super(txdata, txdata.getPsbt().getPsbtOutputs().indexOf(psbtOutput));
|
||||||
this.transactionOutput = txdata.getPsbt().getTransaction().getOutputs().get(txdata.getPsbt().getPsbtOutputs().indexOf(psbtOutput));
|
|
||||||
this.psbtOutput = psbtOutput;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public OutputForm(TransactionData txdata, TransactionOutput transactionOutput) {
|
public OutputForm(TransactionData txdata, TransactionOutput transactionOutput) {
|
||||||
super(txdata, txdata.getTransaction().getOutputs().indexOf(transactionOutput));
|
super(txdata, txdata.getTransaction().getOutputs().indexOf(transactionOutput));
|
||||||
this.transactionOutput = transactionOutput;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public TransactionOutput getTransactionOutput() {
|
public TransactionOutput getTransactionOutput() {
|
||||||
return transactionOutput;
|
if(txdata.getTransaction() != null) {
|
||||||
|
return txdata.getTransaction().getOutputs().get(getIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
public PSBTOutput getPsbtOutput() {
|
return null;
|
||||||
return psbtOutput;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isWalletConsolidation() {
|
public boolean isWalletConsolidation() {
|
||||||
|
@ -59,6 +53,6 @@ public class OutputForm extends IndexedTransactionForm {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Output #" + transactionOutput.getIndex();
|
return "Output #" + getIndex();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import javafx.scene.Parent;
|
||||||
import javafx.scene.control.TreeCell;
|
import javafx.scene.control.TreeCell;
|
||||||
import javafx.scene.control.TreeItem;
|
import javafx.scene.control.TreeItem;
|
||||||
import javafx.scene.control.TreeView;
|
import javafx.scene.control.TreeView;
|
||||||
|
import javafx.scene.input.*;
|
||||||
import javafx.scene.layout.Pane;
|
import javafx.scene.layout.Pane;
|
||||||
import org.controlsfx.control.MasterDetailPane;
|
import org.controlsfx.control.MasterDetailPane;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -35,6 +36,7 @@ import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class TransactionController implements Initializable {
|
public class TransactionController implements Initializable {
|
||||||
private static final Logger log = LoggerFactory.getLogger(TransactionController.class);
|
private static final Logger log = LoggerFactory.getLogger(TransactionController.class);
|
||||||
|
private static final DataFormat JAVA_FORMAT = new DataFormat("application/x-java-serialized-object");
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private Node tabContent;
|
private Node tabContent;
|
||||||
|
@ -62,6 +64,9 @@ public class TransactionController implements Initializable {
|
||||||
private boolean allInputsFetchedFromWallet;
|
private boolean allInputsFetchedFromWallet;
|
||||||
private boolean transactionsFetched;
|
private boolean transactionsFetched;
|
||||||
|
|
||||||
|
private TreeItem<TransactionForm> draggedItem;
|
||||||
|
private TreeCell<TransactionForm> dropZone;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initialize(URL location, ResourceBundle resources) {
|
public void initialize(URL location, ResourceBundle resources) {
|
||||||
EventManager.get().register(this);
|
EventManager.get().register(this);
|
||||||
|
@ -174,6 +179,14 @@ public class TransactionController implements Initializable {
|
||||||
setGraphic(TransactionDiagram.getPaymentGlyph());
|
setGraphic(TransactionDiagram.getPaymentGlyph());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setOnDragDetected(null);
|
||||||
|
setOnDragOver(null);
|
||||||
|
setOnDragDropped(null);
|
||||||
|
} else if(form.isEditable()) {
|
||||||
|
setOnDragDetected(event -> dragDetected(event, this));
|
||||||
|
setOnDragOver(event -> dragOver(event, this));
|
||||||
|
setOnDragDropped(event -> drop(event, this));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -463,6 +476,85 @@ public class TransactionController implements Initializable {
|
||||||
this.initialIndex = initialIndex;
|
this.initialIndex = initialIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void dragDetected(MouseEvent event, TreeCell<TransactionForm> treeCell) {
|
||||||
|
draggedItem = treeCell.getTreeItem();
|
||||||
|
|
||||||
|
if(!draggedItem.getChildren().isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Dragboard db = treeCell.startDragAndDrop(TransferMode.MOVE);
|
||||||
|
|
||||||
|
ClipboardContent content = new ClipboardContent();
|
||||||
|
content.put(JAVA_FORMAT, draggedItem.getValue().toString());
|
||||||
|
db.setContent(content);
|
||||||
|
db.setDragView(treeCell.snapshot(null, null));
|
||||||
|
event.consume();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void dragOver(DragEvent event, TreeCell<TransactionForm> treeCell) {
|
||||||
|
if(!event.getDragboard().hasContent(JAVA_FORMAT)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
TreeItem<TransactionForm> thisItem = treeCell.getTreeItem();
|
||||||
|
|
||||||
|
if(draggedItem == null || thisItem == null || thisItem == draggedItem) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(draggedItem.getParent() == null || thisItem.getParent() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(draggedItem.getValue() instanceof InputForm && (thisItem.getValue() instanceof OutputForm || thisItem.getValue() instanceof OutputsForm)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(draggedItem.getValue() instanceof OutputForm && (thisItem.getValue() instanceof InputForm || thisItem.getValue() instanceof InputsForm)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
event.acceptTransferModes(TransferMode.MOVE);
|
||||||
|
if(!Objects.equals(dropZone, treeCell)) {
|
||||||
|
this.dropZone = treeCell;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void drop(DragEvent event, TreeCell<TransactionForm> treeCell) {
|
||||||
|
Dragboard db = event.getDragboard();
|
||||||
|
if(!db.hasContent(JAVA_FORMAT)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TreeItem<TransactionForm> thisItem = treeCell.getTreeItem();
|
||||||
|
TreeItem<TransactionForm> droppedItemParent = draggedItem.getParent();
|
||||||
|
|
||||||
|
int fromIndex = droppedItemParent.getChildren().indexOf(draggedItem);
|
||||||
|
int toIndex = Objects.equals(droppedItemParent, thisItem) ? 0 : thisItem.getParent().getChildren().indexOf(thisItem);
|
||||||
|
droppedItemParent.getChildren().remove(draggedItem);
|
||||||
|
|
||||||
|
if(Objects.equals(droppedItemParent, thisItem)) {
|
||||||
|
thisItem.getChildren().add(toIndex, draggedItem);
|
||||||
|
} else {
|
||||||
|
thisItem.getParent().getChildren().add(toIndex, draggedItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
PSBT psbt = getPSBT();
|
||||||
|
if(draggedItem.getValue() instanceof InputForm) {
|
||||||
|
psbt.moveInput(fromIndex, toIndex);
|
||||||
|
} else if(draggedItem.getValue() instanceof OutputForm) {
|
||||||
|
psbt.moveOutput(fromIndex, toIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < draggedItem.getParent().getChildren().size(); i++) {
|
||||||
|
if(draggedItem.getParent().getChildren().get(i).getValue() instanceof IndexedTransactionForm indexedTransactionForm) {
|
||||||
|
indexedTransactionForm.setIndex(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
txdata.setTransaction(psbt.getTransaction());
|
||||||
|
txtree.getSelectionModel().select(draggedItem);
|
||||||
|
event.setDropCompleted(true);
|
||||||
|
|
||||||
|
EventManager.get().post(new PSBTReorderedEvent(psbt));
|
||||||
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void viewTransaction(ViewTransactionEvent event) {
|
public void viewTransaction(ViewTransactionEvent event) {
|
||||||
if(txdata.getTransaction().getTxId().equals(event.getTransaction().getTxId())) {
|
if(txdata.getTransaction().getTxId().equals(event.getTransaction().getTxId())) {
|
||||||
|
@ -594,4 +686,12 @@ public class TransactionController implements Initializable {
|
||||||
fetchTransactions();
|
fetchTransactions();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void psbtReordered(PSBTReorderedEvent event) {
|
||||||
|
if(event.getPsbt() == getPSBT()) {
|
||||||
|
txhex.setTransaction(getTransaction());
|
||||||
|
highlightTxHex();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue