mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2024-12-23 20:36:44 +00:00
add google guava for event bus, app control changes
This commit is contained in:
parent
16bac7326e
commit
fb9de5be56
16 changed files with 209 additions and 115 deletions
|
@ -28,6 +28,7 @@ dependencies {
|
|||
exclude group: 'org.hamcrest'
|
||||
exclude group: 'junit'
|
||||
}
|
||||
implementation('com.google.guava:guava:28.2-jre')
|
||||
implementation('org.fxmisc.richtext:richtextfx:0.10.4')
|
||||
implementation('no.tornado:tornadofx-controls:1.0.4')
|
||||
implementation('org.controlsfx:controlsfx:11.0.1' ) {
|
||||
|
@ -56,7 +57,7 @@ jlink {
|
|||
requires 'javafx.base';
|
||||
}
|
||||
|
||||
options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages', '--ignore-signing-information']
|
||||
options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages', '--ignore-signing-information', '--exclude-files', '**.png']
|
||||
launcher {
|
||||
name = 'sparrow'
|
||||
jvmArgs = ["--add-opens=javafx.graphics/com.sun.javafx.css=org.controlsfx.controls"]
|
||||
|
@ -75,7 +76,6 @@ jlink {
|
|||
}
|
||||
if (org.gradle.internal.os.OperatingSystem.current().macOsX) {
|
||||
imageOptions += ['--icon', 'src/main/resources/sparrow.icns']
|
||||
|
||||
installerType = "dmg"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
package com.sparrowwallet.sparrow;
|
||||
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import com.sparrowwallet.drongo.Utils;
|
||||
import com.sparrowwallet.drongo.protocol.Transaction;
|
||||
import com.sparrowwallet.drongo.psbt.PSBT;
|
||||
import com.sparrowwallet.drongo.psbt.PSBTParseException;
|
||||
import com.sparrowwallet.sparrow.event.TabEvent;
|
||||
import com.sparrowwallet.sparrow.event.TransactionTabChangedEvent;
|
||||
import com.sparrowwallet.sparrow.event.TransactionTabSelectedEvent;
|
||||
import com.sparrowwallet.sparrow.transaction.TransactionController;
|
||||
import com.sparrowwallet.sparrow.transaction.TransactionListener;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.control.Alert;
|
||||
import javafx.scene.control.Tab;
|
||||
import javafx.scene.control.TabPane;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.stage.FileChooser;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
|
@ -23,6 +24,10 @@ import java.net.URL;
|
|||
import java.util.ResourceBundle;
|
||||
|
||||
public class AppController implements Initializable {
|
||||
private static final String TRANSACTION_TAB_TYPE = "transaction";
|
||||
|
||||
@FXML
|
||||
private CheckMenuItem showTxHex;
|
||||
|
||||
@FXML
|
||||
private TabPane tabs;
|
||||
|
@ -33,14 +38,15 @@ public class AppController implements Initializable {
|
|||
}
|
||||
|
||||
void initializeView() {
|
||||
tabs.getSelectionModel().selectedItemProperty().addListener((observable, old_val, new_val) -> {
|
||||
String tabName = new_val.getText();
|
||||
if(tabs.getScene() != null) {
|
||||
Stage tabStage = (Stage)tabs.getScene().getWindow();
|
||||
tabStage.setTitle("Sparrow - " + tabName);
|
||||
tabs.getSelectionModel().selectedItemProperty().addListener((observable, old_val, selectedTab) -> {
|
||||
String tabType = (String)selectedTab.getUserData();
|
||||
if(tabType.equals(TRANSACTION_TAB_TYPE)) {
|
||||
EventManager.get().post(new TransactionTabSelectedEvent(selectedTab));
|
||||
}
|
||||
});
|
||||
|
||||
showTxHex.setSelected(true);
|
||||
|
||||
addExampleTxTabs();
|
||||
}
|
||||
|
||||
|
@ -99,6 +105,11 @@ public class AppController implements Initializable {
|
|||
}
|
||||
}
|
||||
|
||||
public void showTxHex(ActionEvent event) {
|
||||
CheckMenuItem item = (CheckMenuItem)event.getSource();
|
||||
EventManager.get().post(new TransactionTabChangedEvent(tabs.getSelectionModel().getSelectedItem(), item.isSelected()));
|
||||
}
|
||||
|
||||
private void addExampleTxTabs() {
|
||||
addTransactionTab("p2pkh", "01000000019c2e0f24a03e72002a96acedb12a632e72b6b74c05dc3ceab1fe78237f886c48010000006a47304402203da9d487be5302a6d69e02a861acff1da472885e43d7528ed9b1b537a8e2cac9022002d1bca03a1e9715a99971bafe3b1852b7a4f0168281cbd27a220380a01b3307012102c9950c622494c2e9ff5a003e33b690fe4832477d32c2d256c67eab8bf613b34effffffff02b6f50500000000001976a914bdf63990d6dc33d705b756e13dd135466c06b3b588ac845e0201000000001976a9145fb0e9755a3424efd2ba0587d20b1e98ee29814a88ac06241559", null);
|
||||
addTransactionTab("p2sh", "0100000003a5ee1a0fd80dfbc3142df136ab56e082b799c13aa977c048bdf8f61bd158652c000000006b48304502203b0160de302cded63589a88214fe499a25aa1d86a2ea09129945cd632476a12c022100c77727daf0718307e184d55df620510cf96d4b5814ae3258519c0482c1ca82fa0121024f4102c1f1cf662bf99f2b034eb03edd4e6c96793cb9445ff519aab580649120ffffffff0fce901eb7b7551ba5f414735ff93b83a2a57403df11059ec88245fba2aaf1a0000000006a47304402204089adb8a1de1a9e22aa43b94d54f1e54dc9bea745d57df1a633e03dd9ede3c2022037d1e53e911ed7212186028f2e085f70524930e22eb6184af090ba4ab779a5b90121030644cb394bf381dbec91680bdf1be1986ad93cfb35603697353199fb285a119effffffff0fce901eb7b7551ba5f414735ff93b83a2a57403df11059ec88245fba2aaf1a0010000009300493046022100a07b2821f96658c938fa9c68950af0e69f3b2ce5f8258b3a6ad254d4bc73e11e022100e82fab8df3f7e7a28e91b3609f91e8ebf663af3a4dc2fd2abd954301a5da67e701475121022afc20bf379bc96a2f4e9e63ffceb8652b2b6a097f63fbee6ecec2a49a48010e2103a767c7221e9f15f870f1ad9311f5ab937d79fcaeee15bb2c722bca515581b4c052aeffffffff02a3b81b00000000001976a914ea00917f128f569cbdf79da5efcd9001671ab52c88ac80969800000000001976a9143dec0ead289be1afa8da127a7dbdd425a05e25f688ac00000000", null);
|
||||
|
@ -131,6 +142,7 @@ public class AppController implements Initializable {
|
|||
private Tab addTransactionTab(String name, Transaction transaction, PSBT psbt) {
|
||||
try {
|
||||
Tab tab = new Tab(name);
|
||||
tab.setUserData(TRANSACTION_TAB_TYPE);
|
||||
tab.setClosable(true);
|
||||
FXMLLoader transactionLoader = new FXMLLoader(getClass().getResource("transaction/transaction.fxml"));
|
||||
tab.setContent(transactionLoader.load());
|
||||
|
@ -148,4 +160,16 @@ public class AppController implements Initializable {
|
|||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void tabSelected(TabEvent event) {
|
||||
Tab selectedTab = event.getTab();
|
||||
String tabType = (String)selectedTab.getUserData();
|
||||
|
||||
String tabName = selectedTab.getText();
|
||||
if(tabs.getScene() != null) {
|
||||
Stage tabStage = (Stage)tabs.getScene().getWindow();
|
||||
tabStage.setTitle("Sparrow - " + tabName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,32 +1,13 @@
|
|||
package com.sparrowwallet.sparrow;
|
||||
|
||||
import com.sparrowwallet.drongo.protocol.Transaction;
|
||||
import com.sparrowwallet.sparrow.transaction.TransactionListener;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import com.google.common.eventbus.EventBus;
|
||||
|
||||
public class EventManager {
|
||||
private List<TransactionListener> listenerList = new ArrayList<>();
|
||||
private static EventManager SINGLETON = new EventManager();
|
||||
private static EventBus SINGLETON = new EventBus();
|
||||
|
||||
private EventManager() {}
|
||||
|
||||
public void subscribe(TransactionListener listener) {
|
||||
listenerList.add(listener);
|
||||
}
|
||||
|
||||
public void unsubscribe(TransactionListener listener) {
|
||||
listenerList.remove(listener);
|
||||
}
|
||||
|
||||
public void notify(Transaction transaction) {
|
||||
for (TransactionListener listener : listenerList) {
|
||||
listener.updated(transaction);
|
||||
}
|
||||
}
|
||||
|
||||
public static EventManager get() {
|
||||
public static EventBus get() {
|
||||
return SINGLETON;
|
||||
}
|
||||
}
|
||||
|
|
15
src/main/java/com/sparrowwallet/sparrow/event/TabEvent.java
Normal file
15
src/main/java/com/sparrowwallet/sparrow/event/TabEvent.java
Normal file
|
@ -0,0 +1,15 @@
|
|||
package com.sparrowwallet.sparrow.event;
|
||||
|
||||
import javafx.scene.control.Tab;
|
||||
|
||||
public class TabEvent {
|
||||
private Tab tab;
|
||||
|
||||
public TabEvent(Tab tab) {
|
||||
this.tab = tab;
|
||||
}
|
||||
|
||||
public Tab getTab() {
|
||||
return tab;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package com.sparrowwallet.sparrow.event;
|
||||
|
||||
import com.sparrowwallet.drongo.protocol.Transaction;
|
||||
|
||||
public class TransactionChangedEvent {
|
||||
private Transaction transaction;
|
||||
|
||||
public TransactionChangedEvent(Transaction transaction) {
|
||||
this.transaction = transaction;
|
||||
}
|
||||
|
||||
public Transaction getTransaction() {
|
||||
return transaction;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package com.sparrowwallet.sparrow.event;
|
||||
|
||||
import javafx.scene.control.Tab;
|
||||
|
||||
public class TransactionTabChangedEvent extends TabEvent {
|
||||
private boolean txHexVisible;
|
||||
|
||||
public TransactionTabChangedEvent(Tab tab, boolean txHexVisible) {
|
||||
super(tab);
|
||||
this.txHexVisible = txHexVisible;
|
||||
}
|
||||
|
||||
public boolean isTxHexVisible() {
|
||||
return txHexVisible;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package com.sparrowwallet.sparrow.event;
|
||||
|
||||
import javafx.scene.control.Tab;
|
||||
|
||||
public class TransactionTabSelectedEvent extends TabEvent {
|
||||
public TransactionTabSelectedEvent(Tab tab) {
|
||||
super(tab);
|
||||
}
|
||||
}
|
|
@ -4,18 +4,20 @@ import com.sparrowwallet.drongo.protocol.Transaction;
|
|||
import com.sparrowwallet.sparrow.EventManager;
|
||||
import com.sparrowwallet.sparrow.control.IdLabel;
|
||||
import com.sparrowwallet.sparrow.control.CopyableLabel;
|
||||
import com.sparrowwallet.sparrow.event.TransactionChangedEvent;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.control.*;
|
||||
import tornadofx.control.DateTimePicker;
|
||||
import tornadofx.control.Field;
|
||||
import tornadofx.control.Fieldset;
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
|
||||
import java.net.URL;
|
||||
import java.time.*;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
public class HeadersController extends TransactionFormController implements Initializable, TransactionListener {
|
||||
public class HeadersController extends TransactionFormController implements Initializable {
|
||||
public static final String LOCKTIME_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
|
||||
|
||||
private HeadersForm headersForm;
|
||||
|
@ -76,7 +78,7 @@ public class HeadersController extends TransactionFormController implements Init
|
|||
|
||||
@Override
|
||||
public void initialize(URL location, ResourceBundle resources) {
|
||||
EventManager.get().subscribe(this);
|
||||
EventManager.get().register(this);
|
||||
}
|
||||
|
||||
void setModel(HeadersForm form) {
|
||||
|
@ -92,7 +94,7 @@ public class HeadersController extends TransactionFormController implements Init
|
|||
version.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(1, 2, (int)tx.getVersion()));
|
||||
version.valueProperty().addListener((obs, oldValue, newValue) -> {
|
||||
tx.setVersion(newValue);
|
||||
EventManager.get().notify(tx);
|
||||
EventManager.get().post(new TransactionChangedEvent(tx));
|
||||
});
|
||||
|
||||
String type = "Legacy";
|
||||
|
@ -113,7 +115,7 @@ public class HeadersController extends TransactionFormController implements Init
|
|||
locktimeFieldset.getChildren().remove(locktimeNoneField);
|
||||
locktimeFieldset.getChildren().add(locktimeNoneField);
|
||||
tx.setLocktime(0);
|
||||
EventManager.get().notify(tx);
|
||||
EventManager.get().post(new TransactionChangedEvent(tx));
|
||||
} else if(selection.equals("block")) {
|
||||
locktimeFieldset.getChildren().remove(locktimeDateField);
|
||||
locktimeFieldset.getChildren().remove(locktimeBlockField);
|
||||
|
@ -122,7 +124,7 @@ public class HeadersController extends TransactionFormController implements Init
|
|||
Integer block = locktimeBlock.getValue();
|
||||
if(block != null) {
|
||||
tx.setLocktime(block);
|
||||
EventManager.get().notify(tx);
|
||||
EventManager.get().post(new TransactionChangedEvent(tx));
|
||||
}
|
||||
} else {
|
||||
locktimeFieldset.getChildren().remove(locktimeBlockField);
|
||||
|
@ -133,7 +135,7 @@ public class HeadersController extends TransactionFormController implements Init
|
|||
if(date != null) {
|
||||
locktimeDate.setDateTimeValue(date);
|
||||
tx.setLocktime(date.toEpochSecond(OffsetDateTime.now(ZoneId.systemDefault()).getOffset()));
|
||||
EventManager.get().notify(tx);
|
||||
EventManager.get().post(new TransactionChangedEvent(tx));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -158,13 +160,13 @@ public class HeadersController extends TransactionFormController implements Init
|
|||
|
||||
locktimeBlock.valueProperty().addListener((obs, oldValue, newValue) -> {
|
||||
tx.setLocktime(newValue);
|
||||
EventManager.get().notify(tx);
|
||||
EventManager.get().post(new TransactionChangedEvent(tx));
|
||||
});
|
||||
|
||||
locktimeDate.setFormat(LOCKTIME_DATE_FORMAT);
|
||||
locktimeDate.dateTimeValueProperty().addListener((obs, oldValue, newValue) -> {
|
||||
tx.setLocktime(newValue.toEpochSecond(OffsetDateTime.now(ZoneId.systemDefault()).getOffset()));
|
||||
EventManager.get().notify(tx);
|
||||
EventManager.get().post(new TransactionChangedEvent(tx));
|
||||
});
|
||||
|
||||
size.setText(tx.getSize() + " B");
|
||||
|
@ -188,15 +190,16 @@ public class HeadersController extends TransactionFormController implements Init
|
|||
id.setText(headersForm.getTransaction().calculateTxId(false).toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updated(Transaction transaction) {
|
||||
updateTxId();
|
||||
|
||||
boolean locktimeEnabled = headersForm.getTransaction().isLocktimeSequenceEnabled();
|
||||
locktimeNoneType.setDisable(!locktimeEnabled);
|
||||
locktimeBlockType.setDisable(!locktimeEnabled);
|
||||
locktimeBlock.setDisable(!locktimeEnabled);
|
||||
locktimeDateType.setDisable(!locktimeEnabled);
|
||||
locktimeDate.setDisable(!locktimeEnabled);
|
||||
@Subscribe
|
||||
public void transactionChanged(TransactionChangedEvent event) {
|
||||
if(headersForm.getTransaction().equals(event.getTransaction())) {
|
||||
updateTxId();
|
||||
boolean locktimeEnabled = headersForm.getTransaction().isLocktimeSequenceEnabled();
|
||||
locktimeNoneType.setDisable(!locktimeEnabled);
|
||||
locktimeBlockType.setDisable(!locktimeEnabled);
|
||||
locktimeBlock.setDisable(!locktimeEnabled);
|
||||
locktimeDateType.setDisable(!locktimeEnabled);
|
||||
locktimeDate.setDisable(!locktimeEnabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import com.sparrowwallet.sparrow.EventManager;
|
|||
import com.sparrowwallet.sparrow.control.IdLabel;
|
||||
import com.sparrowwallet.sparrow.control.CopyableLabel;
|
||||
import com.sparrowwallet.sparrow.control.RelativeTimelockSpinner;
|
||||
import com.sparrowwallet.sparrow.event.TransactionChangedEvent;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.control.*;
|
||||
|
@ -243,12 +244,12 @@ public class InputController extends TransactionFormController implements Initia
|
|||
locktimeToggleGroup.selectToggle(locktimeAbsoluteType);
|
||||
} else if(txInput.isAbsoluteTimeLocked()) {
|
||||
txInput.setSequenceNumber(TransactionInput.SEQUENCE_RBF_ENABLED);
|
||||
EventManager.get().notify(transaction);
|
||||
EventManager.get().post(new TransactionChangedEvent(transaction));
|
||||
}
|
||||
} else {
|
||||
if(txInput.isAbsoluteTimeLocked()) {
|
||||
txInput.setSequenceNumber(TransactionInput.SEQUENCE_LOCKTIME_DISABLED - 1);
|
||||
EventManager.get().notify(transaction);
|
||||
EventManager.get().post(new TransactionChangedEvent(transaction));
|
||||
} else if(txInput.isRelativeTimeLocked()) {
|
||||
locktimeToggleGroup.selectToggle(locktimeAbsoluteType);
|
||||
}
|
||||
|
@ -268,7 +269,7 @@ public class InputController extends TransactionFormController implements Initia
|
|||
locktimeAbsoluteField.setDisable(true);
|
||||
txInput.setSequenceNumber(TransactionInput.SEQUENCE_LOCKTIME_DISABLED);
|
||||
rbf.setSelected(false);
|
||||
EventManager.get().notify(transaction);
|
||||
EventManager.get().post(new TransactionChangedEvent(transaction));
|
||||
} else if(selection.equals("absolute")) {
|
||||
locktimeFieldset.getChildren().removeAll(locktimeRelativeField, locktimeAbsoluteField);
|
||||
locktimeFieldset.getChildren().add(locktimeAbsoluteField);
|
||||
|
@ -279,7 +280,7 @@ public class InputController extends TransactionFormController implements Initia
|
|||
} else {
|
||||
txInput.setSequenceNumber(TransactionInput.SEQUENCE_LOCKTIME_DISABLED - 1);
|
||||
}
|
||||
EventManager.get().notify(transaction);
|
||||
EventManager.get().post(new TransactionChangedEvent(transaction));
|
||||
} else {
|
||||
locktimeFieldset.getChildren().removeAll(locktimeRelativeField, locktimeAbsoluteField);
|
||||
locktimeFieldset.getChildren().add(locktimeRelativeField);
|
||||
|
@ -348,7 +349,7 @@ public class InputController extends TransactionFormController implements Initia
|
|||
long value = locktimeRelativeSeconds.getValue().toSeconds() / TransactionInput.RELATIVE_TIMELOCK_SECONDS_INCREMENT;
|
||||
txInput.setSequenceNumber((value & TransactionInput.RELATIVE_TIMELOCK_VALUE_MASK) | TransactionInput.RELATIVE_TIMELOCK_TYPE_FLAG);
|
||||
}
|
||||
EventManager.get().notify(transaction);
|
||||
EventManager.get().post(new TransactionChangedEvent(transaction));
|
||||
}
|
||||
|
||||
public void setModel(InputForm form) {
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
package com.sparrowwallet.sparrow.transaction;
|
||||
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import com.sparrowwallet.drongo.Utils;
|
||||
import com.sparrowwallet.drongo.protocol.*;
|
||||
import com.sparrowwallet.drongo.psbt.PSBT;
|
||||
import com.sparrowwallet.drongo.psbt.PSBTInput;
|
||||
import com.sparrowwallet.drongo.psbt.PSBTOutput;
|
||||
import com.sparrowwallet.sparrow.EventManager;
|
||||
import com.sparrowwallet.sparrow.event.TransactionChangedEvent;
|
||||
import com.sparrowwallet.sparrow.event.TransactionTabChangedEvent;
|
||||
import com.sparrowwallet.sparrow.event.TransactionTabSelectedEvent;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.Node;
|
||||
|
@ -15,6 +19,7 @@ import javafx.scene.control.TreeView;
|
|||
import javafx.scene.control.cell.TextFieldTreeCell;
|
||||
import javafx.scene.layout.Pane;
|
||||
import javafx.util.StringConverter;
|
||||
import org.controlsfx.control.MasterDetailPane;
|
||||
import org.fxmisc.richtext.CodeArea;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
@ -22,7 +27,13 @@ import java.io.IOException;
|
|||
import java.net.URL;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
public class TransactionController implements Initializable, TransactionListener {
|
||||
public class TransactionController implements Initializable {
|
||||
|
||||
@FXML
|
||||
private Node tabContent;
|
||||
|
||||
@FXML
|
||||
private MasterDetailPane transactionMasterDetail;
|
||||
|
||||
@FXML
|
||||
private TreeView<TransactionForm> txtree;
|
||||
|
@ -40,7 +51,7 @@ public class TransactionController implements Initializable, TransactionListener
|
|||
|
||||
@Override
|
||||
public void initialize(URL location, ResourceBundle resources) {
|
||||
EventManager.get().subscribe(this);
|
||||
EventManager.get().register(this);
|
||||
}
|
||||
|
||||
private void initializeView() {
|
||||
|
@ -56,9 +67,9 @@ public class TransactionController implements Initializable, TransactionListener
|
|||
InputsForm inputsForm = (psbt == null ? new InputsForm(transaction) : new InputsForm(psbt));
|
||||
TreeItem<TransactionForm> inputsItem = new TreeItem<>(inputsForm);
|
||||
inputsItem.setExpanded(true);
|
||||
for(TransactionInput txInput : transaction.getInputs()) {
|
||||
for (TransactionInput txInput : transaction.getInputs()) {
|
||||
PSBTInput psbtInput = null;
|
||||
if(psbt != null && psbt.getPsbtInputs().size() > txInput.getIndex()) {
|
||||
if (psbt != null && psbt.getPsbtInputs().size() > txInput.getIndex()) {
|
||||
psbtInput = psbt.getPsbtInputs().get(txInput.getIndex());
|
||||
}
|
||||
InputForm inputForm = (psbt == null ? new InputForm(transaction, txInput) : new InputForm(psbt, psbtInput));
|
||||
|
@ -69,9 +80,9 @@ public class TransactionController implements Initializable, TransactionListener
|
|||
OutputsForm outputsForm = (psbt == null ? new OutputsForm(transaction) : new OutputsForm(psbt));
|
||||
TreeItem<TransactionForm> outputsItem = new TreeItem<>(outputsForm);
|
||||
outputsItem.setExpanded(true);
|
||||
for(TransactionOutput txOutput : transaction.getOutputs()) {
|
||||
for (TransactionOutput txOutput : transaction.getOutputs()) {
|
||||
PSBTOutput psbtOutput = null;
|
||||
if(psbt != null && psbt.getPsbtOutputs().size() > txOutput.getIndex()) {
|
||||
if (psbt != null && psbt.getPsbtOutputs().size() > txOutput.getIndex()) {
|
||||
psbtOutput = psbt.getPsbtOutputs().get(txOutput.getIndex());
|
||||
}
|
||||
OutputForm outputForm = (psbt == null ? new OutputForm(transaction, txOutput) : new OutputForm(psbt, psbtOutput));
|
||||
|
@ -83,7 +94,7 @@ public class TransactionController implements Initializable, TransactionListener
|
|||
rootItem.getChildren().add(outputsItem);
|
||||
txtree.setRoot(rootItem);
|
||||
|
||||
txtree.setCellFactory(p -> new TextFieldTreeCell<>(new StringConverter<TransactionForm>(){
|
||||
txtree.setCellFactory(p -> new TextFieldTreeCell<>(new StringConverter<TransactionForm>() {
|
||||
@Override
|
||||
public String toString(TransactionForm transactionForm) {
|
||||
return transactionForm.toString();
|
||||
|
@ -102,18 +113,18 @@ public class TransactionController implements Initializable, TransactionListener
|
|||
txpane.getChildren().clear();
|
||||
txpane.getChildren().add(node);
|
||||
|
||||
if(node instanceof Parent) {
|
||||
Parent parent = (Parent)node;
|
||||
if (node instanceof Parent) {
|
||||
Parent parent = (Parent) node;
|
||||
txhex.getStylesheets().clear();
|
||||
txhex.getStylesheets().addAll(parent.getStylesheets());
|
||||
|
||||
selectedInputIndex = -1;
|
||||
selectedOutputIndex = -1;
|
||||
if(transactionForm instanceof InputForm) {
|
||||
InputForm inputForm = (InputForm)transactionForm;
|
||||
if (transactionForm instanceof InputForm) {
|
||||
InputForm inputForm = (InputForm) transactionForm;
|
||||
selectedInputIndex = inputForm.getTransactionInput().getIndex();
|
||||
} else if(transactionForm instanceof OutputForm) {
|
||||
OutputForm outputForm = (OutputForm)transactionForm;
|
||||
} else if (transactionForm instanceof OutputForm) {
|
||||
OutputForm outputForm = (OutputForm) transactionForm;
|
||||
selectedOutputIndex = outputForm.getTransactionOutput().getIndex();
|
||||
}
|
||||
|
||||
|
@ -135,7 +146,7 @@ public class TransactionController implements Initializable, TransactionListener
|
|||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
transaction.bitcoinSerializeToStream(baos);
|
||||
hex = Utils.bytesToHex(baos.toByteArray());
|
||||
} catch(IOException e) {
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException("Can't happen");
|
||||
}
|
||||
|
||||
|
@ -144,7 +155,7 @@ public class TransactionController implements Initializable, TransactionListener
|
|||
//Version
|
||||
cursor = addText(hex, cursor, 8, "version");
|
||||
|
||||
if(transaction.hasWitnesses()) {
|
||||
if (transaction.hasWitnesses()) {
|
||||
//Segwit marker
|
||||
cursor = addText(hex, cursor, 2, "segwit-marker");
|
||||
//Segwit flag
|
||||
|
@ -153,43 +164,43 @@ public class TransactionController implements Initializable, TransactionListener
|
|||
|
||||
//Number of inputs
|
||||
VarInt numInputs = new VarInt(transaction.getInputs().size());
|
||||
cursor = addText(hex, cursor, numInputs.getSizeInBytes()*2, "num-inputs");
|
||||
cursor = addText(hex, cursor, numInputs.getSizeInBytes() * 2, "num-inputs");
|
||||
|
||||
//Inputs
|
||||
for (int i = 0; i < transaction.getInputs().size(); i++) {
|
||||
TransactionInput input = transaction.getInputs().get(i);
|
||||
cursor = addText(hex, cursor, 32*2, "input-" + getIndexedStyleClass(i, selectedInputIndex, "hash"));
|
||||
cursor = addText(hex, cursor, 4*2, "input-" + getIndexedStyleClass(i, selectedInputIndex, "index"));
|
||||
cursor = addText(hex, cursor, 32 * 2, "input-" + getIndexedStyleClass(i, selectedInputIndex, "hash"));
|
||||
cursor = addText(hex, cursor, 4 * 2, "input-" + getIndexedStyleClass(i, selectedInputIndex, "index"));
|
||||
VarInt scriptLen = new VarInt(input.getScriptBytes().length);
|
||||
cursor = addText(hex, cursor, scriptLen.getSizeInBytes()*2, "input-" + getIndexedStyleClass(i, selectedInputIndex, "sigscript-length"));
|
||||
cursor = addText(hex, cursor, (int)scriptLen.value*2, "input-" + getIndexedStyleClass(i, selectedInputIndex, "sigscript"));
|
||||
cursor = addText(hex, cursor, 4*2, "input-" + getIndexedStyleClass(i, selectedInputIndex, "sequence"));
|
||||
cursor = addText(hex, cursor, scriptLen.getSizeInBytes() * 2, "input-" + getIndexedStyleClass(i, selectedInputIndex, "sigscript-length"));
|
||||
cursor = addText(hex, cursor, (int) scriptLen.value * 2, "input-" + getIndexedStyleClass(i, selectedInputIndex, "sigscript"));
|
||||
cursor = addText(hex, cursor, 4 * 2, "input-" + getIndexedStyleClass(i, selectedInputIndex, "sequence"));
|
||||
}
|
||||
|
||||
//Number of outputs
|
||||
VarInt numOutputs = new VarInt(transaction.getOutputs().size());
|
||||
cursor = addText(hex, cursor, numOutputs.getSizeInBytes()*2, "num-outputs");
|
||||
cursor = addText(hex, cursor, numOutputs.getSizeInBytes() * 2, "num-outputs");
|
||||
|
||||
//Outputs
|
||||
for (int i = 0; i < transaction.getOutputs().size(); i++) {
|
||||
TransactionOutput output = transaction.getOutputs().get(i);
|
||||
cursor = addText(hex, cursor, 8*2, "output-" + getIndexedStyleClass(i, selectedOutputIndex, "value"));
|
||||
cursor = addText(hex, cursor, 8 * 2, "output-" + getIndexedStyleClass(i, selectedOutputIndex, "value"));
|
||||
VarInt scriptLen = new VarInt(output.getScriptBytes().length);
|
||||
cursor = addText(hex, cursor, scriptLen.getSizeInBytes()*2, "output-" + getIndexedStyleClass(i, selectedOutputIndex, "pubkeyscript-length"));
|
||||
cursor = addText(hex, cursor, (int)scriptLen.value*2, "output-" + getIndexedStyleClass(i, selectedOutputIndex, "pubkeyscript"));
|
||||
cursor = addText(hex, cursor, scriptLen.getSizeInBytes() * 2, "output-" + getIndexedStyleClass(i, selectedOutputIndex, "pubkeyscript-length"));
|
||||
cursor = addText(hex, cursor, (int) scriptLen.value * 2, "output-" + getIndexedStyleClass(i, selectedOutputIndex, "pubkeyscript"));
|
||||
}
|
||||
|
||||
if(transaction.hasWitnesses()) {
|
||||
if (transaction.hasWitnesses()) {
|
||||
for (int i = 0; i < transaction.getInputs().size(); i++) {
|
||||
TransactionInput input = transaction.getInputs().get(i);
|
||||
if(input.hasWitness()) {
|
||||
if (input.hasWitness()) {
|
||||
TransactionWitness witness = input.getWitness();
|
||||
VarInt witnessCount = new VarInt(witness.getPushCount());
|
||||
cursor = addText(hex, cursor, witnessCount.getSizeInBytes()*2, "witness-" + getIndexedStyleClass(i, selectedInputIndex, "count"));
|
||||
for(byte[] push : witness.getPushes()) {
|
||||
cursor = addText(hex, cursor, witnessCount.getSizeInBytes() * 2, "witness-" + getIndexedStyleClass(i, selectedInputIndex, "count"));
|
||||
for (byte[] push : witness.getPushes()) {
|
||||
VarInt witnessLen = new VarInt(push.length);
|
||||
cursor = addText(hex, cursor, witnessLen.getSizeInBytes()*2, "witness-" + getIndexedStyleClass(i, selectedInputIndex, "length"));
|
||||
cursor = addText(hex, cursor, (int)witnessLen.value*2, "witness-" + getIndexedStyleClass(i, selectedInputIndex, "data"));
|
||||
cursor = addText(hex, cursor, witnessLen.getSizeInBytes() * 2, "witness-" + getIndexedStyleClass(i, selectedInputIndex, "length"));
|
||||
cursor = addText(hex, cursor, (int) witnessLen.value * 2, "witness-" + getIndexedStyleClass(i, selectedInputIndex, "data"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -198,13 +209,13 @@ public class TransactionController implements Initializable, TransactionListener
|
|||
//Locktime
|
||||
cursor = addText(hex, cursor, 8, "locktime");
|
||||
|
||||
if(cursor != hex.length()) {
|
||||
if (cursor != hex.length()) {
|
||||
throw new IllegalStateException("Cursor position does not match transaction serialisation " + cursor + ": " + hex.length());
|
||||
}
|
||||
}
|
||||
|
||||
private String getIndexedStyleClass(int iterableIndex, int selectedIndex, String styleClass) {
|
||||
if(selectedIndex == -1 || selectedIndex == iterableIndex) {
|
||||
if (selectedIndex == -1 || selectedIndex == iterableIndex) {
|
||||
return styleClass;
|
||||
}
|
||||
|
||||
|
@ -212,7 +223,7 @@ public class TransactionController implements Initializable, TransactionListener
|
|||
}
|
||||
|
||||
private int addText(String hex, int cursor, int length, String styleClass) {
|
||||
txhex.append(hex.substring(cursor, cursor+=length), styleClass);
|
||||
txhex.append(hex.substring(cursor, cursor += length), styleClass);
|
||||
return cursor;
|
||||
}
|
||||
|
||||
|
@ -229,9 +240,21 @@ public class TransactionController implements Initializable, TransactionListener
|
|||
initializeView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updated(Transaction transaction) {
|
||||
refreshTxHex();
|
||||
txtree.refresh();
|
||||
@Subscribe
|
||||
public void transactionChanged(TransactionChangedEvent event) {
|
||||
if (event.getTransaction().equals(transaction)) {
|
||||
refreshTxHex();
|
||||
txtree.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void tabSelected(TransactionTabSelectedEvent event) {
|
||||
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void tabChanged(TransactionTabChangedEvent event) {
|
||||
transactionMasterDetail.setShowDetailNode(event.isTxHexVisible());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
package com.sparrowwallet.sparrow.transaction;
|
||||
|
||||
import com.sparrowwallet.drongo.protocol.Transaction;
|
||||
|
||||
public interface TransactionListener {
|
||||
void updated(Transaction transaction);
|
||||
}
|
|
@ -6,5 +6,6 @@ open module com.sparrowwallet.sparrow {
|
|||
requires org.fxmisc.richtext;
|
||||
requires tornadofx.controls;
|
||||
requires com.sparrowwallet.drongo;
|
||||
requires com.google.common;
|
||||
requires flowless;
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
<?import javafx.scene.control.*?>
|
||||
<?import javafx.scene.layout.*?>
|
||||
<?import org.controlsfx.control.StatusBar?>
|
||||
|
||||
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="750.0" prefWidth="1100.0" fx:controller="com.sparrowwallet.sparrow.AppController" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1">
|
||||
<children>
|
||||
|
@ -18,6 +19,11 @@
|
|||
<MenuItem mnemonicParsing="false" text="Delete" />
|
||||
</items>
|
||||
</Menu>
|
||||
<Menu mnemonicParsing="false" text="View">
|
||||
<items>
|
||||
<CheckMenuItem fx:id="showTxHex" mnemonicParsing="false" text="Show Transaction Hex" onAction="#showTxHex" />
|
||||
</items>
|
||||
</Menu>
|
||||
<Menu mnemonicParsing="false" text="Help">
|
||||
<items>
|
||||
<MenuItem mnemonicParsing="false" text="About" />
|
||||
|
@ -27,6 +33,6 @@
|
|||
</MenuBar>
|
||||
<TabPane prefHeight="200.0" prefWidth="200.0" VBox.vgrow="ALWAYS" fx:id="tabs" />
|
||||
|
||||
<Label alignment="BOTTOM_LEFT" text="Label" />
|
||||
<StatusBar text=""/>
|
||||
</children>
|
||||
</VBox>
|
||||
|
|
|
@ -3,20 +3,27 @@
|
|||
<?import javafx.scene.control.*?>
|
||||
<?import javafx.scene.layout.*?>
|
||||
<?import org.fxmisc.richtext.*?>
|
||||
|
||||
<?import org.fxmisc.flowless.VirtualizedScrollPane?>
|
||||
<SplitPane dividerPositions="0.82" orientation="VERTICAL" prefHeight="200.0" prefWidth="160.0" stylesheets="@transaction.css" VBox.vgrow="ALWAYS" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.sparrowwallet.sparrow.transaction.TransactionController">
|
||||
<?import org.controlsfx.control.MasterDetailPane?>
|
||||
|
||||
<SplitPane fx:id="tabContent" dividerPositions="0.82" orientation="VERTICAL" prefHeight="200.0" prefWidth="160.0" stylesheets="@transaction.css" VBox.vgrow="ALWAYS" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.sparrowwallet.sparrow.transaction.TransactionController">
|
||||
<items>
|
||||
<SplitPane dividerPositions="0.2" prefHeight="160.0" prefWidth="200.0">
|
||||
<items>
|
||||
<TreeView fx:id="txtree" prefHeight="154.0" prefWidth="174.0" />
|
||||
<Pane fx:id="txpane" />
|
||||
</items>
|
||||
</SplitPane>
|
||||
<VirtualizedScrollPane>
|
||||
<content>
|
||||
<CodeArea fx:id="txhex" editable="false" wrapText="true" />
|
||||
</content>
|
||||
</VirtualizedScrollPane>
|
||||
<MasterDetailPane fx:id="transactionMasterDetail" detailSide="BOTTOM">
|
||||
<masterNode>
|
||||
<SplitPane dividerPositions="0.2" prefHeight="160.0" prefWidth="200.0">
|
||||
<items>
|
||||
<TreeView fx:id="txtree" prefHeight="154.0" prefWidth="174.0" />
|
||||
<Pane fx:id="txpane" />
|
||||
</items>
|
||||
</SplitPane>
|
||||
</masterNode>
|
||||
<detailNode>
|
||||
<VirtualizedScrollPane>
|
||||
<content>
|
||||
<CodeArea fx:id="txhex" editable="false" wrapText="true" />
|
||||
</content>
|
||||
</VirtualizedScrollPane>
|
||||
</detailNode>
|
||||
</MasterDetailPane>
|
||||
</items>
|
||||
</SplitPane>
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 690 KiB |
Binary file not shown.
Before Width: | Height: | Size: 248 KiB |
Loading…
Reference in a new issue