update utxo tab ui to show utxo balance and count next to smaller utxo chart

This commit is contained in:
Craig Raw 2021-12-07 13:29:03 +02:00
parent 1b61a78e6d
commit 3c94664ac3
8 changed files with 112 additions and 66 deletions

View file

@ -144,10 +144,6 @@ public class AppController implements Initializable {
private CheckMenuItem showLoadingLog;
private static final BooleanProperty showLoadingLogProperty = new SimpleBooleanProperty();
@FXML
private CheckMenuItem showUtxosChart;
private static final BooleanProperty showUtxosChartProperty = new SimpleBooleanProperty();
@FXML
private CheckMenuItem showTxHex;
private static final BooleanProperty showTxHexProperty = new SimpleBooleanProperty();
@ -320,8 +316,6 @@ public class AppController implements Initializable {
showTxHex.selectedProperty().bindBidirectional(showTxHexProperty);
showLoadingLogProperty.set(Config.get().isShowLoadingLog());
showLoadingLog.selectedProperty().bindBidirectional(showLoadingLogProperty);
showUtxosChartProperty.set(Config.get().isShowUtxosChart());
showUtxosChart.selectedProperty().bindBidirectional(showUtxosChartProperty);
preventSleepProperty.set(Config.get().isPreventSleep());
preventSleep.selectedProperty().bindBidirectional(preventSleepProperty);
@ -802,12 +796,6 @@ public class AppController implements Initializable {
EventManager.get().post(new LoadingLogChangedEvent(item.isSelected()));
}
public void showUtxosChart(ActionEvent event) {
CheckMenuItem item = (CheckMenuItem)event.getSource();
Config.get().setShowUtxosChart(item.isSelected());
EventManager.get().post(new UtxosChartChangedEvent(item.isSelected()));
}
public void showTxHex(ActionEvent event) {
CheckMenuItem item = (CheckMenuItem)event.getSource();
Config.get().setShowTransactionHex(item.isSelected());
@ -1869,7 +1857,6 @@ public class AppController implements Initializable {
lockWallet.setDisable(true);
exportWallet.setDisable(true);
showLoadingLog.setDisable(true);
showUtxosChart.setDisable(true);
showTxHex.setDisable(false);
findMixingPartner.setDisable(true);
} else if(event instanceof WalletTabSelectedEvent) {
@ -1880,7 +1867,6 @@ public class AppController implements Initializable {
lockWallet.setDisable(walletTabData.getWalletForm().lockedProperty().get());
exportWallet.setDisable(walletTabData.getWallet() == null || !walletTabData.getWallet().isValid());
showLoadingLog.setDisable(false);
showUtxosChart.setDisable(false);
showTxHex.setDisable(true);
findMixingPartner.setDisable(exportWallet.isDisable() || !SorobanServices.canWalletMix(walletTabData.getWallet()) || !AppServices.onlineProperty().get());
}

View file

@ -9,14 +9,18 @@ import com.sparrowwallet.sparrow.wallet.WalletUtxosEntry;
import javafx.beans.NamedArg;
import javafx.scene.Node;
import javafx.scene.chart.*;
import javafx.scene.control.Tooltip;
import javafx.util.Duration;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.stream.Collectors;
public class UtxosChart extends BarChart<String, Number> {
private static final int MAX_BARS = 8;
private static final String OTHER_CATEGORY = "Other";
private static final int TOOLTIP_SHOW_DELAY = 50;
private List<Entry> selectedEntries;
private int totalUtxos;
@ -57,9 +61,11 @@ public class UtxosChart extends BarChart<String, Number> {
XYChart.Data<String, Number> existingData = utxoSeries.getData().get(i);
if(!newData.getXValue().equals(existingData.getXValue()) || !newData.getYValue().equals(existingData.getYValue()) || (newData.getExtraValue() instanceof Entry && !newData.getExtraValue().equals(existingData.getExtraValue()))) {
utxoSeries.getData().set(i, newData);
installTooltip(newData);
}
} else {
utxoSeries.getData().add(newData);
installTooltip(newData);
}
}
@ -74,12 +80,21 @@ public class UtxosChart extends BarChart<String, Number> {
private String getCategoryName(Entry entry) {
if(entry.getLabel() != null && !entry.getLabel().isEmpty()) {
return entry.getLabel().length() > 15 ? entry.getLabel().substring(0, 15) + "..." + "\n" + ((UtxoEntry)entry).getDescription() : entry.getLabel() + "\n" + ((UtxoEntry)entry).getDescription();
return entry.getLabel() + "\n" + ((UtxoEntry)entry).getDescription();
}
return ((UtxoEntry)entry).getDescription();
}
private void installTooltip(XYChart.Data<String, Number> item) {
Tooltip.uninstall(item.getNode(), null);
String satsValue = String.format(Locale.ENGLISH, "%,d", item.getYValue());
Tooltip tooltip = new Tooltip(item.getXValue() + "\n" + satsValue + " sats");
tooltip.setShowDelay(Duration.millis(TOOLTIP_SHOW_DELAY));
Tooltip.install(item.getNode(), tooltip);
}
public void select(List<Entry> entries) {
Set<Node> selectedBars = lookupAll(".chart-bar.selected");
for(Node selectedBar : selectedBars) {

View file

@ -40,7 +40,6 @@ public class Config {
private boolean hideEmptyUsedAddresses = false;
private boolean showTransactionHex = true;
private boolean showLoadingLog = true;
private boolean showUtxosChart = true;
private boolean preventSleep = false;
private List<File> recentWalletFiles;
private Integer keyDerivationPeriod;
@ -273,15 +272,6 @@ public class Config {
flush();
}
public boolean isShowUtxosChart() {
return showUtxosChart;
}
public void setShowUtxosChart(boolean showUtxosChart) {
this.showUtxosChart = showUtxosChart;
flush();
}
public boolean isPreventSleep() {
return preventSleep;
}
@ -388,7 +378,9 @@ public class Config {
public void changePublicServer() {
List<String> otherServers = PublicElectrumServer.getServers().stream().map(PublicElectrumServer::getUrl).filter(url -> !url.equals(getPublicElectrumServer())).collect(Collectors.toList());
setPublicElectrumServer(otherServers.get(new Random().nextInt(otherServers.size())));
if(!otherServers.isEmpty()) {
setPublicElectrumServer(otherServers.get(new Random().nextInt(otherServers.size())));
}
}
public String getCoreServer() {

View file

@ -106,15 +106,6 @@ public class TransactionsController extends WalletFormController implements Init
loadingLog.setEditable(false);
}
private void setFiatBalance(FiatLabel fiatLabel, CurrencyRate currencyRate, long balance) {
if(currencyRate != null && currencyRate.isAvailable() && balance > 0) {
fiatLabel.set(currencyRate, balance);
} else {
fiatLabel.setCurrency(null);
fiatLabel.setBtcRate(0.0);
}
}
private void setTransactionCount(WalletTransactionsEntry walletTransactionsEntry) {
transactionCount.setText(walletTransactionsEntry.getChildren() != null ? Integer.toString(walletTransactionsEntry.getChildren().size()) : "0");
}

View file

@ -52,6 +52,21 @@ import static com.sparrowwallet.sparrow.AppServices.showErrorDialog;
public class UtxosController extends WalletFormController implements Initializable {
private static final Logger log = LoggerFactory.getLogger(UtxosController.class);
@FXML
private CoinLabel balance;
@FXML
private FiatLabel fiatBalance;
@FXML
private CoinLabel mempoolBalance;
@FXML
private FiatLabel fiatMempoolBalance;
@FXML
private CopyableLabel utxoCount;
@FXML
private UtxosTreeTable utxosTable;
@ -115,8 +130,17 @@ public class UtxosController extends WalletFormController implements Initializab
@Override
public void initializeView() {
utxosTable.initialize(getWalletForm().getWalletUtxosEntry());
utxosChart.initialize(getWalletForm().getWalletUtxosEntry());
balance.valueProperty().addListener((observable, oldValue, newValue) -> {
setFiatBalance(fiatBalance, AppServices.getFiatCurrencyExchangeRate(), newValue.longValue());
});
mempoolBalance.valueProperty().addListener((observable, oldValue, newValue) -> {
setFiatBalance(fiatMempoolBalance, AppServices.getFiatCurrencyExchangeRate(), newValue.longValue());
});
WalletUtxosEntry walletUtxosEntry = getWalletForm().getWalletUtxosEntry();
updateFields(walletUtxosEntry);
utxosTable.initialize(walletUtxosEntry);
utxosChart.initialize(walletUtxosEntry);
mixButtonsBox.managedProperty().bind(mixButtonsBox.visibleProperty());
mixButtonsBox.setVisible(getWalletForm().getWallet().isWhirlpoolMixWallet());
@ -159,9 +183,12 @@ public class UtxosController extends WalletFormController implements Initializab
utxosChart.select(selectedEntries);
updateButtons(Config.get().getBitcoinUnit());
});
}
utxosChart.managedProperty().bind(utxosChart.visibleProperty());
utxosChart.setVisible(Config.get().isShowUtxosChart() && !getWalletForm().getWallet().isWhirlpoolMixWallet());
private void updateFields(WalletUtxosEntry walletUtxosEntry) {
balance.setValue(walletUtxosEntry.getChildren().stream().mapToLong(Entry::getValue).sum());
mempoolBalance.setValue(walletUtxosEntry.getChildren().stream().filter(entry -> ((UtxoEntry)entry).getHashIndex().getHeight() <= 0).mapToLong(Entry::getValue).sum());
utxoCount.setText(walletUtxosEntry.getChildren() != null ? Integer.toString(walletUtxosEntry.getChildren().size()) : "0");
}
private boolean canWalletMix() {
@ -458,6 +485,7 @@ public class UtxosController extends WalletFormController implements Initializab
public void walletNodesChanged(WalletNodesChangedEvent event) {
if(event.getWallet().equals(walletForm.getWallet())) {
WalletUtxosEntry walletUtxosEntry = getWalletForm().getWalletUtxosEntry();
updateFields(walletUtxosEntry);
utxosTable.updateAll(walletUtxosEntry);
utxosChart.update(walletUtxosEntry);
mixSelected.setVisible(canWalletMix());
@ -478,6 +506,7 @@ public class UtxosController extends WalletFormController implements Initializab
utxosTable.getSelectionModel().clearSelection();
}
updateFields(walletUtxosEntry);
utxosTable.updateHistory(event.getHistoryChangedNodes());
utxosChart.update(walletUtxosEntry);
}
@ -497,6 +526,8 @@ public class UtxosController extends WalletFormController implements Initializab
public void bitcoinUnitChanged(BitcoinUnitChangedEvent event) {
utxosTable.setBitcoinUnit(getWalletForm().getWallet(), event.getBitcoinUnit());
utxosChart.setBitcoinUnit(getWalletForm().getWallet(), event.getBitcoinUnit());
balance.refresh(event.getBitcoinUnit());
mempoolBalance.refresh(event.getBitcoinUnit());
updateButtons(event.getBitcoinUnit());
}

View file

@ -5,8 +5,10 @@ import com.sparrowwallet.drongo.KeyDerivation;
import com.sparrowwallet.drongo.wallet.Keystore;
import com.sparrowwallet.drongo.wallet.WalletNode;
import com.sparrowwallet.sparrow.BaseController;
import com.sparrowwallet.sparrow.CurrencyRate;
import com.sparrowwallet.sparrow.EventManager;
import com.sparrowwallet.sparrow.WalletTabData;
import com.sparrowwallet.sparrow.control.FiatLabel;
import com.sparrowwallet.sparrow.event.WalletTabsClosedEvent;
public abstract class WalletFormController extends BaseController {
@ -53,4 +55,13 @@ public abstract class WalletFormController extends BaseController {
return node.getDerivationPath().replace("m", "multi");
}
protected void setFiatBalance(FiatLabel fiatLabel, CurrencyRate currencyRate, long balance) {
if(currencyRate != null && currencyRate.isAvailable() && balance > 0) {
fiatLabel.set(currencyRate, balance);
} else {
fiatLabel.setCurrency(null);
fiatLabel.setBtcRate(0.0);
}
}
}

View file

@ -98,7 +98,6 @@
<CheckMenuItem fx:id="hideEmptyUsedAddresses" mnemonicParsing="false" text="Hide Empty Used Addresses" onAction="#hideEmptyUsedAddresses"/>
<CheckMenuItem fx:id="useHdCameraResolution" mnemonicParsing="false" text="Use HD Camera Resolution" onAction="#useHdCameraResolution"/>
<CheckMenuItem fx:id="showLoadingLog" mnemonicParsing="false" text="Show Wallet Loading Log" onAction="#showLoadingLog" />
<CheckMenuItem fx:id="showUtxosChart" mnemonicParsing="false" text="Show UTXOs Chart" onAction="#showUtxosChart" />
<CheckMenuItem fx:id="showTxHex" mnemonicParsing="false" text="Show Transaction Hex" onAction="#showTxHex"/>
<SeparatorMenuItem />
<MenuItem fx:id="minimizeToTray" mnemonicParsing="false" text="Minimize to System Tray" accelerator="Shortcut+Y" onAction="#minimizeToTray"/>

View file

@ -5,35 +5,64 @@
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.chart.BarChart?>
<?import com.sparrowwallet.sparrow.control.UtxosTreeTable?>
<?import javafx.scene.chart.CategoryAxis?>
<?import javafx.scene.chart.NumberAxis?>
<?import com.sparrowwallet.sparrow.control.UtxosChart?>
<?import org.controlsfx.glyphfont.Glyph?>
<?import tornadofx.control.Form?>
<?import tornadofx.control.Fieldset?>
<?import tornadofx.control.Field?>
<?import com.sparrowwallet.sparrow.control.CoinLabel?>
<?import com.sparrowwallet.sparrow.control.FiatLabel?>
<?import com.sparrowwallet.sparrow.control.CopyableLabel?>
<BorderPane stylesheets="@utxos.css, @wallet.css, @../general.css" styleClass="wallet-pane" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.sparrowwallet.sparrow.wallet.UtxosController">
<padding>
<Insets left="25.0" right="25.0" top="15.0" bottom="25.0" />
</padding>
<center>
<VBox spacing="10.0">
<padding>
<Insets left="25.0" right="25.0" top="25.0" bottom="25.0" />
</padding>
<GridPane styleClass="send-form" hgap="10.0" vgap="10.0">
<columnConstraints>
<ColumnConstraints percentWidth="50" />
<ColumnConstraints percentWidth="50" />
</columnConstraints>
<rowConstraints>
<RowConstraints />
</rowConstraints>
<Form GridPane.columnIndex="0" GridPane.rowIndex="0">
<Fieldset inputGrow="SOMETIMES" text="Unspent Transaction Outputs" styleClass="header">
<Field text="Balance:">
<CoinLabel fx:id="balance"/><Region HBox.hgrow="ALWAYS"/><FiatLabel fx:id="fiatBalance" minWidth="110" />
</Field>
<Field text="Mempool:">
<CoinLabel fx:id="mempoolBalance" /><Region HBox.hgrow="ALWAYS"/><FiatLabel fx:id="fiatMempoolBalance" minWidth="110" />
</Field>
<Field text="UTXOs:">
<CopyableLabel fx:id="utxoCount" />
<Button fx:id="exportCsv" maxHeight="25" onAction="#exportUtxos" translateY="-1" styleClass="icon-button">
<graphic>
<Glyph fontFamily="Font Awesome 5 Free Solid" icon="ARROW_CIRCLE_DOWN" fontSize="12" />
</graphic>
<tooltip>
<Tooltip text="Export UTXOs as CSV" />
</tooltip>
</Button>
</Field>
</Fieldset>
</Form>
<UtxosChart fx:id="utxosChart" legendVisible="false" verticalGridLinesVisible="false" animated="false" GridPane.columnIndex="1" GridPane.rowIndex="0" maxHeight="140">
<xAxis>
<CategoryAxis side="BOTTOM" animated="false" tickLabelsVisible="false" tickMarkVisible="false" />
</xAxis>
<yAxis>
<NumberAxis side="LEFT" />
</yAxis>
</UtxosChart>
</GridPane>
<BorderPane VBox.vgrow="ALWAYS">
<top>
<HBox alignment="CENTER_LEFT">
<Label styleClass="utxos-treetable-label" text="Unspent Transaction Outputs"/>
<Button onAction="#exportUtxos" styleClass="icon-button">
<graphic>
<Glyph fontFamily="Font Awesome 5 Free Solid" icon="ARROW_CIRCLE_DOWN" fontSize="12" />
</graphic>
<tooltip>
<Tooltip text="Export UTXOs as CSV" />
</tooltip>
</Button>
</HBox>
</top>
<center>
<UtxosTreeTable fx:id="utxosTable" />
</center>
@ -69,14 +98,6 @@
</HBox>
</bottom>
</BorderPane>
<UtxosChart fx:id="utxosChart" legendVisible="false" verticalGridLinesVisible="false" animated="false" prefHeight="250">
<xAxis>
<CategoryAxis side="BOTTOM" animated="false" />
</xAxis>
<yAxis>
<NumberAxis side="LEFT" />
</yAxis>
</UtxosChart>
</VBox>
</center>
</BorderPane>