mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2024-12-25 05:06:45 +00:00
finish perf improvements to tx viewer
This commit is contained in:
parent
82ca9552bd
commit
9cd8a9b9ee
10 changed files with 125 additions and 28 deletions
|
@ -2,6 +2,7 @@ package com.sparrowwallet.sparrow.control;
|
||||||
|
|
||||||
import com.sparrowwallet.drongo.Utils;
|
import com.sparrowwallet.drongo.Utils;
|
||||||
import com.sparrowwallet.drongo.protocol.*;
|
import com.sparrowwallet.drongo.protocol.*;
|
||||||
|
import javafx.application.Platform;
|
||||||
import org.fxmisc.richtext.CodeArea;
|
import org.fxmisc.richtext.CodeArea;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
|
@ -12,6 +13,7 @@ import java.util.Objects;
|
||||||
|
|
||||||
public class TransactionHexArea extends CodeArea {
|
public class TransactionHexArea extends CodeArea {
|
||||||
private static final int TRUNCATE_AT = 30000;
|
private static final int TRUNCATE_AT = 30000;
|
||||||
|
private static final int SEGMENTS_INTERVAL = 250;
|
||||||
|
|
||||||
private List<TransactionSegment> previousSegmentList = new ArrayList<>();
|
private List<TransactionSegment> previousSegmentList = new ArrayList<>();
|
||||||
|
|
||||||
|
@ -38,14 +40,24 @@ public class TransactionHexArea extends CodeArea {
|
||||||
List<TransactionSegment> segments = getTransactionSegments(transaction, selectedInputIndex, selectedOutputIndex);
|
List<TransactionSegment> segments = getTransactionSegments(transaction, selectedInputIndex, selectedOutputIndex);
|
||||||
List<TransactionSegment> changedSegments = new ArrayList<>(segments);
|
List<TransactionSegment> changedSegments = new ArrayList<>(segments);
|
||||||
changedSegments.removeAll(previousSegmentList);
|
changedSegments.removeAll(previousSegmentList);
|
||||||
|
applyHighlighting(0, changedSegments);
|
||||||
|
previousSegmentList = segments;
|
||||||
|
}
|
||||||
|
|
||||||
for(TransactionSegment segment : changedSegments) {
|
private void applyHighlighting(int start, List<TransactionSegment> segments) {
|
||||||
|
int end = Math.min(segments.size(), start + SEGMENTS_INTERVAL);
|
||||||
|
for(int i = start; i < end; i++) {
|
||||||
|
TransactionSegment segment = segments.get(i);
|
||||||
if(segment.start < TRUNCATE_AT) {
|
if(segment.start < TRUNCATE_AT) {
|
||||||
setStyleClass(segment.start, Math.min(TRUNCATE_AT, segment.start + segment.length), segment.style);
|
setStyleClass(segment.start, Math.min(TRUNCATE_AT, segment.start + segment.length), segment.style);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
previousSegmentList = segments;
|
if(end < segments.size()) {
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
applyHighlighting(end, segments);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<TransactionSegment> getTransactionSegments(Transaction transaction, int selectedInputIndex, int selectedOutputIndex) {
|
public List<TransactionSegment> getTransactionSegments(Transaction transaction, int selectedInputIndex, int selectedOutputIndex) {
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
package com.sparrowwallet.sparrow.event;
|
||||||
|
|
||||||
|
import com.sparrowwallet.drongo.protocol.Transaction;
|
||||||
|
|
||||||
|
public class TransactionLocktimeChangedEvent extends TransactionChangedEvent {
|
||||||
|
public TransactionLocktimeChangedEvent(Transaction transaction) {
|
||||||
|
super(transaction);
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,7 +10,7 @@ public class ViewTransactionEvent {
|
||||||
public final Integer initialIndex;
|
public final Integer initialIndex;
|
||||||
|
|
||||||
public ViewTransactionEvent(BlockTransaction blockTransaction) {
|
public ViewTransactionEvent(BlockTransaction blockTransaction) {
|
||||||
this(blockTransaction, null, null);
|
this(blockTransaction, TransactionView.HEADERS, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ViewTransactionEvent(BlockTransaction blockTransaction, HashIndexEntry hashIndexEntry) {
|
public ViewTransactionEvent(BlockTransaction blockTransaction, HashIndexEntry hashIndexEntry) {
|
||||||
|
|
|
@ -12,6 +12,7 @@ import com.sparrowwallet.sparrow.control.IdLabel;
|
||||||
import com.sparrowwallet.sparrow.control.CopyableLabel;
|
import com.sparrowwallet.sparrow.control.CopyableLabel;
|
||||||
import com.sparrowwallet.sparrow.event.BlockTransactionFetchedEvent;
|
import com.sparrowwallet.sparrow.event.BlockTransactionFetchedEvent;
|
||||||
import com.sparrowwallet.sparrow.event.TransactionChangedEvent;
|
import com.sparrowwallet.sparrow.event.TransactionChangedEvent;
|
||||||
|
import com.sparrowwallet.sparrow.event.TransactionLocktimeChangedEvent;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.fxml.Initializable;
|
import javafx.fxml.Initializable;
|
||||||
import javafx.scene.control.*;
|
import javafx.scene.control.*;
|
||||||
|
@ -199,6 +200,7 @@ public class HeadersController extends TransactionFormController implements Init
|
||||||
tx.setLocktime(newValue);
|
tx.setLocktime(newValue);
|
||||||
if(oldValue != null) {
|
if(oldValue != null) {
|
||||||
EventManager.get().post(new TransactionChangedEvent(tx));
|
EventManager.get().post(new TransactionChangedEvent(tx));
|
||||||
|
EventManager.get().post(new TransactionLocktimeChangedEvent(tx));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -249,9 +251,13 @@ public class HeadersController extends TransactionFormController implements Init
|
||||||
|
|
||||||
BlockTransaction inputTx = inputTransactions.get(input.getOutpoint().getHash());
|
BlockTransaction inputTx = inputTransactions.get(input.getOutpoint().getHash());
|
||||||
if(inputTx == null) {
|
if(inputTx == null) {
|
||||||
System.out.println("Cannot find transaction for hash " + input.getOutpoint().getHash() + ", still paging?");
|
if(headersForm.allInputsFetched()) {
|
||||||
|
throw new IllegalStateException("Cannot find transaction for hash " + input.getOutpoint().getHash());
|
||||||
|
} else {
|
||||||
|
//Still paging
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
feeAmt += inputTx.getTransaction().getOutputs().get((int)input.getOutpoint().getIndex()).getValue();
|
feeAmt += inputTx.getTransaction().getOutputs().get((int)input.getOutpoint().getIndex()).getValue();
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import com.sparrowwallet.sparrow.EventManager;
|
||||||
import com.sparrowwallet.sparrow.control.*;
|
import com.sparrowwallet.sparrow.control.*;
|
||||||
import com.sparrowwallet.sparrow.event.BlockTransactionFetchedEvent;
|
import com.sparrowwallet.sparrow.event.BlockTransactionFetchedEvent;
|
||||||
import com.sparrowwallet.sparrow.event.TransactionChangedEvent;
|
import com.sparrowwallet.sparrow.event.TransactionChangedEvent;
|
||||||
|
import com.sparrowwallet.sparrow.event.TransactionLocktimeChangedEvent;
|
||||||
import com.sparrowwallet.sparrow.event.ViewTransactionEvent;
|
import com.sparrowwallet.sparrow.event.ViewTransactionEvent;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.fxml.Initializable;
|
import javafx.fxml.Initializable;
|
||||||
|
@ -192,9 +193,13 @@ public class InputController extends TransactionFormController implements Initia
|
||||||
if(!txInput.isCoinBase()) {
|
if(!txInput.isCoinBase()) {
|
||||||
BlockTransaction blockTransaction = inputTransactions.get(txInput.getOutpoint().getHash());
|
BlockTransaction blockTransaction = inputTransactions.get(txInput.getOutpoint().getHash());
|
||||||
if(blockTransaction == null) {
|
if(blockTransaction == null) {
|
||||||
System.out.println("Could not retrieve block transaction for input #" + inputForm.getIndex());
|
if(inputForm.getIndex() < inputForm.getMaxInputFetched()) {
|
||||||
|
throw new IllegalStateException("Could not retrieve block transaction for input #" + inputForm.getIndex());
|
||||||
|
} else {
|
||||||
|
//Still paging
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TransactionOutput output = blockTransaction.getTransaction().getOutputs().get((int)txInput.getOutpoint().getIndex());
|
TransactionOutput output = blockTransaction.getTransaction().getOutputs().get((int)txInput.getOutpoint().getIndex());
|
||||||
updateSpends(output);
|
updateSpends(output);
|
||||||
|
@ -486,4 +491,11 @@ public class InputController extends TransactionFormController implements Initia
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void transctionLocktimeChanged(TransactionLocktimeChangedEvent event) {
|
||||||
|
if(event.getTransaction().equals(inputForm.getTransaction())) {
|
||||||
|
locktimeAbsolute.setText(Long.toString(event.getTransaction().getLocktime()));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,9 +125,13 @@ public class InputsController extends TransactionFormController implements Initi
|
||||||
} else {
|
} else {
|
||||||
BlockTransaction inputTx = inputTransactions.get(input.getOutpoint().getHash());
|
BlockTransaction inputTx = inputTransactions.get(input.getOutpoint().getHash());
|
||||||
if(inputTx == null) {
|
if(inputTx == null) {
|
||||||
System.out.println("Cannot find transaction for hash " + input.getOutpoint().getHash() + ", still paging?");
|
if(inputsForm.allInputsFetched()) {
|
||||||
|
throw new IllegalStateException("Cannot find transaction for hash " + input.getOutpoint().getHash());
|
||||||
|
} else {
|
||||||
|
//Still paging
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TransactionOutput output = inputTx.getTransaction().getOutputs().get((int)input.getOutpoint().getIndex());
|
TransactionOutput output = inputTx.getTransaction().getOutputs().get((int)input.getOutpoint().getIndex());
|
||||||
outputs.add(output);
|
outputs.add(output);
|
||||||
|
|
|
@ -90,7 +90,7 @@ public class TransactionController implements Initializable {
|
||||||
inputsItem.getChildren().add(inputItem);
|
inputsItem.getChildren().add(inputItem);
|
||||||
inputPagingAdded = false;
|
inputPagingAdded = false;
|
||||||
} else if(!inputPagingAdded) {
|
} else if(!inputPagingAdded) {
|
||||||
PageForm pageForm = new PageForm(TransactionView.INPUT, i, i + PageForm.PAGE_SIZE);
|
PageForm pageForm = new PageForm(TransactionView.INPUT, i, Math.min(getTransaction().getInputs().size(), i + PageForm.PAGE_SIZE));
|
||||||
TreeItem<TransactionForm> pageItem = new TreeItem<>(pageForm);
|
TreeItem<TransactionForm> pageItem = new TreeItem<>(pageForm);
|
||||||
inputsItem.getChildren().add(pageItem);
|
inputsItem.getChildren().add(pageItem);
|
||||||
inputPagingAdded = true;
|
inputPagingAdded = true;
|
||||||
|
@ -110,7 +110,7 @@ public class TransactionController implements Initializable {
|
||||||
outputsItem.getChildren().add(outputItem);
|
outputsItem.getChildren().add(outputItem);
|
||||||
outputPagingAdded = false;
|
outputPagingAdded = false;
|
||||||
} else if(!outputPagingAdded) {
|
} else if(!outputPagingAdded) {
|
||||||
PageForm pageForm = new PageForm(TransactionView.OUTPUT, i, i + PageForm.PAGE_SIZE);
|
PageForm pageForm = new PageForm(TransactionView.OUTPUT, i, Math.min(getTransaction().getOutputs().size(), i + PageForm.PAGE_SIZE));
|
||||||
TreeItem<TransactionForm> pageItem = new TreeItem<>(pageForm);
|
TreeItem<TransactionForm> pageItem = new TreeItem<>(pageForm);
|
||||||
outputsItem.getChildren().add(pageItem);
|
outputsItem.getChildren().add(pageItem);
|
||||||
outputPagingAdded = true;
|
outputPagingAdded = true;
|
||||||
|
@ -169,7 +169,7 @@ public class TransactionController implements Initializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(pageForm.getPageEnd() < max) {
|
if(pageForm.getPageEnd() < max) {
|
||||||
PageForm nextPageForm = new PageForm(pageForm.getView(), pageForm.getPageStart() + PageForm.PAGE_SIZE, pageForm.getPageEnd() + PageForm.PAGE_SIZE);
|
PageForm nextPageForm = new PageForm(pageForm.getView(), pageForm.getPageEnd(), Math.min(max, pageForm.getPageEnd() + PageForm.PAGE_SIZE));
|
||||||
TreeItem<TransactionForm> nextPageItem = new TreeItem<>(nextPageForm);
|
TreeItem<TransactionForm> nextPageItem = new TreeItem<>(nextPageForm);
|
||||||
if(pageForm.getPageEnd() >= parentItem.getChildren().size()) {
|
if(pageForm.getPageEnd() >= parentItem.getChildren().size()) {
|
||||||
parentItem.getChildren().add(nextPageItem);
|
parentItem.getChildren().add(nextPageItem);
|
||||||
|
@ -397,16 +397,16 @@ public class TransactionController implements Initializable {
|
||||||
setTreeSelection(event.getInitialView(), event.getInitialIndex());
|
setTreeSelection(event.getInitialView(), event.getInitialIndex());
|
||||||
} else if(event.getInitialView().equals(TransactionView.INPUT) || event.getInitialView().equals(TransactionView.OUTPUT)) {
|
} else if(event.getInitialView().equals(TransactionView.INPUT) || event.getInitialView().equals(TransactionView.OUTPUT)) {
|
||||||
TreeItem<TransactionForm> parentItem = getTreeItem(event.getInitialView().equals(TransactionView.INPUT) ? TransactionView.INPUTS : TransactionView.OUTPUTS, null);
|
TreeItem<TransactionForm> parentItem = getTreeItem(event.getInitialView().equals(TransactionView.INPUT) ? TransactionView.INPUTS : TransactionView.OUTPUTS, null);
|
||||||
|
|
||||||
TreeItem<TransactionForm> newItem = event.getInitialView().equals(TransactionView.INPUT) ? createInputTreeItem(event.getInitialIndex()) : createOutputTreeItem(event.getInitialIndex());
|
TreeItem<TransactionForm> newItem = event.getInitialView().equals(TransactionView.INPUT) ? createInputTreeItem(event.getInitialIndex()) : createOutputTreeItem(event.getInitialIndex());
|
||||||
PageForm nextPageForm = new PageForm(event.getInitialView(), event.getInitialIndex() + 1, event.getInitialIndex() + 1 + PageForm.PAGE_SIZE);
|
|
||||||
|
int max = event.getInitialView().equals(TransactionView.INPUT) ? getTransaction().getInputs().size() : getTransaction().getOutputs().size();
|
||||||
|
PageForm nextPageForm = new PageForm(event.getInitialView(), event.getInitialIndex() + 1, Math.min(max, event.getInitialIndex() + 1 + PageForm.PAGE_SIZE));
|
||||||
TreeItem<TransactionForm> nextPageItem = new TreeItem<>(nextPageForm);
|
TreeItem<TransactionForm> nextPageItem = new TreeItem<>(nextPageForm);
|
||||||
|
|
||||||
if(existingItem != null) {
|
if(existingItem != null) {
|
||||||
parentItem.getChildren().remove(existingItem);
|
parentItem.getChildren().remove(existingItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
int max = event.getInitialView().equals(TransactionView.INPUT) ? getTransaction().getInputs().size() : getTransaction().getOutputs().size();
|
|
||||||
int highestIndex = ((IndexedTransactionForm)parentItem.getChildren().get(parentItem.getChildren().size() - 1).getValue()).getIndex();
|
int highestIndex = ((IndexedTransactionForm)parentItem.getChildren().get(parentItem.getChildren().size() - 1).getValue()).getIndex();
|
||||||
if(event.getInitialIndex() < highestIndex) {
|
if(event.getInitialIndex() < highestIndex) {
|
||||||
for(int i = 0; i < parentItem.getChildren().size(); i++) {
|
for(int i = 0; i < parentItem.getChildren().size(); i++) {
|
||||||
|
@ -466,6 +466,7 @@ public class TransactionController implements Initializable {
|
||||||
} else {
|
} else {
|
||||||
txdata.getInputTransactions().putAll(event.getInputTransactions());
|
txdata.getInputTransactions().putAll(event.getInputTransactions());
|
||||||
}
|
}
|
||||||
|
txdata.updateInputsFetchedRange(event.getPageStart(), event.getPageEnd());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -482,6 +483,7 @@ public class TransactionController implements Initializable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
txdata.updateOutputsFetchedRange(event.getPageStart(), event.getPageEnd());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -15,6 +15,11 @@ public class TransactionData {
|
||||||
private Map<Sha256Hash, BlockTransaction> inputTransactions;
|
private Map<Sha256Hash, BlockTransaction> inputTransactions;
|
||||||
private List<BlockTransaction> outputTransactions;
|
private List<BlockTransaction> outputTransactions;
|
||||||
|
|
||||||
|
private int minInputFetched;
|
||||||
|
private int maxInputFetched;
|
||||||
|
private int minOutputFetched;
|
||||||
|
private int maxOutputFetched;
|
||||||
|
|
||||||
public TransactionData(PSBT psbt) {
|
public TransactionData(PSBT psbt) {
|
||||||
this.transaction = psbt.getTransaction();
|
this.transaction = psbt.getTransaction();
|
||||||
this.psbt = psbt;
|
this.psbt = psbt;
|
||||||
|
@ -53,6 +58,28 @@ public class TransactionData {
|
||||||
this.inputTransactions = inputTransactions;
|
this.inputTransactions = inputTransactions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void updateInputsFetchedRange(int pageStart, int pageEnd) {
|
||||||
|
if(pageStart < 0 || pageEnd > transaction.getInputs().size()) {
|
||||||
|
throw new IllegalStateException("Paging outside transaction inputs range");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pageStart != maxInputFetched) {
|
||||||
|
//non contiguous range, ignore
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.minInputFetched = Math.min(minInputFetched, pageStart);
|
||||||
|
this.maxInputFetched = Math.max(maxInputFetched, pageEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxInputFetched() {
|
||||||
|
return maxInputFetched;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean allInputsFetched() {
|
||||||
|
return minInputFetched == 0 && maxInputFetched == transaction.getOutputs().size();
|
||||||
|
}
|
||||||
|
|
||||||
public List<BlockTransaction> getOutputTransactions() {
|
public List<BlockTransaction> getOutputTransactions() {
|
||||||
return outputTransactions;
|
return outputTransactions;
|
||||||
}
|
}
|
||||||
|
@ -60,4 +87,22 @@ public class TransactionData {
|
||||||
public void setOutputTransactions(List<BlockTransaction> outputTransactions) {
|
public void setOutputTransactions(List<BlockTransaction> outputTransactions) {
|
||||||
this.outputTransactions = outputTransactions;
|
this.outputTransactions = outputTransactions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void updateOutputsFetchedRange(int pageStart, int pageEnd) {
|
||||||
|
if(pageStart < 0 || pageEnd > transaction.getOutputs().size()) {
|
||||||
|
throw new IllegalStateException("Paging outside transaction outputs range");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pageStart != maxOutputFetched) {
|
||||||
|
//non contiguous range, ignore
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.minOutputFetched = Math.min(minOutputFetched, pageStart);
|
||||||
|
this.maxOutputFetched = Math.max(maxOutputFetched, pageEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean allOutputsFetched() {
|
||||||
|
return minOutputFetched == 0 && maxOutputFetched == transaction.getOutputs().size();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,24 +29,24 @@ public abstract class TransactionForm {
|
||||||
return txdata.getBlockTransaction();
|
return txdata.getBlockTransaction();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBlockTransaction(BlockTransaction blockTransaction) {
|
|
||||||
txdata.setBlockTransaction(blockTransaction);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<Sha256Hash, BlockTransaction> getInputTransactions() {
|
public Map<Sha256Hash, BlockTransaction> getInputTransactions() {
|
||||||
return txdata.getInputTransactions();
|
return txdata.getInputTransactions();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setInputTransactions(Map<Sha256Hash, BlockTransaction> inputTransactions) {
|
public int getMaxInputFetched() {
|
||||||
txdata.setInputTransactions(inputTransactions);
|
return txdata.getMaxInputFetched();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean allInputsFetched() {
|
||||||
|
return txdata.allInputsFetched();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<BlockTransaction> getOutputTransactions() {
|
public List<BlockTransaction> getOutputTransactions() {
|
||||||
return txdata.getOutputTransactions();
|
return txdata.getOutputTransactions();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOutputTransactions(List<BlockTransaction> outputTransactions) {
|
public boolean allOutputsFetched() {
|
||||||
txdata.setOutputTransactions(outputTransactions);
|
return txdata.allOutputsFetched();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEditable() {
|
public boolean isEditable() {
|
||||||
|
|
|
@ -16,18 +16,21 @@ import javafx.scene.input.ClipboardContent;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public abstract class TransactionFormController extends BaseController {
|
public abstract class TransactionFormController extends BaseController {
|
||||||
|
private static final int MAX_PIE_SEGMENTS = 200;
|
||||||
|
|
||||||
protected void addPieData(PieChart pie, List<TransactionOutput> outputs) {
|
protected void addPieData(PieChart pie, List<TransactionOutput> outputs) {
|
||||||
ObservableList<PieChart.Data> outputsPieData = FXCollections.observableArrayList();
|
ObservableList<PieChart.Data> outputsPieData = FXCollections.observableArrayList();
|
||||||
|
|
||||||
long totalAmt = 0;
|
long totalAmt = 0;
|
||||||
for(TransactionOutput output : outputs) {
|
for(int i = 0; i < outputs.size(); i++) {
|
||||||
String name = "Unknown";
|
TransactionOutput output = outputs.get(i);
|
||||||
|
String name = "#" + i;
|
||||||
try {
|
try {
|
||||||
Address[] addresses = output.getScript().getToAddresses();
|
Address[] addresses = output.getScript().getToAddresses();
|
||||||
if(addresses.length == 1) {
|
if(addresses.length == 1) {
|
||||||
name = addresses[0].getAddress();
|
name = name + " " + addresses[0].getAddress();
|
||||||
} else {
|
} else {
|
||||||
name = "[" + addresses[0].getAddress() + ",...]";
|
name = name + " [" + addresses[0].getAddress() + ",...]";
|
||||||
}
|
}
|
||||||
} catch(NonStandardScriptException e) {
|
} catch(NonStandardScriptException e) {
|
||||||
//ignore
|
//ignore
|
||||||
|
@ -46,12 +49,16 @@ public abstract class TransactionFormController extends BaseController {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addPieData(PieChart pie, ObservableList<PieChart.Data> outputsPieData) {
|
private void addPieData(PieChart pie, ObservableList<PieChart.Data> outputsPieData) {
|
||||||
|
if(outputsPieData.size() > MAX_PIE_SEGMENTS) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
pie.setData(outputsPieData);
|
pie.setData(outputsPieData);
|
||||||
final double totalSum = outputsPieData.stream().map(PieChart.Data::getPieValue).mapToDouble(Double::doubleValue).sum();
|
final double totalSum = outputsPieData.stream().map(PieChart.Data::getPieValue).mapToDouble(Double::doubleValue).sum();
|
||||||
pie.getData().forEach(data -> {
|
pie.getData().forEach(data -> {
|
||||||
Tooltip tooltip = new Tooltip();
|
Tooltip tooltip = new Tooltip();
|
||||||
double percent = 100.0 * (data.getPieValue() / totalSum);
|
double percent = 100.0 * (data.getPieValue() / totalSum);
|
||||||
tooltip.setText(String.format("%.1f", percent) + "%");
|
tooltip.setText(data.getName() + " " + String.format("%.1f", percent) + "%");
|
||||||
Tooltip.install(data.getNode(), tooltip);
|
Tooltip.install(data.getNode(), tooltip);
|
||||||
data.pieValueProperty().addListener((observable, oldValue, newValue) -> tooltip.setText(newValue + "%"));
|
data.pieValueProperty().addListener((observable, oldValue, newValue) -> tooltip.setText(newValue + "%"));
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue