From d8c94504c3ce606575e8011731a61c5d25b36ea8 Mon Sep 17 00:00:00 2001 From: Craig Raw Date: Sun, 28 Jun 2020 15:46:52 +0200 Subject: [PATCH] utxo chart rewrite --- .../sparrow/control/UtxosChart.java | 80 +++++++++++++++++++ .../sparrow/control/UtxosTreeTable.java | 10 +-- .../sparrow/wallet/UtxosController.java | 74 +++-------------- .../sparrowwallet/sparrow/wallet/utxos.css | 4 + .../sparrowwallet/sparrow/wallet/utxos.fxml | 6 +- 5 files changed, 102 insertions(+), 72 deletions(-) create mode 100644 src/main/java/com/sparrowwallet/sparrow/control/UtxosChart.java diff --git a/src/main/java/com/sparrowwallet/sparrow/control/UtxosChart.java b/src/main/java/com/sparrowwallet/sparrow/control/UtxosChart.java new file mode 100644 index 00000000..30492d5f --- /dev/null +++ b/src/main/java/com/sparrowwallet/sparrow/control/UtxosChart.java @@ -0,0 +1,80 @@ +package com.sparrowwallet.sparrow.control; + +import com.sparrowwallet.sparrow.wallet.Entry; +import com.sparrowwallet.sparrow.wallet.UtxoEntry; +import com.sparrowwallet.sparrow.wallet.WalletUtxosEntry; +import javafx.beans.NamedArg; +import javafx.scene.Node; +import javafx.scene.chart.Axis; +import javafx.scene.chart.BarChart; +import javafx.scene.chart.XYChart; + +import java.util.List; +import java.util.stream.Collectors; + +public class UtxosChart extends BarChart { + private static final int MAX_BARS = 8; + private static final String OTHER_CATEGORY = "Other"; + + private Entry selectedEntry; + + private XYChart.Series utxoSeries; + + public UtxosChart(@NamedArg("xAxis") Axis xAxis, @NamedArg("yAxis") Axis yAxis) { + super(xAxis, yAxis); + } + + public void initialize(WalletUtxosEntry walletUtxosEntry) { + utxoSeries = new XYChart.Series<>(); + getData().add(utxoSeries); + update(walletUtxosEntry); + } + + public void update(WalletUtxosEntry walletUtxosEntry) { + List> utxoDataList = walletUtxosEntry.getChildren().stream() + .map(entry -> new XYChart.Data<>(entry.getLabel() != null && !entry.getLabel().isEmpty() ? entry.getLabel() : ((UtxoEntry)entry).getDescription(), (Number)entry.getValue(), entry)) + .sorted((o1, o2) -> (int) (o2.getYValue().longValue() - o1.getYValue().longValue())) + .collect(Collectors.toList()); + + if(utxoDataList.size() > MAX_BARS) { + Long otherTotal = utxoDataList.subList(MAX_BARS - 1, utxoDataList.size()).stream().mapToLong(data -> data.getYValue().longValue()).sum(); + utxoDataList = utxoDataList.subList(0, MAX_BARS - 1); + utxoDataList.add(new XYChart.Data<>(OTHER_CATEGORY, otherTotal)); + } + + for(int i = 0; i < utxoDataList.size(); i++) { + XYChart.Data newData = utxoDataList.get(i); + if(i < utxoSeries.getData().size()) { + XYChart.Data existingData = utxoSeries.getData().get(i); + if(!newData.getXValue().equals(existingData.getXValue()) || !newData.getYValue().equals(existingData.getYValue()) || (newData.getExtraValue() != null && !newData.getExtraValue().equals(existingData.getExtraValue()))) { + utxoSeries.getData().set(i, newData); + } + } else { + utxoSeries.getData().add(newData); + } + } + + if(utxoSeries.getData().size() > utxoDataList.size()) { + utxoSeries.getData().remove(utxoDataList.size() - 1, utxoSeries.getData().size()); + } + + if(selectedEntry != null) { + select(selectedEntry); + } + } + + public void select(Entry entry) { + for(int i = 0; i < utxoSeries.getData().size(); i++) { + XYChart.Data data = utxoSeries.getData().get(i); + Node bar = lookup(".data" + i); + if(bar != null) { + if(data.getExtraValue() != null && data.getExtraValue().equals(entry)) { + bar.getStyleClass().add("selected"); + this.selectedEntry = entry; + } else { + bar.getStyleClass().remove("selected"); + } + } + } + } +} diff --git a/src/main/java/com/sparrowwallet/sparrow/control/UtxosTreeTable.java b/src/main/java/com/sparrowwallet/sparrow/control/UtxosTreeTable.java index 04c33245..a21aaaa2 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/UtxosTreeTable.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/UtxosTreeTable.java @@ -70,8 +70,8 @@ public class UtxosTreeTable extends TreeTableView { setPlaceholder(new Label("No unspent outputs")); setEditable(true); setColumnResizePolicy(TreeTableView.CONSTRAINED_RESIZE_POLICY); - dateCol.setSortType(TreeTableColumn.SortType.DESCENDING); - getSortOrder().add(dateCol); + amountCol.setSortType(TreeTableColumn.SortType.DESCENDING); + getSortOrder().add(amountCol); } public void updateAll(WalletUtxosEntry rootEntry) { @@ -80,9 +80,9 @@ public class UtxosTreeTable extends TreeTableView { rootItem.setExpanded(true); if(getColumns().size() > 0 && getSortOrder().isEmpty()) { - TreeTableColumn dateCol = getColumns().get(0); - getSortOrder().add(dateCol); - dateCol.setSortType(TreeTableColumn.SortType.DESCENDING); + TreeTableColumn amountCol = getColumns().get(getColumns().size() - 1); + getSortOrder().add(amountCol); + amountCol.setSortType(TreeTableColumn.SortType.DESCENDING); } } diff --git a/src/main/java/com/sparrowwallet/sparrow/wallet/UtxosController.java b/src/main/java/com/sparrowwallet/sparrow/wallet/UtxosController.java index 6cefb47e..80a3e383 100644 --- a/src/main/java/com/sparrowwallet/sparrow/wallet/UtxosController.java +++ b/src/main/java/com/sparrowwallet/sparrow/wallet/UtxosController.java @@ -2,21 +2,16 @@ package com.sparrowwallet.sparrow.wallet; import com.google.common.eventbus.Subscribe; import com.sparrowwallet.sparrow.EventManager; +import com.sparrowwallet.sparrow.control.UtxosChart; import com.sparrowwallet.sparrow.control.UtxosTreeTable; import com.sparrowwallet.sparrow.event.WalletEntryLabelChangedEvent; import com.sparrowwallet.sparrow.event.WalletHistoryChangedEvent; import com.sparrowwallet.sparrow.event.WalletNodesChangedEvent; -import javafx.collections.ListChangeListener; import javafx.fxml.FXML; import javafx.fxml.Initializable; -import javafx.scene.chart.BarChart; -import javafx.scene.chart.XYChart; import java.net.URL; -import java.util.List; -import java.util.Optional; import java.util.ResourceBundle; -import java.util.stream.Collectors; public class UtxosController extends WalletFormController implements Initializable { @@ -24,7 +19,7 @@ public class UtxosController extends WalletFormController implements Initializab private UtxosTreeTable utxosTable; @FXML - private BarChart utxosChart; + private UtxosChart utxosChart; @Override public void initialize(URL location, ResourceBundle resources) { @@ -34,52 +29,11 @@ public class UtxosController extends WalletFormController implements Initializab @Override public void initializeView() { utxosTable.initialize(getWalletForm().getWalletUtxosEntry()); - initializeChart(getWalletForm().getWalletUtxosEntry()); - } + utxosChart.initialize(getWalletForm().getWalletUtxosEntry()); - private void initializeChart(WalletUtxosEntry walletUtxosEntry) { - XYChart.Series utxoSeries = new XYChart.Series<>(); - - List> utxoDataList = walletUtxosEntry.getChildren().stream() - .map(UtxoData::new) - .map(data -> new XYChart.Data<>(data.name, data.value, data.entry)) - .collect(Collectors.toList()); - utxoSeries.getData().addAll(utxoDataList); - walletUtxosEntry.getChildren().forEach(entry -> entry.labelProperty().addListener((observable, oldValue, newValue) -> { - Optional> optData = utxoSeries.getData().stream().filter(data -> data.getExtraValue().equals(entry)).findFirst(); - if(optData.isPresent()) { - int index = utxoSeries.getData().indexOf(optData.get()); - utxoSeries.getData().set(index, new XYChart.Data<>(newValue, optData.get().getYValue(), optData.get().getExtraValue())); - } - })); - utxoSeries.getData().sort((o1, o2) -> (int) (o2.getYValue().longValue() - o1.getYValue().longValue())); - - utxosChart.getData().clear(); - utxosChart.getData().add(utxoSeries); - - walletUtxosEntry.getChildren().addListener((ListChangeListener) change -> { - while(change.next()) { - if(change.wasAdded()) { - List> addedList = change.getAddedSubList().stream().map(UtxoData::new).map(data -> new XYChart.Data<>(data.name, data.value, data.entry)).collect(Collectors.toList()); - utxoSeries.getData().addAll(addedList); - utxoSeries.getData().sort((o1, o2) -> (int) (o2.getYValue().longValue() - o1.getYValue().longValue())); - change.getAddedSubList().forEach(entry -> entry.labelProperty().addListener((observable, oldValue, newValue) -> { - Optional> optData = utxoSeries.getData().stream().filter(data -> data.getExtraValue().equals(entry)).findFirst(); - if(optData.isPresent()) { - int index = utxoSeries.getData().indexOf(optData.get()); - utxoSeries.getData().set(index, new XYChart.Data<>(newValue, optData.get().getYValue(), optData.get().getExtraValue())); - } - })); - } - - if(change.wasRemoved()) { - change.getRemoved().forEach(entry -> { - UtxoData utxoData = new UtxoData(entry); - Optional> optRemovedData = utxoSeries.getData().stream().filter(data -> data.getExtraValue().equals(utxoData.entry)).findFirst(); - optRemovedData.ifPresent(removedData -> utxoSeries.getData().remove(removedData)); - }); - } - } + utxosTable.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> { + Entry entry = newValue.getValue(); + utxosChart.select(entry); }); } @@ -87,7 +41,7 @@ public class UtxosController extends WalletFormController implements Initializab public void walletNodesChanged(WalletNodesChangedEvent event) { if(event.getWallet().equals(walletForm.getWallet())) { utxosTable.updateAll(getWalletForm().getWalletUtxosEntry()); - initializeChart(getWalletForm().getWalletUtxosEntry()); + utxosChart.update(getWalletForm().getWalletUtxosEntry()); } } @@ -95,6 +49,7 @@ public class UtxosController extends WalletFormController implements Initializab public void walletHistoryChanged(WalletHistoryChangedEvent event) { if(event.getWallet().equals(walletForm.getWallet())) { utxosTable.updateHistory(event.getHistoryChangedNodes()); + utxosChart.update(getWalletForm().getWalletUtxosEntry()); } } @@ -102,18 +57,7 @@ public class UtxosController extends WalletFormController implements Initializab public void walletEntryLabelChanged(WalletEntryLabelChangedEvent event) { if(event.getWallet().equals(walletForm.getWallet())) { utxosTable.updateLabel(event.getEntry()); - } - } - - private static class UtxoData { - public final Entry entry; - public final String name; - public final Number value; - - public UtxoData(Entry entry) { - this.entry = entry; - this.name = entry.getLabel() != null && !entry.getLabel().isEmpty() ? entry.getLabel() : ((UtxoEntry)entry).getDescription(); - this.value = entry.getValue(); + utxosChart.update(getWalletForm().getWalletUtxosEntry()); } } } diff --git a/src/main/resources/com/sparrowwallet/sparrow/wallet/utxos.css b/src/main/resources/com/sparrowwallet/sparrow/wallet/utxos.css index f7afc201..772919fa 100644 --- a/src/main/resources/com/sparrowwallet/sparrow/wallet/utxos.css +++ b/src/main/resources/com/sparrowwallet/sparrow/wallet/utxos.css @@ -6,4 +6,8 @@ .chart-bar { -fx-bar-fill: rgba(105, 108, 119, 0.6); +} + +.chart-bar.selected { + -fx-bar-fill: rgba(30, 136, 207, 0.6); } \ No newline at end of file diff --git a/src/main/resources/com/sparrowwallet/sparrow/wallet/utxos.fxml b/src/main/resources/com/sparrowwallet/sparrow/wallet/utxos.fxml index 954da1de..dd4367cc 100644 --- a/src/main/resources/com/sparrowwallet/sparrow/wallet/utxos.fxml +++ b/src/main/resources/com/sparrowwallet/sparrow/wallet/utxos.fxml @@ -11,6 +11,8 @@ + + @@ -32,14 +34,14 @@
- + - +