mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-23 15:00:30 +01:00
Merge pull request #2513 from ripcurlx/create-dao-section-for-economy
Move BSQ dashboard into separate Facts & Figures section
This commit is contained in:
commit
2356d2eba2
18 changed files with 1197 additions and 295 deletions
|
@ -421,6 +421,10 @@ public class BSFormatter {
|
|||
}
|
||||
}
|
||||
|
||||
public String formatPrice(Price price, boolean appendCurrencyCode) {
|
||||
return formatPrice(price, fiatPriceFormat, true);
|
||||
}
|
||||
|
||||
public String formatPrice(Price price) {
|
||||
return formatPrice(price, fiatPriceFormat, false);
|
||||
}
|
||||
|
|
|
@ -124,6 +124,10 @@ public class BsqFormatter extends BSFormatter {
|
|||
return super.formatCoin(satoshi, coinFormat);
|
||||
}
|
||||
|
||||
public String formatBSQSatoshisWithCode(long satoshi) {
|
||||
return super.formatCoinWithCode(satoshi, coinFormat);
|
||||
}
|
||||
|
||||
public String formatBTCSatoshis(long satoshi) {
|
||||
return super.formatCoin(satoshi, btcCoinFormat);
|
||||
}
|
||||
|
|
|
@ -198,6 +198,7 @@ shared.actions=Actions
|
|||
shared.buyerUpperCase=Buyer
|
||||
shared.sellerUpperCase=Seller
|
||||
shared.new=NEW
|
||||
shared.new=NEW
|
||||
|
||||
####################################################################
|
||||
# UI views
|
||||
|
@ -1268,6 +1269,7 @@ account.notifications.priceAlert.warning.lowerPriceTooHigh=The lower price must
|
|||
# DAO
|
||||
####################################################################
|
||||
|
||||
dao.tab.factsAndFigures=Facts & Figures
|
||||
dao.tab.bsqWallet=BSQ wallet
|
||||
dao.tab.proposals=Governance
|
||||
dao.tab.bonding=Bonding
|
||||
|
@ -1755,29 +1757,6 @@ dao.wallet.menuItem.receive=Receive
|
|||
dao.wallet.menuItem.transactions=Transactions
|
||||
|
||||
dao.wallet.dashboard.myBalance=My wallet balance
|
||||
dao.wallet.dashboard.distribution=Distribution of all BSQ
|
||||
dao.wallet.dashboard.locked=Global state of locked BSQ
|
||||
dao.wallet.dashboard.market=Market data
|
||||
dao.wallet.dashboard.genesis=Genesis transaction
|
||||
dao.wallet.dashboard.txDetails=BSQ transactions statistics
|
||||
dao.wallet.dashboard.genesisBlockHeight=Genesis block height
|
||||
dao.wallet.dashboard.genesisTxId=Genesis transaction ID
|
||||
dao.wallet.dashboard.genesisIssueAmount=BSQ issued at genesis transaction
|
||||
dao.wallet.dashboard.compRequestIssueAmount=BSQ issued for compensation requests
|
||||
dao.wallet.dashboard.reimbursementAmount=BSQ issued for reimbursement requests
|
||||
dao.wallet.dashboard.availableAmount=Total available BSQ
|
||||
dao.wallet.dashboard.burntAmount=Burned BSQ (fees)
|
||||
dao.wallet.dashboard.totalLockedUpAmount=Locked up in bonds
|
||||
dao.wallet.dashboard.totalUnlockingAmount=Unlocking BSQ from bonds
|
||||
dao.wallet.dashboard.totalUnlockedAmount=Unlocked BSQ from bonds
|
||||
dao.wallet.dashboard.totalConfiscatedAmount=Confiscated BSQ from bonds
|
||||
dao.wallet.dashboard.allTx=No. of all BSQ transactions
|
||||
dao.wallet.dashboard.utxo=No. of all unspent transaction outputs
|
||||
dao.wallet.dashboard.compensationIssuanceTx=No. of all compensation request issuance transactions
|
||||
dao.wallet.dashboard.reimbursementIssuanceTx=No. of all reimbursement request issuance transactions
|
||||
dao.wallet.dashboard.burntTx=No. of all fee payments transactions
|
||||
dao.wallet.dashboard.price=Latest BSQ/BTC trade price (in Bisq)
|
||||
dao.wallet.dashboard.marketCap=Market capitalisation (based on trade price)
|
||||
|
||||
dao.wallet.receive.fundYourWallet=Your BSQ receive address
|
||||
dao.wallet.receive.bsqAddress=BSQ wallet address (Fresh unused address)
|
||||
|
@ -1939,6 +1918,37 @@ dao.monitor.blindVote.table.hash=Hash of blind vote state
|
|||
dao.monitor.blindVote.table.prev=Previous hash
|
||||
dao.monitor.blindVote.table.numBlindVotes=No. blind votes
|
||||
|
||||
dao.factsAndFigures.menuItem.supply=BSQ Supply
|
||||
dao.factsAndFigures.menuItem.transactions=BSQ Transactions
|
||||
|
||||
dao.factsAndFigures.dashboard.marketPrice=Market data
|
||||
dao.factsAndFigures.dashboard.price=Latest BSQ/BTC trade price (in Bisq)
|
||||
dao.factsAndFigures.dashboard.marketCap=Market capitalisation (based on trade price)
|
||||
dao.factsAndFigures.dashboard.availableAmount=Total available BSQ
|
||||
|
||||
dao.factsAndFigures.supply.issued=BSQ issued
|
||||
dao.factsAndFigures.supply.genesisIssueAmount=BSQ issued at genesis transaction
|
||||
dao.factsAndFigures.supply.compRequestIssueAmount=BSQ issued for compensation requests
|
||||
dao.factsAndFigures.supply.reimbursementAmount=BSQ issued for reimbursement requests
|
||||
|
||||
dao.factsAndFigures.supply.burnt=BSQ burnt
|
||||
|
||||
dao.factsAndFigures.supply.locked=Global state of locked BSQ
|
||||
dao.factsAndFigures.supply.totalLockedUpAmount=Locked up in bonds
|
||||
dao.factsAndFigures.supply.totalUnlockingAmount=Unlocking BSQ from bonds
|
||||
dao.factsAndFigures.supply.totalUnlockedAmount=Unlocked BSQ from bonds
|
||||
dao.factsAndFigures.supply.totalConfiscatedAmount=Confiscated BSQ from bonds
|
||||
dao.factsAndFigures.supply.burntAmount=Burned BSQ (fees)
|
||||
|
||||
dao.factsAndFigures.transactions.genesis=Genesis transaction
|
||||
dao.factsAndFigures.transactions.genesisBlockHeight=Genesis block height
|
||||
dao.factsAndFigures.transactions.genesisTxId=Genesis transaction ID
|
||||
dao.factsAndFigures.transactions.txDetails=BSQ transactions statistics
|
||||
dao.factsAndFigures.transactions.allTx=No. of all BSQ transactions
|
||||
dao.factsAndFigures.transactions.utxo=No. of all unspent transaction outputs
|
||||
dao.factsAndFigures.transactions.compensationIssuanceTx=No. of all compensation request issuance transactions
|
||||
dao.factsAndFigures.transactions.reimbursementIssuanceTx=No. of all reimbursement request issuance transactions
|
||||
dao.factsAndFigures.transactions.burntTx=No. of all fee payments transactions
|
||||
|
||||
####################################################################
|
||||
# Windows
|
||||
|
|
|
@ -1682,17 +1682,21 @@ textfield */
|
|||
* *
|
||||
********************************************************************************************************************/
|
||||
|
||||
#charts .chart-legend {
|
||||
.chart-pane {
|
||||
-fx-background-color: -bs-rd-white;
|
||||
}
|
||||
|
||||
#charts .chart-legend, #charts-dao .chart-legend {
|
||||
-fx-font-size: 1.077em;
|
||||
-fx-alignment: center;
|
||||
}
|
||||
|
||||
#charts .axis, #price-chart .axis, #volume-chart .axis {
|
||||
#charts .axis, #price-chart .axis, #volume-chart .axis, #charts-dao .axis {
|
||||
-fx-tick-label-fill: -bs-rd-font-lighter;
|
||||
-fx-tick-label-font-size: 0.769em;
|
||||
}
|
||||
|
||||
#charts .chart-plot-background {
|
||||
#charts .chart-plot-background, #charts-dao .chart-plot-background {
|
||||
-fx-background-color: -bs-rd-white;
|
||||
}
|
||||
|
||||
|
@ -1700,7 +1704,7 @@ textfield */
|
|||
-fx-background-color: -bs-sell, -bs-rd-white;
|
||||
}
|
||||
|
||||
#charts .default-color1.chart-area-symbol {
|
||||
#charts .default-color1.chart-area-symbol, #charts-dao .default-color0.chart-area-symbol {
|
||||
-fx-background-color: -bs-buy, -bs-rd-white;
|
||||
}
|
||||
|
||||
|
@ -1708,7 +1712,7 @@ textfield */
|
|||
-fx-stroke: -bs-sell;
|
||||
}
|
||||
|
||||
#charts .default-color1.chart-series-area-line {
|
||||
#charts .default-color1.chart-series-area-line, #charts-dao .default-color0.chart-series-area-line {
|
||||
-fx-stroke: -bs-buy;
|
||||
}
|
||||
|
||||
|
@ -1716,7 +1720,7 @@ textfield */
|
|||
-fx-fill: -bs-sell-transparent;
|
||||
}
|
||||
|
||||
#charts .default-color1.chart-series-area-fill {
|
||||
#charts .default-color1.chart-series-area-fill, #charts-dao .default-color0.chart-series-area-fill {
|
||||
-fx-fill: -bs-buy-transparent;
|
||||
}
|
||||
|
||||
|
@ -2071,6 +2075,17 @@ textfield */
|
|||
-fx-text-fill: -bs-rd-error-red;
|
||||
}
|
||||
|
||||
.dao-kpi-big {
|
||||
-fx-font-size: 1.923em;
|
||||
-fx-text-fill: -bs-rd-black;
|
||||
-fx-font-family: "IBM Plex Sans Light";
|
||||
}
|
||||
|
||||
.dao-kpi-subtext {
|
||||
-fx-text-fill: -bs-rd-font-light;
|
||||
-fx-font-size: 0.923em;
|
||||
}
|
||||
|
||||
/********************************************************************************************************************
|
||||
* *
|
||||
* Notifications *
|
||||
|
|
|
@ -27,11 +27,12 @@ import bisq.desktop.common.view.ViewLoader;
|
|||
import bisq.desktop.main.MainView;
|
||||
import bisq.desktop.main.dao.bonding.BondingView;
|
||||
import bisq.desktop.main.dao.burnbsq.BurnBsqView;
|
||||
import bisq.desktop.main.dao.economy.EconomyView;
|
||||
import bisq.desktop.main.dao.governance.GovernanceView;
|
||||
import bisq.desktop.main.dao.monitor.MonitorView;
|
||||
import bisq.desktop.main.dao.news.NewsView;
|
||||
import bisq.desktop.main.dao.wallet.BsqWalletView;
|
||||
import bisq.desktop.main.dao.wallet.dashboard.BsqDashboardView;
|
||||
import bisq.desktop.main.dao.wallet.send.BsqSendView;
|
||||
import bisq.desktop.main.overlays.popups.Popup;
|
||||
|
||||
import bisq.core.dao.governance.votereveal.VoteRevealService;
|
||||
|
@ -53,7 +54,7 @@ import javafx.beans.value.ChangeListener;
|
|||
public class DaoView extends ActivatableViewAndModel<TabPane, Activatable> {
|
||||
|
||||
@FXML
|
||||
private Tab bsqWalletTab, proposalsTab, bondingTab, burnBsqTab, daoNewsTab, monitor;
|
||||
private Tab bsqWalletTab, proposalsTab, bondingTab, burnBsqTab, daoNewsTab, monitorTab, factsAndFiguresTab;
|
||||
|
||||
private Navigation.Listener navigationListener;
|
||||
private ChangeListener<Tab> tabChangeListener;
|
||||
|
@ -77,36 +78,39 @@ public class DaoView extends ActivatableViewAndModel<TabPane, Activatable> {
|
|||
|
||||
@Override
|
||||
public void initialize() {
|
||||
factsAndFiguresTab = new Tab(Res.get("dao.tab.factsAndFigures").toUpperCase());
|
||||
bsqWalletTab = new Tab(Res.get("dao.tab.bsqWallet").toUpperCase());
|
||||
proposalsTab = new Tab(Res.get("dao.tab.proposals").toUpperCase());
|
||||
bondingTab = new Tab(Res.get("dao.tab.bonding").toUpperCase());
|
||||
burnBsqTab = new Tab(Res.get("dao.tab.proofOfBurn").toUpperCase());
|
||||
monitor = new Tab(Res.get("dao.tab.monitor").toUpperCase());
|
||||
monitorTab = new Tab(Res.get("dao.tab.monitor").toUpperCase());
|
||||
|
||||
factsAndFiguresTab.setClosable(false);
|
||||
bsqWalletTab.setClosable(false);
|
||||
proposalsTab.setClosable(false);
|
||||
bondingTab.setClosable(false);
|
||||
burnBsqTab.setClosable(false);
|
||||
monitor.setClosable(false);
|
||||
monitorTab.setClosable(false);
|
||||
|
||||
if (!DevEnv.isDaoActivated()) {
|
||||
factsAndFiguresTab.setDisable(true);
|
||||
bsqWalletTab.setDisable(true);
|
||||
proposalsTab.setDisable(true);
|
||||
bondingTab.setDisable(true);
|
||||
burnBsqTab.setDisable(true);
|
||||
monitor.setDisable(true);
|
||||
monitorTab.setDisable(true);
|
||||
|
||||
daoNewsTab = new Tab(Res.get("dao.tab.news").toUpperCase());
|
||||
|
||||
root.getTabs().add(daoNewsTab);
|
||||
} else {
|
||||
root.getTabs().addAll(bsqWalletTab, proposalsTab, bondingTab, burnBsqTab, monitor);
|
||||
root.getTabs().addAll(factsAndFiguresTab, bsqWalletTab, proposalsTab, bondingTab, burnBsqTab, monitorTab);
|
||||
}
|
||||
|
||||
navigationListener = viewPath -> {
|
||||
if (viewPath.size() == 3 && viewPath.indexOf(DaoView.class) == 1) {
|
||||
if (proposalsTab == null && viewPath.get(2).equals(BsqWalletView.class))
|
||||
navigation.navigateTo(MainView.class, DaoView.class, BsqWalletView.class);
|
||||
if (proposalsTab == null && viewPath.get(2).equals(EconomyView.class))
|
||||
navigation.navigateTo(MainView.class, DaoView.class, EconomyView.class);
|
||||
else
|
||||
loadView(viewPath.tip());
|
||||
}
|
||||
|
@ -114,9 +118,9 @@ public class DaoView extends ActivatableViewAndModel<TabPane, Activatable> {
|
|||
|
||||
tabChangeListener = (ov, oldValue, newValue) -> {
|
||||
if (newValue == bsqWalletTab) {
|
||||
Class<? extends View> selectedViewClass = bsqWalletView.getSelectedViewClass();
|
||||
Class<? extends View> selectedViewClass = bsqWalletView != null ? bsqWalletView.getSelectedViewClass() : null;
|
||||
if (selectedViewClass == null)
|
||||
navigation.navigateTo(MainView.class, DaoView.class, BsqWalletView.class, BsqDashboardView.class);
|
||||
navigation.navigateTo(MainView.class, DaoView.class, BsqWalletView.class, BsqSendView.class);
|
||||
else
|
||||
navigation.navigateTo(MainView.class, DaoView.class, BsqWalletView.class, selectedViewClass);
|
||||
} else if (newValue == proposalsTab) {
|
||||
|
@ -125,7 +129,9 @@ public class DaoView extends ActivatableViewAndModel<TabPane, Activatable> {
|
|||
navigation.navigateTo(MainView.class, DaoView.class, BondingView.class);
|
||||
} else if (newValue == burnBsqTab) {
|
||||
navigation.navigateTo(MainView.class, DaoView.class, BurnBsqView.class);
|
||||
} else if (newValue == monitor) {
|
||||
} else if (newValue == factsAndFiguresTab) {
|
||||
navigation.navigateTo(MainView.class, DaoView.class, EconomyView.class);
|
||||
} else if (newValue == monitorTab) {
|
||||
navigation.navigateTo(MainView.class, DaoView.class, MonitorView.class);
|
||||
}
|
||||
};
|
||||
|
@ -147,7 +153,9 @@ public class DaoView extends ActivatableViewAndModel<TabPane, Activatable> {
|
|||
navigation.navigateTo(MainView.class, DaoView.class, BondingView.class);
|
||||
else if (selectedItem == burnBsqTab)
|
||||
navigation.navigateTo(MainView.class, DaoView.class, BurnBsqView.class);
|
||||
else if (selectedItem == monitor)
|
||||
else if (selectedItem == factsAndFiguresTab)
|
||||
navigation.navigateTo(MainView.class, DaoView.class, EconomyView.class);
|
||||
else if (selectedItem == monitorTab)
|
||||
navigation.navigateTo(MainView.class, DaoView.class, MonitorView.class);
|
||||
}
|
||||
} else {
|
||||
|
@ -182,9 +190,11 @@ public class DaoView extends ActivatableViewAndModel<TabPane, Activatable> {
|
|||
} else if (view instanceof BurnBsqView) {
|
||||
selectedTab = burnBsqTab;
|
||||
} else if (view instanceof MonitorView) {
|
||||
selectedTab = monitor;
|
||||
selectedTab = monitorTab;
|
||||
} else if (view instanceof NewsView) {
|
||||
selectedTab = daoNewsTab;
|
||||
} else if (view instanceof EconomyView) {
|
||||
selectedTab = factsAndFiguresTab;
|
||||
}
|
||||
|
||||
selectedTab.setContent(view.getRoot());
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!--
|
||||
~ This file is part of Bisq.
|
||||
~
|
||||
~ Bisq is free software: you can redistribute it and/or modify it
|
||||
~ under the terms of the GNU Affero General Public License as published by
|
||||
~ the Free Software Foundation, either version 3 of the License, or (at
|
||||
~ your option) any later version.
|
||||
~
|
||||
~ Bisq is distributed in the hope that it will be useful, but WITHOUT
|
||||
~ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
~ FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
~ License for more details.
|
||||
~
|
||||
~ You should have received a copy of the GNU Affero General Public License
|
||||
~ along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
|
||||
<?import javafx.scene.control.ScrollPane?>
|
||||
<?import javafx.scene.layout.AnchorPane?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
<AnchorPane fx:id="root" fx:controller="bisq.desktop.main.dao.economy.EconomyView"
|
||||
xmlns:fx="http://javafx.com/fxml">
|
||||
|
||||
<VBox fx:id="leftVBox" prefWidth="240" spacing="5" AnchorPane.bottomAnchor="20" AnchorPane.leftAnchor="15"
|
||||
AnchorPane.topAnchor="15"/>
|
||||
|
||||
<ScrollPane fitToWidth="true" fitToHeight="true"
|
||||
AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="270.0"
|
||||
AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
|
||||
<AnchorPane fx:id="content"/>
|
||||
</ScrollPane>
|
||||
|
||||
</AnchorPane>
|
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* This file is part of Bisq.
|
||||
*
|
||||
* Bisq is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bisq is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more supply.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package bisq.desktop.main.dao.economy;
|
||||
|
||||
import bisq.desktop.Navigation;
|
||||
import bisq.desktop.common.view.ActivatableViewAndModel;
|
||||
import bisq.desktop.common.view.CachingViewLoader;
|
||||
import bisq.desktop.common.view.FxmlView;
|
||||
import bisq.desktop.common.view.View;
|
||||
import bisq.desktop.common.view.ViewLoader;
|
||||
import bisq.desktop.common.view.ViewPath;
|
||||
import bisq.desktop.components.MenuItem;
|
||||
import bisq.desktop.main.MainView;
|
||||
import bisq.desktop.main.dao.DaoView;
|
||||
import bisq.desktop.main.dao.economy.dashboard.BsqDashboardView;
|
||||
import bisq.desktop.main.dao.economy.supply.SupplyView;
|
||||
import bisq.desktop.main.dao.economy.transactions.BSQTransactionsView;
|
||||
|
||||
import bisq.core.locale.Res;
|
||||
|
||||
import bisq.common.app.DevEnv;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import javafx.fxml.FXML;
|
||||
|
||||
import javafx.scene.control.ToggleGroup;
|
||||
import javafx.scene.layout.AnchorPane;
|
||||
import javafx.scene.layout.VBox;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@FxmlView
|
||||
public class EconomyView extends ActivatableViewAndModel {
|
||||
|
||||
private final ViewLoader viewLoader;
|
||||
private final Navigation navigation;
|
||||
|
||||
private MenuItem dashboard, supply, transactions;
|
||||
private Navigation.Listener listener;
|
||||
|
||||
@FXML
|
||||
private VBox leftVBox;
|
||||
@FXML
|
||||
private AnchorPane content;
|
||||
|
||||
private Class<? extends View> selectedViewClass;
|
||||
private ToggleGroup toggleGroup;
|
||||
|
||||
@Inject
|
||||
private EconomyView(CachingViewLoader viewLoader, Navigation navigation) {
|
||||
this.viewLoader = viewLoader;
|
||||
this.navigation = navigation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
listener = viewPath -> {
|
||||
if (viewPath.size() != 4 || viewPath.indexOf(EconomyView.class) != 2)
|
||||
return;
|
||||
|
||||
selectedViewClass = viewPath.tip();
|
||||
loadView(selectedViewClass);
|
||||
};
|
||||
|
||||
toggleGroup = new ToggleGroup();
|
||||
List<Class<? extends View>> baseNavPath = Arrays.asList(MainView.class, DaoView.class, EconomyView.class);
|
||||
dashboard = new MenuItem(navigation, toggleGroup, Res.get("shared.dashboard"), BsqDashboardView.class, baseNavPath);
|
||||
supply = new MenuItem(navigation, toggleGroup, Res.get("dao.factsAndFigures.menuItem.supply"), SupplyView.class, baseNavPath);
|
||||
transactions = new MenuItem(navigation, toggleGroup, Res.get("dao.factsAndFigures.menuItem.transactions"), BSQTransactionsView.class, baseNavPath);
|
||||
|
||||
leftVBox.getChildren().addAll(dashboard, supply, transactions);
|
||||
|
||||
// TODO just until DAO is enabled
|
||||
if (!DevEnv.isDaoActivated()) {
|
||||
dashboard.setDisable(true);
|
||||
supply.setDisable(true);
|
||||
transactions.setDisable(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void activate() {
|
||||
dashboard.activate();
|
||||
supply.activate();
|
||||
transactions.activate();
|
||||
|
||||
navigation.addListener(listener);
|
||||
ViewPath viewPath = navigation.getCurrentPath();
|
||||
if (viewPath.size() == 3 && viewPath.indexOf(EconomyView.class) == 2 ||
|
||||
viewPath.size() == 2 && viewPath.indexOf(DaoView.class) == 1) {
|
||||
if (selectedViewClass == null)
|
||||
selectedViewClass = BsqDashboardView.class;
|
||||
|
||||
loadView(selectedViewClass);
|
||||
} else if (viewPath.size() == 4 && viewPath.indexOf(EconomyView.class) == 2) {
|
||||
selectedViewClass = viewPath.get(3);
|
||||
loadView(selectedViewClass);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("Duplicates")
|
||||
@Override
|
||||
protected void deactivate() {
|
||||
navigation.removeListener(listener);
|
||||
|
||||
dashboard.deactivate();
|
||||
supply.deactivate();
|
||||
transactions.deactivate();
|
||||
}
|
||||
|
||||
private void loadView(Class<? extends View> viewClass) {
|
||||
View view = viewLoader.load(viewClass);
|
||||
content.getChildren().setAll(view.getRoot());
|
||||
|
||||
if (view instanceof BsqDashboardView) toggleGroup.selectToggle(dashboard);
|
||||
else if (view instanceof SupplyView) toggleGroup.selectToggle(supply);
|
||||
else if (view instanceof BSQTransactionsView) toggleGroup.selectToggle(transactions);
|
||||
}
|
||||
}
|
|
@ -20,14 +20,13 @@
|
|||
<?import javafx.scene.layout.AnchorPane?>
|
||||
<?import javafx.scene.layout.ColumnConstraints?>
|
||||
<?import javafx.scene.layout.GridPane?>
|
||||
<GridPane fx:id="root" fx:controller="bisq.desktop.main.dao.wallet.dashboard.BsqDashboardView"
|
||||
<GridPane fx:id="root" fx:controller="bisq.desktop.main.dao.economy.dashboard.BsqDashboardView"
|
||||
hgap="5.0" vgap="5.0"
|
||||
AnchorPane.bottomAnchor="20.0" AnchorPane.leftAnchor="20.0"
|
||||
AnchorPane.rightAnchor="25.0" AnchorPane.topAnchor="20.0"
|
||||
xmlns:fx="http://javafx.com/fxml">
|
||||
<columnConstraints>
|
||||
<ColumnConstraints percentWidth="50"/>
|
||||
<ColumnConstraints minWidth="10" maxWidth="5"/>
|
||||
<ColumnConstraints percentWidth="50"/>
|
||||
</columnConstraints>
|
||||
</GridPane>
|
|
@ -0,0 +1,324 @@
|
|||
/*
|
||||
* This file is part of Bisq.
|
||||
*
|
||||
* Bisq is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bisq is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package bisq.desktop.main.dao.economy.dashboard;
|
||||
|
||||
import bisq.desktop.common.view.ActivatableView;
|
||||
import bisq.desktop.common.view.FxmlView;
|
||||
import bisq.desktop.util.FormBuilder;
|
||||
|
||||
import bisq.core.dao.DaoFacade;
|
||||
import bisq.core.dao.state.DaoStateListener;
|
||||
import bisq.core.dao.state.DaoStateService;
|
||||
import bisq.core.dao.state.model.blockchain.Block;
|
||||
import bisq.core.dao.state.model.governance.IssuanceType;
|
||||
import bisq.core.locale.Res;
|
||||
import bisq.core.monetary.Price;
|
||||
import bisq.core.provider.price.PriceFeedService;
|
||||
import bisq.core.trade.statistics.TradeStatistics2;
|
||||
import bisq.core.trade.statistics.TradeStatisticsManager;
|
||||
import bisq.core.user.Preferences;
|
||||
import bisq.core.util.BSFormatter;
|
||||
import bisq.core.util.BsqFormatter;
|
||||
|
||||
import bisq.common.util.Tuple3;
|
||||
|
||||
import org.bitcoinj.core.Coin;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import javafx.scene.chart.AreaChart;
|
||||
import javafx.scene.chart.NumberAxis;
|
||||
import javafx.scene.chart.XYChart;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.layout.AnchorPane;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.layout.VBox;
|
||||
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Side;
|
||||
|
||||
import javafx.beans.value.ChangeListener;
|
||||
|
||||
import javafx.util.StringConverter;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.FormatStyle;
|
||||
import java.time.temporal.TemporalAdjuster;
|
||||
import java.time.temporal.TemporalAdjusters;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static bisq.desktop.util.FormBuilder.addLabelWithSubText;
|
||||
import static bisq.desktop.util.FormBuilder.addTopLabelReadOnlyTextField;
|
||||
|
||||
|
||||
|
||||
import java.sql.Date;
|
||||
|
||||
@FxmlView
|
||||
public class BsqDashboardView extends ActivatableView<GridPane, Void> implements DaoStateListener {
|
||||
|
||||
private static final String DAY = "day";
|
||||
private static final Map<String, TemporalAdjuster> ADJUSTERS = new HashMap<>();
|
||||
|
||||
private final DaoFacade daoFacade;
|
||||
private final TradeStatisticsManager tradeStatisticsManager;
|
||||
private final PriceFeedService priceFeedService;
|
||||
private final DaoStateService daoStateService;
|
||||
private final Preferences preferences;
|
||||
private final BsqFormatter bsqFormatter;
|
||||
private final BSFormatter btcFormatter;
|
||||
|
||||
private ChangeListener<Number> priceChangeListener;
|
||||
|
||||
private AreaChart bsqPriceChart;
|
||||
private XYChart.Series<Number, Number> seriesBSQAdded, seriesBSQBurnt;
|
||||
private XYChart.Series<Number, Number> seriesBSQPrice;
|
||||
|
||||
private TextField marketCapTextField, availableAmountTextField;
|
||||
private Label marketPriceLabel;
|
||||
|
||||
private Coin availableAmount;
|
||||
|
||||
private int gridRow = 0;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor, lifecycle
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Inject
|
||||
private BsqDashboardView(DaoFacade daoFacade,
|
||||
TradeStatisticsManager tradeStatisticsManager,
|
||||
PriceFeedService priceFeedService,
|
||||
DaoStateService daoStateService,
|
||||
Preferences preferences,
|
||||
BsqFormatter bsqFormatter,
|
||||
BSFormatter btcFormatter) {
|
||||
this.daoFacade = daoFacade;
|
||||
this.tradeStatisticsManager = tradeStatisticsManager;
|
||||
this.priceFeedService = priceFeedService;
|
||||
this.daoStateService = daoStateService;
|
||||
this.preferences = preferences;
|
||||
this.bsqFormatter = bsqFormatter;
|
||||
this.btcFormatter = btcFormatter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
|
||||
ADJUSTERS.put(DAY, TemporalAdjusters.ofDateAdjuster(d -> d));
|
||||
|
||||
createKPIs();
|
||||
createChart();
|
||||
|
||||
priceChangeListener = (observable, oldValue, newValue) -> updatePrice();
|
||||
}
|
||||
|
||||
private void createKPIs() {
|
||||
|
||||
Tuple3<Label, Label, VBox> marketPriceBox = addLabelWithSubText(root, gridRow++, "0.004000 BSQ/BTC", "Latest BSQ/BTC trade price (in Bisq)");
|
||||
marketPriceLabel = marketPriceBox.first;
|
||||
marketPriceLabel.getStyleClass().add("dao-kpi-big");
|
||||
|
||||
marketPriceBox.second.getStyleClass().add("dao-kpi-subtext");
|
||||
|
||||
marketCapTextField = addTopLabelReadOnlyTextField(root, ++gridRow,
|
||||
Res.get("dao.factsAndFigures.dashboard.marketCap")).second;
|
||||
|
||||
availableAmountTextField = FormBuilder.addTopLabelReadOnlyTextField(root, gridRow, 1,
|
||||
Res.get("dao.factsAndFigures.dashboard.availableAmount")).second;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void activate() {
|
||||
daoFacade.addBsqStateListener(this);
|
||||
priceFeedService.updateCounterProperty().addListener(priceChangeListener);
|
||||
|
||||
updateWithBsqBlockChainData();
|
||||
updatePrice();
|
||||
updateChartData();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void deactivate() {
|
||||
daoFacade.removeBsqStateListener(this);
|
||||
priceFeedService.updateCounterProperty().removeListener(priceChangeListener);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// DaoStateListener
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void onParseBlockCompleteAfterBatchProcessing(Block block) {
|
||||
updateWithBsqBlockChainData();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Private
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void createChart() {
|
||||
NumberAxis xAxis = new NumberAxis();
|
||||
xAxis.setForceZeroInRange(false);
|
||||
xAxis.setAutoRanging(true);
|
||||
xAxis.setTickLabelGap(6);
|
||||
xAxis.setTickMarkVisible(false);
|
||||
xAxis.setMinorTickVisible(false);
|
||||
|
||||
xAxis.setTickLabelFormatter(new StringConverter<>() {
|
||||
@Override
|
||||
public String toString(Number timestamp) {
|
||||
LocalDateTime localDateTime = LocalDateTime.ofEpochSecond(timestamp.longValue(),
|
||||
0, OffsetDateTime.now(ZoneId.systemDefault()).getOffset());
|
||||
return localDateTime.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Number fromString(String string) {
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
|
||||
NumberAxis yAxis = new NumberAxis();
|
||||
yAxis.setForceZeroInRange(false);
|
||||
yAxis.setSide(Side.RIGHT);
|
||||
yAxis.setAutoRanging(true);
|
||||
yAxis.setTickMarkVisible(false);
|
||||
yAxis.setMinorTickVisible(false);
|
||||
yAxis.setTickLabelGap(5);
|
||||
yAxis.setTickLabelFormatter(new StringConverter<>() {
|
||||
@Override
|
||||
public String toString(Number marketPrice) {
|
||||
return bsqFormatter.formatBTCWithCode(marketPrice.longValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Number fromString(String string) {
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
|
||||
seriesBSQPrice = new XYChart.Series<>();
|
||||
seriesBSQPrice.setName("Price in BTC for 1 BSQ");
|
||||
|
||||
bsqPriceChart = new AreaChart<>(xAxis, yAxis);
|
||||
bsqPriceChart.setLegendVisible(false);
|
||||
bsqPriceChart.setAnimated(false);
|
||||
bsqPriceChart.setId("charts-dao");
|
||||
bsqPriceChart.setMinHeight(385);
|
||||
bsqPriceChart.setPrefHeight(385);
|
||||
bsqPriceChart.setCreateSymbols(true);
|
||||
bsqPriceChart.setPadding(new Insets(0));
|
||||
bsqPriceChart.getData().addAll(seriesBSQPrice);
|
||||
|
||||
AnchorPane chartPane = new AnchorPane();
|
||||
chartPane.getStyleClass().add("chart-pane");
|
||||
|
||||
AnchorPane.setTopAnchor(bsqPriceChart, 15d);
|
||||
AnchorPane.setBottomAnchor(bsqPriceChart, 10d);
|
||||
AnchorPane.setLeftAnchor(bsqPriceChart, 25d);
|
||||
AnchorPane.setRightAnchor(bsqPriceChart, 10d);
|
||||
|
||||
chartPane.getChildren().add(bsqPriceChart);
|
||||
|
||||
GridPane.setRowIndex(chartPane, ++gridRow);
|
||||
GridPane.setColumnSpan(chartPane, 2);
|
||||
GridPane.setMargin(chartPane, new Insets(10, 0, 0, 0));
|
||||
|
||||
root.getChildren().addAll(chartPane);
|
||||
}
|
||||
|
||||
private void updateChartData() {
|
||||
updateBSQPriceData();
|
||||
}
|
||||
|
||||
private void updateBSQPriceData() {
|
||||
seriesBSQPrice.getData().clear();
|
||||
|
||||
Map<LocalDate, List<TradeStatistics2>> bsqPriceByDate = tradeStatisticsManager.getObservableTradeStatisticsSet().stream()
|
||||
.filter(e -> e.getCurrencyCode().equals("BSQ"))
|
||||
.sorted(Comparator.comparing(TradeStatistics2::getTradeDate))
|
||||
.collect(Collectors.groupingBy(item -> new Date(item.getTradeDate().getTime()).toLocalDate()
|
||||
.with(ADJUSTERS.get(DAY))));
|
||||
|
||||
List<XYChart.Data<Number, Number>> updatedBSQPrice = bsqPriceByDate.keySet().stream()
|
||||
.map(e -> {
|
||||
ZonedDateTime zonedDateTime = e.atStartOfDay(ZoneId.systemDefault());
|
||||
return new XYChart.Data<Number, Number>(zonedDateTime.toInstant().getEpochSecond(), bsqPriceByDate.get(e).stream()
|
||||
.map(TradeStatistics2::getTradePrice)
|
||||
.mapToDouble(Price::getValue)
|
||||
.average()
|
||||
.orElse(Double.NaN)
|
||||
);
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
|
||||
seriesBSQPrice.getData().setAll(updatedBSQPrice);
|
||||
}
|
||||
|
||||
private void updateWithBsqBlockChainData() {
|
||||
Coin issuedAmountFromGenesis = daoFacade.getGenesisTotalSupply();
|
||||
Coin issuedAmountFromCompRequests = Coin.valueOf(daoFacade.getTotalIssuedAmount(IssuanceType.COMPENSATION));
|
||||
Coin issuedAmountFromReimbursementRequests = Coin.valueOf(daoFacade.getTotalIssuedAmount(IssuanceType.REIMBURSEMENT));
|
||||
Coin burntFee = Coin.valueOf(daoFacade.getTotalBurntFee());
|
||||
Coin totalConfiscatedAmount = Coin.valueOf(daoFacade.getTotalAmountOfConfiscatedTxOutputs());
|
||||
|
||||
availableAmount = issuedAmountFromGenesis
|
||||
.add(issuedAmountFromCompRequests)
|
||||
.add(issuedAmountFromReimbursementRequests)
|
||||
.subtract(burntFee)
|
||||
.subtract(totalConfiscatedAmount);
|
||||
|
||||
availableAmountTextField.setText(bsqFormatter.formatAmountWithGroupSeparatorAndCode(availableAmount));
|
||||
}
|
||||
|
||||
private void updatePrice() {
|
||||
Optional<Price> optionalBsqPrice = priceFeedService.getBsqPrice();
|
||||
if (optionalBsqPrice.isPresent()) {
|
||||
Price bsqPrice = optionalBsqPrice.get();
|
||||
marketPriceLabel.setText(bsqFormatter.formatPrice(bsqPrice) + " BSQ/BTC");
|
||||
|
||||
marketCapTextField.setText(bsqFormatter.formatMarketCap(priceFeedService.getMarketPrice("BSQ"),
|
||||
priceFeedService.getMarketPrice(preferences.getPreferredTradeCurrency().getCode()),
|
||||
availableAmount));
|
||||
|
||||
updateChartData();
|
||||
|
||||
} else {
|
||||
marketPriceLabel.setText(Res.get("shared.na"));
|
||||
marketCapTextField.setText(Res.get("shared.na"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!--
|
||||
~ This file is part of Bisq.
|
||||
~
|
||||
~ Bisq is free software: you can redistribute it and/or modify it
|
||||
~ under the terms of the GNU Affero General Public License as published by
|
||||
~ the Free Software Foundation, either version 3 of the License, or (at
|
||||
~ your option) any later version.
|
||||
~
|
||||
~ Bisq is distributed in the hope that it will be useful, but WITHOUT
|
||||
~ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
~ FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
~ License for more details.
|
||||
~
|
||||
~ You should have received a copy of the GNU Affero General Public License
|
||||
~ along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<?import javafx.scene.layout.AnchorPane?>
|
||||
<?import javafx.scene.layout.ColumnConstraints?>
|
||||
<?import javafx.scene.layout.GridPane?>
|
||||
<GridPane fx:id="root" fx:controller="bisq.desktop.main.dao.economy.supply.SupplyView"
|
||||
hgap="5.0" vgap="5.0"
|
||||
AnchorPane.bottomAnchor="20.0" AnchorPane.leftAnchor="20.0"
|
||||
AnchorPane.rightAnchor="25.0" AnchorPane.topAnchor="20.0"
|
||||
xmlns:fx="http://javafx.com/fxml">
|
||||
<columnConstraints>
|
||||
<ColumnConstraints percentWidth="50"/>
|
||||
<ColumnConstraints percentWidth="50"/>
|
||||
</columnConstraints>
|
||||
</GridPane>
|
|
@ -0,0 +1,335 @@
|
|||
/*
|
||||
* This file is part of Bisq.
|
||||
*
|
||||
* Bisq is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bisq is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package bisq.desktop.main.dao.economy.supply;
|
||||
|
||||
import bisq.desktop.common.view.ActivatableView;
|
||||
import bisq.desktop.common.view.FxmlView;
|
||||
import bisq.desktop.components.TitledGroupBg;
|
||||
import bisq.desktop.util.Layout;
|
||||
|
||||
import bisq.core.dao.DaoFacade;
|
||||
import bisq.core.dao.state.DaoStateListener;
|
||||
import bisq.core.dao.state.DaoStateService;
|
||||
import bisq.core.dao.state.model.blockchain.Block;
|
||||
import bisq.core.dao.state.model.blockchain.Tx;
|
||||
import bisq.core.dao.state.model.governance.Issuance;
|
||||
import bisq.core.dao.state.model.governance.IssuanceType;
|
||||
import bisq.core.locale.GlobalSettings;
|
||||
import bisq.core.locale.Res;
|
||||
import bisq.core.util.BsqFormatter;
|
||||
|
||||
import bisq.common.util.Tuple3;
|
||||
|
||||
import org.bitcoinj.core.Coin;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import javafx.scene.chart.AreaChart;
|
||||
import javafx.scene.chart.NumberAxis;
|
||||
import javafx.scene.chart.XYChart;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.layout.AnchorPane;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.layout.VBox;
|
||||
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Side;
|
||||
|
||||
import javafx.util.StringConverter;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.TemporalAdjuster;
|
||||
import java.time.temporal.TemporalAdjusters;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static bisq.desktop.util.FormBuilder.addTitledGroupBg;
|
||||
import static bisq.desktop.util.FormBuilder.addTopLabelReadOnlyTextField;
|
||||
|
||||
|
||||
|
||||
import java.sql.Date;
|
||||
|
||||
@FxmlView
|
||||
public class SupplyView extends ActivatableView<GridPane, Void> implements DaoStateListener {
|
||||
|
||||
private static final String MONTH = "month";
|
||||
|
||||
private final DaoFacade daoFacade;
|
||||
private DaoStateService daoStateService;
|
||||
private final BsqFormatter bsqFormatter;
|
||||
|
||||
private int gridRow = 0;
|
||||
private TextField genesisIssueAmountTextField, compRequestIssueAmountTextField, reimbursementAmountTextField,
|
||||
burntAmountTextField, totalLockedUpAmountTextField, totalUnlockingAmountTextField,
|
||||
totalUnlockedAmountTextField, totalConfiscatedAmountTextField;
|
||||
private XYChart.Series<Number, Number> seriesBSQIssued, seriesBSQBurnt;
|
||||
|
||||
private static final Map<String, TemporalAdjuster> ADJUSTERS = new HashMap<>();
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor, lifecycle
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Inject
|
||||
private SupplyView(DaoFacade daoFacade,
|
||||
DaoStateService daoStateService,
|
||||
BsqFormatter bsqFormatter) {
|
||||
this.daoFacade = daoFacade;
|
||||
this.daoStateService = daoStateService;
|
||||
this.bsqFormatter = bsqFormatter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
|
||||
ADJUSTERS.put(MONTH, TemporalAdjusters.firstDayOfMonth());
|
||||
|
||||
createSupplyIncreasedInformation();
|
||||
createSupplyReducedInformation();
|
||||
createSupplyLockedInformation();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void activate() {
|
||||
daoFacade.addBsqStateListener(this);
|
||||
|
||||
updateWithBsqBlockChainData();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void deactivate() {
|
||||
daoFacade.removeBsqStateListener(this);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// DaoStateListener
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void onParseBlockCompleteAfterBatchProcessing(Block block) {
|
||||
updateWithBsqBlockChainData();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Private
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void createSupplyIncreasedInformation() {
|
||||
addTitledGroupBg(root, ++gridRow, 3, Res.get("dao.factsAndFigures.supply.issued"));
|
||||
|
||||
Tuple3<Label, TextField, VBox> genesisAmountTuple = addTopLabelReadOnlyTextField(root, gridRow,
|
||||
Res.get("dao.factsAndFigures.supply.genesisIssueAmount"), Layout.FIRST_ROW_DISTANCE);
|
||||
genesisIssueAmountTextField = genesisAmountTuple.second;
|
||||
GridPane.setColumnSpan(genesisAmountTuple.third, 2);
|
||||
|
||||
compRequestIssueAmountTextField = addTopLabelReadOnlyTextField(root, ++gridRow,
|
||||
Res.get("dao.factsAndFigures.supply.compRequestIssueAmount")).second;
|
||||
reimbursementAmountTextField = addTopLabelReadOnlyTextField(root, gridRow, 1,
|
||||
Res.get("dao.factsAndFigures.supply.reimbursementAmount")).second;
|
||||
|
||||
|
||||
seriesBSQIssued = new XYChart.Series<>();
|
||||
createChart(seriesBSQIssued, Res.get("dao.factsAndFigures.supply.issued"));
|
||||
}
|
||||
|
||||
private void createSupplyReducedInformation() {
|
||||
addTitledGroupBg(root, ++gridRow, 2, Res.get("dao.factsAndFigures.supply.burnt"), Layout.GROUP_DISTANCE);
|
||||
|
||||
Tuple3<Label, TextField, VBox> burntAmountTuple = addTopLabelReadOnlyTextField(root, gridRow,
|
||||
Res.get("dao.factsAndFigures.supply.burntAmount"), Layout.FIRST_ROW_AND_GROUP_DISTANCE);
|
||||
burntAmountTextField = burntAmountTuple.second;
|
||||
|
||||
GridPane.setColumnSpan(burntAmountTuple.third, 2);
|
||||
|
||||
seriesBSQBurnt = new XYChart.Series<>();
|
||||
createChart(seriesBSQBurnt, Res.get("dao.factsAndFigures.supply.burnt"));
|
||||
}
|
||||
|
||||
private void createSupplyLockedInformation() {
|
||||
TitledGroupBg titledGroupBg = addTitledGroupBg(root, ++gridRow, 2, Res.get("dao.factsAndFigures.supply.locked"), Layout.GROUP_DISTANCE);
|
||||
titledGroupBg.getStyleClass().add("last");
|
||||
|
||||
totalLockedUpAmountTextField = addTopLabelReadOnlyTextField(root, gridRow,
|
||||
Res.get("dao.factsAndFigures.supply.totalLockedUpAmount"),
|
||||
Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
||||
totalUnlockingAmountTextField = addTopLabelReadOnlyTextField(root, gridRow, 1,
|
||||
Res.get("dao.factsAndFigures.supply.totalUnlockingAmount"),
|
||||
Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
||||
|
||||
totalUnlockedAmountTextField = addTopLabelReadOnlyTextField(root, ++gridRow,
|
||||
Res.get("dao.factsAndFigures.supply.totalUnlockedAmount")).second;
|
||||
totalConfiscatedAmountTextField = addTopLabelReadOnlyTextField(root, gridRow, 1,
|
||||
Res.get("dao.factsAndFigures.supply.totalConfiscatedAmount")).second;
|
||||
|
||||
}
|
||||
|
||||
private void createChart(XYChart.Series<Number, Number> series, String seriesLabel) {
|
||||
NumberAxis xAxis = new NumberAxis();
|
||||
xAxis.setForceZeroInRange(false);
|
||||
xAxis.setAutoRanging(true);
|
||||
xAxis.setTickLabelGap(6);
|
||||
xAxis.setTickMarkVisible(false);
|
||||
xAxis.setMinorTickVisible(false);
|
||||
xAxis.setTickLabelFormatter(new StringConverter<>() {
|
||||
@Override
|
||||
public String toString(Number timestamp) {
|
||||
LocalDateTime localDateTime = LocalDateTime.ofEpochSecond(timestamp.longValue(),
|
||||
0, OffsetDateTime.now(ZoneId.systemDefault()).getOffset());
|
||||
return localDateTime.format(DateTimeFormatter.ofPattern("MMM uu", GlobalSettings.getLocale()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Number fromString(String string) {
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
|
||||
NumberAxis yAxis = new NumberAxis();
|
||||
yAxis.setForceZeroInRange(false);
|
||||
yAxis.setSide(Side.RIGHT);
|
||||
yAxis.setAutoRanging(true);
|
||||
yAxis.setTickMarkVisible(false);
|
||||
yAxis.setMinorTickVisible(false);
|
||||
yAxis.setTickLabelGap(5);
|
||||
yAxis.setTickLabelFormatter(new StringConverter<>() {
|
||||
@Override
|
||||
public String toString(Number marketPrice) {
|
||||
return bsqFormatter.formatBSQSatoshisWithCode(marketPrice.longValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Number fromString(String string) {
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
|
||||
series.setName(seriesLabel);
|
||||
|
||||
AreaChart<Number, Number> chart = new AreaChart<>(xAxis, yAxis);
|
||||
chart.setLegendVisible(false);
|
||||
chart.setAnimated(false);
|
||||
chart.setId("charts-dao");
|
||||
chart.setMinHeight(250);
|
||||
chart.setPrefHeight(250);
|
||||
chart.setCreateSymbols(true);
|
||||
chart.setPadding(new Insets(0));
|
||||
chart.getData().addAll(series);
|
||||
|
||||
AnchorPane chartPane = new AnchorPane();
|
||||
chartPane.getStyleClass().add("chart-pane");
|
||||
|
||||
AnchorPane.setTopAnchor(chart, 15d);
|
||||
AnchorPane.setBottomAnchor(chart, 10d);
|
||||
AnchorPane.setLeftAnchor(chart, 25d);
|
||||
AnchorPane.setRightAnchor(chart, 10d);
|
||||
|
||||
chartPane.getChildren().add(chart);
|
||||
|
||||
GridPane.setColumnSpan(chartPane, 2);
|
||||
GridPane.setRowIndex(chartPane, ++gridRow);
|
||||
GridPane.setMargin(chartPane, new Insets(10, 0, 0, 0));
|
||||
|
||||
root.getChildren().add(chartPane);
|
||||
}
|
||||
|
||||
private void updateWithBsqBlockChainData() {
|
||||
Coin issuedAmountFromGenesis = daoFacade.getGenesisTotalSupply();
|
||||
genesisIssueAmountTextField.setText(bsqFormatter.formatAmountWithGroupSeparatorAndCode(issuedAmountFromGenesis));
|
||||
|
||||
Coin issuedAmountFromCompRequests = Coin.valueOf(daoFacade.getTotalIssuedAmount(IssuanceType.COMPENSATION));
|
||||
compRequestIssueAmountTextField.setText(bsqFormatter.formatAmountWithGroupSeparatorAndCode(issuedAmountFromCompRequests));
|
||||
Coin issuedAmountFromReimbursementRequests = Coin.valueOf(daoFacade.getTotalIssuedAmount(IssuanceType.REIMBURSEMENT));
|
||||
reimbursementAmountTextField.setText(bsqFormatter.formatAmountWithGroupSeparatorAndCode(issuedAmountFromReimbursementRequests));
|
||||
|
||||
Coin burntFee = Coin.valueOf(daoFacade.getTotalBurntFee());
|
||||
Coin totalLockedUpAmount = Coin.valueOf(daoFacade.getTotalLockupAmount());
|
||||
Coin totalUnlockingAmount = Coin.valueOf(daoFacade.getTotalAmountOfUnLockingTxOutputs());
|
||||
Coin totalUnlockedAmount = Coin.valueOf(daoFacade.getTotalAmountOfUnLockedTxOutputs());
|
||||
Coin totalConfiscatedAmount = Coin.valueOf(daoFacade.getTotalAmountOfConfiscatedTxOutputs());
|
||||
|
||||
burntAmountTextField.setText("-" + bsqFormatter.formatAmountWithGroupSeparatorAndCode(burntFee));
|
||||
totalLockedUpAmountTextField.setText(bsqFormatter.formatAmountWithGroupSeparatorAndCode(totalLockedUpAmount));
|
||||
totalUnlockingAmountTextField.setText(bsqFormatter.formatAmountWithGroupSeparatorAndCode(totalUnlockingAmount));
|
||||
totalUnlockedAmountTextField.setText(bsqFormatter.formatAmountWithGroupSeparatorAndCode(totalUnlockedAmount));
|
||||
totalConfiscatedAmountTextField.setText(bsqFormatter.formatAmountWithGroupSeparatorAndCode(totalConfiscatedAmount));
|
||||
|
||||
updateCharts();
|
||||
}
|
||||
|
||||
private void updateCharts() {
|
||||
seriesBSQIssued.getData().clear();
|
||||
seriesBSQBurnt.getData().clear();
|
||||
|
||||
Map<LocalDate, List<Tx>> feesBurntByMonth = daoStateService.getBurntFeeTxs().stream()
|
||||
.sorted(Comparator.comparing(Tx::getTime))
|
||||
.collect(Collectors.groupingBy(item -> new Date(item.getTime()).toLocalDate()
|
||||
.with(ADJUSTERS.get(MONTH))));
|
||||
|
||||
List<XYChart.Data<Number, Number>> updatedBurntBSQ = feesBurntByMonth.keySet().stream()
|
||||
.map(date -> {
|
||||
ZonedDateTime zonedDateTime = date.atStartOfDay(ZoneId.systemDefault());
|
||||
return new XYChart.Data<Number, Number>(zonedDateTime.toInstant().getEpochSecond(), feesBurntByMonth.get(date)
|
||||
.stream()
|
||||
.mapToDouble(Tx::getBurntFee)
|
||||
.sum()
|
||||
);
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
|
||||
seriesBSQBurnt.getData().setAll(updatedBurntBSQ);
|
||||
|
||||
Stream<Issuance> bsqByCompensation = daoStateService.getIssuanceSet(IssuanceType.COMPENSATION).stream()
|
||||
.sorted(Comparator.comparing(Issuance::getChainHeight));
|
||||
|
||||
Stream<Issuance> bsqByReImbursement = daoStateService.getIssuanceSet(IssuanceType.REIMBURSEMENT).stream()
|
||||
.sorted(Comparator.comparing(Issuance::getChainHeight));
|
||||
|
||||
Map<LocalDate, List<Issuance>> bsqAddedByVote = Stream.concat(bsqByCompensation, bsqByReImbursement)
|
||||
.collect(Collectors.groupingBy(item -> new Date(daoFacade.getBlockTime(item.getChainHeight())).toLocalDate()
|
||||
.with(ADJUSTERS.get(MONTH))));
|
||||
|
||||
List<XYChart.Data<Number, Number>> updatedAddedBSQ = bsqAddedByVote.keySet().stream()
|
||||
.map(date -> {
|
||||
ZonedDateTime zonedDateTime = date.atStartOfDay(ZoneId.systemDefault());
|
||||
return new XYChart.Data<Number, Number>(zonedDateTime.toInstant().getEpochSecond(), bsqAddedByVote.get(date)
|
||||
.stream()
|
||||
.mapToDouble(Issuance::getAmount)
|
||||
.sum());
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
|
||||
seriesBSQIssued.getData().setAll(updatedAddedBSQ);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!--
|
||||
~ This file is part of Bisq.
|
||||
~
|
||||
~ Bisq is free software: you can redistribute it and/or modify it
|
||||
~ under the terms of the GNU Affero General Public License as published by
|
||||
~ the Free Software Foundation, either version 3 of the License, or (at
|
||||
~ your option) any later version.
|
||||
~
|
||||
~ Bisq is distributed in the hope that it will be useful, but WITHOUT
|
||||
~ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
~ FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
~ License for more details.
|
||||
~
|
||||
~ You should have received a copy of the GNU Affero General Public License
|
||||
~ along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<?import javafx.scene.layout.AnchorPane?>
|
||||
<?import javafx.scene.layout.ColumnConstraints?>
|
||||
<?import javafx.scene.layout.GridPane?>
|
||||
<GridPane fx:id="root" fx:controller="bisq.desktop.main.dao.economy.transactions.BSQTransactionsView"
|
||||
hgap="5.0" vgap="5.0"
|
||||
AnchorPane.bottomAnchor="20.0" AnchorPane.leftAnchor="20.0"
|
||||
AnchorPane.rightAnchor="25.0" AnchorPane.topAnchor="20.0"
|
||||
xmlns:fx="http://javafx.com/fxml">
|
||||
<columnConstraints>
|
||||
<ColumnConstraints percentWidth="50"/>
|
||||
<ColumnConstraints percentWidth="50"/>
|
||||
</columnConstraints>
|
||||
</GridPane>
|
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* This file is part of Bisq.
|
||||
*
|
||||
* Bisq is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bisq is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package bisq.desktop.main.dao.economy.transactions;
|
||||
|
||||
import bisq.desktop.common.view.ActivatableView;
|
||||
import bisq.desktop.common.view.FxmlView;
|
||||
import bisq.desktop.components.HyperlinkWithIcon;
|
||||
import bisq.desktop.components.TitledGroupBg;
|
||||
import bisq.desktop.util.Layout;
|
||||
|
||||
import bisq.core.dao.DaoFacade;
|
||||
import bisq.core.dao.state.DaoStateListener;
|
||||
import bisq.core.dao.state.model.blockchain.Block;
|
||||
import bisq.core.dao.state.model.governance.IssuanceType;
|
||||
import bisq.core.locale.Res;
|
||||
import bisq.core.user.Preferences;
|
||||
|
||||
import bisq.common.util.Tuple3;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.control.Tooltip;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.layout.VBox;
|
||||
|
||||
import static bisq.desktop.util.FormBuilder.addTitledGroupBg;
|
||||
import static bisq.desktop.util.FormBuilder.addTopLabelHyperlinkWithIcon;
|
||||
import static bisq.desktop.util.FormBuilder.addTopLabelReadOnlyTextField;
|
||||
|
||||
@FxmlView
|
||||
public class BSQTransactionsView extends ActivatableView<GridPane, Void> implements DaoStateListener {
|
||||
|
||||
private final DaoFacade daoFacade;
|
||||
private final Preferences preferences;
|
||||
|
||||
private int gridRow = 0;
|
||||
private TextField allTxTextField, burntTxTextField,
|
||||
utxoTextField, compensationIssuanceTxTextField,
|
||||
reimbursementIssuanceTxTextField;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor, lifecycle
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Inject
|
||||
private BSQTransactionsView(DaoFacade daoFacade,
|
||||
Preferences preferences) {
|
||||
this.daoFacade = daoFacade;
|
||||
this.preferences = preferences;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
addTitledGroupBg(root, gridRow, 2, Res.get("dao.factsAndFigures.transactions.genesis"));
|
||||
String genTxHeight = String.valueOf(daoFacade.getGenesisBlockHeight());
|
||||
String genesisTxId = daoFacade.getGenesisTxId();
|
||||
String url = preferences.getBsqBlockChainExplorer().txUrl + genesisTxId;
|
||||
|
||||
GridPane.setColumnSpan(addTopLabelReadOnlyTextField(root, gridRow, Res.get("dao.factsAndFigures.transactions.genesisBlockHeight"),
|
||||
genTxHeight, Layout.FIRST_ROW_DISTANCE).third, 2);
|
||||
|
||||
// TODO use addTopLabelTxIdTextField
|
||||
Tuple3<Label, HyperlinkWithIcon, VBox> tuple = addTopLabelHyperlinkWithIcon(root, ++gridRow,
|
||||
Res.get("dao.factsAndFigures.transactions.genesisTxId"), genesisTxId, url, 0);
|
||||
HyperlinkWithIcon hyperlinkWithIcon = tuple.second;
|
||||
hyperlinkWithIcon.setTooltip(new Tooltip(Res.get("tooltip.openBlockchainForTx", genesisTxId)));
|
||||
|
||||
GridPane.setColumnSpan(tuple.third, 2);
|
||||
|
||||
|
||||
int startRow = ++gridRow;
|
||||
|
||||
TitledGroupBg titledGroupBg = addTitledGroupBg(root, gridRow, 3, Res.get("dao.factsAndFigures.transactions.txDetails"), Layout.GROUP_DISTANCE);
|
||||
titledGroupBg.getStyleClass().add("last");
|
||||
|
||||
allTxTextField = addTopLabelReadOnlyTextField(root, gridRow, Res.get("dao.factsAndFigures.transactions.allTx"),
|
||||
genTxHeight, Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
||||
utxoTextField = addTopLabelReadOnlyTextField(root, ++gridRow, Res.get("dao.factsAndFigures.transactions.utxo")).second;
|
||||
compensationIssuanceTxTextField = addTopLabelReadOnlyTextField(root, ++gridRow,
|
||||
Res.get("dao.factsAndFigures.transactions.compensationIssuanceTx")).second;
|
||||
|
||||
int columnIndex = 1;
|
||||
|
||||
gridRow = startRow;
|
||||
|
||||
titledGroupBg = addTitledGroupBg(root, startRow, columnIndex, 3, "", Layout.GROUP_DISTANCE);
|
||||
titledGroupBg.getStyleClass().add("last");
|
||||
|
||||
reimbursementIssuanceTxTextField = addTopLabelReadOnlyTextField(root, gridRow, columnIndex,
|
||||
Res.get("dao.factsAndFigures.transactions.reimbursementIssuanceTx"),
|
||||
Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
||||
burntTxTextField = addTopLabelReadOnlyTextField(root, ++gridRow, columnIndex,
|
||||
Res.get("dao.factsAndFigures.transactions.burntTx")).second;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void activate() {
|
||||
daoFacade.addBsqStateListener(this);
|
||||
|
||||
updateWithBsqBlockChainData();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void deactivate() {
|
||||
daoFacade.removeBsqStateListener(this);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// DaoStateListener
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void onParseBlockCompleteAfterBatchProcessing(Block block) {
|
||||
updateWithBsqBlockChainData();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Private
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void updateWithBsqBlockChainData() {
|
||||
allTxTextField.setText(String.valueOf(daoFacade.getTxs().size()));
|
||||
utxoTextField.setText(String.valueOf(daoFacade.getUnspentTxOutputs().size()));
|
||||
compensationIssuanceTxTextField.setText(String.valueOf(daoFacade.getNumIssuanceTransactions(IssuanceType.COMPENSATION)));
|
||||
reimbursementIssuanceTxTextField.setText(String.valueOf(daoFacade.getNumIssuanceTransactions(IssuanceType.REIMBURSEMENT)));
|
||||
burntTxTextField.setText(String.valueOf(daoFacade.getFeeTxs().size()));
|
||||
}
|
||||
}
|
||||
|
|
@ -27,7 +27,6 @@ import bisq.desktop.common.view.ViewPath;
|
|||
import bisq.desktop.components.MenuItem;
|
||||
import bisq.desktop.main.MainView;
|
||||
import bisq.desktop.main.dao.DaoView;
|
||||
import bisq.desktop.main.dao.wallet.dashboard.BsqDashboardView;
|
||||
import bisq.desktop.main.dao.wallet.receive.BsqReceiveView;
|
||||
import bisq.desktop.main.dao.wallet.send.BsqSendView;
|
||||
import bisq.desktop.main.dao.wallet.tx.BsqTxView;
|
||||
|
@ -53,7 +52,7 @@ public class BsqWalletView extends ActivatableViewAndModel {
|
|||
private final ViewLoader viewLoader;
|
||||
private final Navigation navigation;
|
||||
|
||||
private MenuItem dashboard, send, receive, transactions;
|
||||
private MenuItem send, receive, transactions;
|
||||
private Navigation.Listener listener;
|
||||
|
||||
@FXML
|
||||
|
@ -82,15 +81,13 @@ public class BsqWalletView extends ActivatableViewAndModel {
|
|||
|
||||
toggleGroup = new ToggleGroup();
|
||||
List<Class<? extends View>> baseNavPath = Arrays.asList(MainView.class, DaoView.class, BsqWalletView.class);
|
||||
dashboard = new MenuItem(navigation, toggleGroup, Res.get("shared.dashboard"), BsqDashboardView.class, baseNavPath);
|
||||
send = new MenuItem(navigation, toggleGroup, Res.get("dao.wallet.menuItem.send"), BsqSendView.class, baseNavPath);
|
||||
receive = new MenuItem(navigation, toggleGroup, Res.get("dao.wallet.menuItem.receive"), BsqReceiveView.class, baseNavPath);
|
||||
transactions = new MenuItem(navigation, toggleGroup, Res.get("dao.wallet.menuItem.transactions"), BsqTxView.class, baseNavPath);
|
||||
leftVBox.getChildren().addAll(dashboard, send, receive, transactions);
|
||||
leftVBox.getChildren().addAll(send, receive, transactions);
|
||||
|
||||
// TODO just until DAO is enabled
|
||||
if (!DevEnv.isDaoActivated()) {
|
||||
dashboard.setDisable(true);
|
||||
send.setDisable(true);
|
||||
transactions.setDisable(true);
|
||||
}
|
||||
|
@ -98,7 +95,6 @@ public class BsqWalletView extends ActivatableViewAndModel {
|
|||
|
||||
@Override
|
||||
protected void activate() {
|
||||
dashboard.activate();
|
||||
send.activate();
|
||||
receive.activate();
|
||||
transactions.activate();
|
||||
|
@ -108,7 +104,7 @@ public class BsqWalletView extends ActivatableViewAndModel {
|
|||
if (viewPath.size() == 3 && viewPath.indexOf(BsqWalletView.class) == 2 ||
|
||||
viewPath.size() == 2 && viewPath.indexOf(DaoView.class) == 1) {
|
||||
if (selectedViewClass == null)
|
||||
selectedViewClass = BsqDashboardView.class;
|
||||
selectedViewClass = BsqSendView.class;
|
||||
|
||||
// TODO just until DAO is enabled
|
||||
if (!DevEnv.isDaoActivated())
|
||||
|
@ -126,7 +122,6 @@ public class BsqWalletView extends ActivatableViewAndModel {
|
|||
protected void deactivate() {
|
||||
navigation.removeListener(listener);
|
||||
|
||||
dashboard.deactivate();
|
||||
send.deactivate();
|
||||
receive.deactivate();
|
||||
transactions.deactivate();
|
||||
|
@ -136,8 +131,7 @@ public class BsqWalletView extends ActivatableViewAndModel {
|
|||
View view = viewLoader.load(viewClass);
|
||||
content.getChildren().setAll(view.getRoot());
|
||||
|
||||
if (view instanceof BsqDashboardView) toggleGroup.selectToggle(dashboard);
|
||||
else if (view instanceof BsqSendView) toggleGroup.selectToggle(send);
|
||||
if (view instanceof BsqSendView) toggleGroup.selectToggle(send);
|
||||
else if (view instanceof BsqReceiveView) toggleGroup.selectToggle(receive);
|
||||
else if (view instanceof BsqTxView) toggleGroup.selectToggle(transactions);
|
||||
}
|
||||
|
|
|
@ -1,236 +0,0 @@
|
|||
/*
|
||||
* This file is part of Bisq.
|
||||
*
|
||||
* Bisq is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bisq is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package bisq.desktop.main.dao.wallet.dashboard;
|
||||
|
||||
import bisq.desktop.common.view.ActivatableView;
|
||||
import bisq.desktop.common.view.FxmlView;
|
||||
import bisq.desktop.components.HyperlinkWithIcon;
|
||||
import bisq.desktop.components.TitledGroupBg;
|
||||
import bisq.desktop.main.dao.wallet.BsqBalanceUtil;
|
||||
import bisq.desktop.util.FormBuilder;
|
||||
import bisq.desktop.util.Layout;
|
||||
|
||||
import bisq.core.dao.DaoFacade;
|
||||
import bisq.core.dao.state.DaoStateListener;
|
||||
import bisq.core.dao.state.model.blockchain.Block;
|
||||
import bisq.core.dao.state.model.governance.IssuanceType;
|
||||
import bisq.core.locale.Res;
|
||||
import bisq.core.monetary.Price;
|
||||
import bisq.core.provider.price.PriceFeedService;
|
||||
import bisq.core.user.Preferences;
|
||||
import bisq.core.util.BsqFormatter;
|
||||
|
||||
import bisq.common.util.Tuple3;
|
||||
|
||||
import org.bitcoinj.core.Coin;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.control.Tooltip;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.layout.VBox;
|
||||
|
||||
import javafx.beans.value.ChangeListener;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import static bisq.desktop.util.FormBuilder.addTitledGroupBg;
|
||||
import static bisq.desktop.util.FormBuilder.addTopLabelReadOnlyTextField;
|
||||
|
||||
@FxmlView
|
||||
public class BsqDashboardView extends ActivatableView<GridPane, Void> implements DaoStateListener {
|
||||
|
||||
private final BsqBalanceUtil bsqBalanceUtil;
|
||||
private final DaoFacade daoFacade;
|
||||
private final PriceFeedService priceFeedService;
|
||||
private final Preferences preferences;
|
||||
private final BsqFormatter bsqFormatter;
|
||||
|
||||
private int gridRow = 0;
|
||||
private TextField genesisIssueAmountTextField, compRequestIssueAmountTextField, reimbursementAmountTextField, availableAmountTextField,
|
||||
burntAmountTextField, totalLockedUpAmountTextField, totalUnlockingAmountTextField,
|
||||
totalUnlockedAmountTextField, totalConfiscatedAmountTextField, allTxTextField, burntTxTextField,
|
||||
utxoTextField, compensationIssuanceTxTextField,
|
||||
reimbursementIssuanceTxTextField, priceTextField, marketCapTextField;
|
||||
private ChangeListener<Number> priceChangeListener;
|
||||
private Coin availableAmount;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor, lifecycle
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Inject
|
||||
private BsqDashboardView(BsqBalanceUtil bsqBalanceUtil,
|
||||
DaoFacade daoFacade,
|
||||
PriceFeedService priceFeedService,
|
||||
Preferences preferences,
|
||||
BsqFormatter bsqFormatter) {
|
||||
this.bsqBalanceUtil = bsqBalanceUtil;
|
||||
this.daoFacade = daoFacade;
|
||||
this.priceFeedService = priceFeedService;
|
||||
this.preferences = preferences;
|
||||
this.bsqFormatter = bsqFormatter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
gridRow = bsqBalanceUtil.addGroup(root, gridRow);
|
||||
int columnIndex = 2;
|
||||
|
||||
int startRow = gridRow;
|
||||
addTitledGroupBg(root, ++gridRow, 5, Res.get("dao.wallet.dashboard.distribution"), Layout.GROUP_DISTANCE);
|
||||
genesisIssueAmountTextField = addTopLabelReadOnlyTextField(root, gridRow, Res.get("dao.wallet.dashboard.genesisIssueAmount"), Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
||||
compRequestIssueAmountTextField = addTopLabelReadOnlyTextField(root, ++gridRow, Res.get("dao.wallet.dashboard.compRequestIssueAmount")).second;
|
||||
reimbursementAmountTextField = addTopLabelReadOnlyTextField(root, ++gridRow, Res.get("dao.wallet.dashboard.reimbursementAmount")).second;
|
||||
burntAmountTextField = addTopLabelReadOnlyTextField(root, ++gridRow, Res.get("dao.wallet.dashboard.burntAmount")).second;
|
||||
availableAmountTextField = addTopLabelReadOnlyTextField(root, ++gridRow, Res.get("dao.wallet.dashboard.availableAmount")).second;
|
||||
|
||||
gridRow = startRow;
|
||||
addTitledGroupBg(root, ++gridRow, columnIndex, 5, Res.get("dao.wallet.dashboard.locked"), Layout.GROUP_DISTANCE);
|
||||
totalLockedUpAmountTextField = addTopLabelReadOnlyTextField(root, gridRow, columnIndex, Res.get("dao.wallet.dashboard.totalLockedUpAmount"), Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
||||
totalUnlockingAmountTextField = addTopLabelReadOnlyTextField(root, ++gridRow, columnIndex, Res.get("dao.wallet.dashboard.totalUnlockingAmount")).second;
|
||||
totalUnlockedAmountTextField = addTopLabelReadOnlyTextField(root, ++gridRow, columnIndex, Res.get("dao.wallet.dashboard.totalUnlockedAmount")).second;
|
||||
totalConfiscatedAmountTextField = addTopLabelReadOnlyTextField(root, ++gridRow, columnIndex, Res.get("dao.wallet.dashboard.totalConfiscatedAmount")).second;
|
||||
gridRow++;
|
||||
|
||||
startRow = gridRow;
|
||||
addTitledGroupBg(root, ++gridRow, 2, Res.get("dao.wallet.dashboard.market"), Layout.GROUP_DISTANCE);
|
||||
priceTextField = addTopLabelReadOnlyTextField(root, gridRow, Res.get("dao.wallet.dashboard.price"), Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
||||
marketCapTextField = addTopLabelReadOnlyTextField(root, ++gridRow, Res.get("dao.wallet.dashboard.marketCap")).second;
|
||||
|
||||
gridRow = startRow;
|
||||
addTitledGroupBg(root, ++gridRow, columnIndex, 2, Res.get("dao.wallet.dashboard.genesis"), Layout.GROUP_DISTANCE);
|
||||
String genTxHeight = String.valueOf(daoFacade.getGenesisBlockHeight());
|
||||
String genesisTxId = daoFacade.getGenesisTxId();
|
||||
String url = preferences.getBsqBlockChainExplorer().txUrl + genesisTxId;
|
||||
addTopLabelReadOnlyTextField(root, gridRow, columnIndex, Res.get("dao.wallet.dashboard.genesisBlockHeight"),
|
||||
genTxHeight, Layout.FIRST_ROW_AND_GROUP_DISTANCE);
|
||||
|
||||
// TODO use addTopLabelTxIdTextField
|
||||
Tuple3<Label, HyperlinkWithIcon, VBox> tuple = FormBuilder.addTopLabelHyperlinkWithIcon(root, ++gridRow, columnIndex,
|
||||
Res.get("dao.wallet.dashboard.genesisTxId"), genesisTxId, url, 0);
|
||||
HyperlinkWithIcon hyperlinkWithIcon = tuple.second;
|
||||
hyperlinkWithIcon.setTooltip(new Tooltip(Res.get("tooltip.openBlockchainForTx", genesisTxId)));
|
||||
|
||||
startRow = gridRow;
|
||||
TitledGroupBg titledGroupBgTxDetails = addTitledGroupBg(root, ++gridRow, 3, Res.get("dao.wallet.dashboard.txDetails"), Layout.GROUP_DISTANCE);
|
||||
titledGroupBgTxDetails.getStyleClass().add("last");
|
||||
allTxTextField = addTopLabelReadOnlyTextField(root, gridRow, Res.get("dao.wallet.dashboard.allTx"),
|
||||
genTxHeight, Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
||||
utxoTextField = addTopLabelReadOnlyTextField(root, ++gridRow, Res.get("dao.wallet.dashboard.utxo")).second;
|
||||
compensationIssuanceTxTextField = addTopLabelReadOnlyTextField(root, ++gridRow,
|
||||
Res.get("dao.wallet.dashboard.compensationIssuanceTx")).second;
|
||||
|
||||
gridRow = startRow;
|
||||
TitledGroupBg titledGroupBgReImbursement = addTitledGroupBg(root, ++gridRow, columnIndex, 3, "", Layout.GROUP_DISTANCE);
|
||||
titledGroupBgReImbursement.getStyleClass().add("last");
|
||||
reimbursementIssuanceTxTextField = addTopLabelReadOnlyTextField(root, gridRow, columnIndex,
|
||||
Res.get("dao.wallet.dashboard.reimbursementIssuanceTx"),
|
||||
Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
||||
burntTxTextField = addTopLabelReadOnlyTextField(root, ++gridRow, columnIndex,
|
||||
Res.get("dao.wallet.dashboard.burntTx")).second;
|
||||
++gridRow;
|
||||
|
||||
priceChangeListener = (observable, oldValue, newValue) -> updatePrice();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void activate() {
|
||||
bsqBalanceUtil.activate();
|
||||
|
||||
daoFacade.addBsqStateListener(this);
|
||||
priceFeedService.updateCounterProperty().addListener(priceChangeListener);
|
||||
|
||||
updateWithBsqBlockChainData();
|
||||
updatePrice();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void deactivate() {
|
||||
bsqBalanceUtil.deactivate();
|
||||
daoFacade.removeBsqStateListener(this);
|
||||
priceFeedService.updateCounterProperty().removeListener(priceChangeListener);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// DaoStateListener
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void onParseBlockCompleteAfterBatchProcessing(Block block) {
|
||||
updateWithBsqBlockChainData();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Private
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void updateWithBsqBlockChainData() {
|
||||
Coin issuedAmountFromGenesis = daoFacade.getGenesisTotalSupply();
|
||||
genesisIssueAmountTextField.setText(bsqFormatter.formatAmountWithGroupSeparatorAndCode(issuedAmountFromGenesis));
|
||||
|
||||
Coin issuedAmountFromCompRequests = Coin.valueOf(daoFacade.getTotalIssuedAmount(IssuanceType.COMPENSATION));
|
||||
compRequestIssueAmountTextField.setText(bsqFormatter.formatAmountWithGroupSeparatorAndCode(issuedAmountFromCompRequests));
|
||||
Coin issuedAmountFromReimbursementRequests = Coin.valueOf(daoFacade.getTotalIssuedAmount(IssuanceType.REIMBURSEMENT));
|
||||
reimbursementAmountTextField.setText(bsqFormatter.formatAmountWithGroupSeparatorAndCode(issuedAmountFromReimbursementRequests));
|
||||
|
||||
Coin burntFee = Coin.valueOf(daoFacade.getTotalBurntFee());
|
||||
Coin totalLockedUpAmount = Coin.valueOf(daoFacade.getTotalLockupAmount());
|
||||
Coin totalUnlockingAmount = Coin.valueOf(daoFacade.getTotalAmountOfUnLockingTxOutputs());
|
||||
Coin totalUnlockedAmount = Coin.valueOf(daoFacade.getTotalAmountOfUnLockedTxOutputs());
|
||||
Coin totalConfiscatedAmount = Coin.valueOf(daoFacade.getTotalAmountOfConfiscatedTxOutputs());
|
||||
availableAmount = issuedAmountFromGenesis
|
||||
.add(issuedAmountFromCompRequests)
|
||||
.add(issuedAmountFromReimbursementRequests)
|
||||
.subtract(burntFee)
|
||||
.subtract(totalConfiscatedAmount);
|
||||
|
||||
availableAmountTextField.setText(bsqFormatter.formatAmountWithGroupSeparatorAndCode(availableAmount));
|
||||
burntAmountTextField.setText("-" + bsqFormatter.formatAmountWithGroupSeparatorAndCode(burntFee));
|
||||
totalLockedUpAmountTextField.setText(bsqFormatter.formatAmountWithGroupSeparatorAndCode(totalLockedUpAmount));
|
||||
totalUnlockingAmountTextField.setText(bsqFormatter.formatAmountWithGroupSeparatorAndCode(totalUnlockingAmount));
|
||||
totalUnlockedAmountTextField.setText(bsqFormatter.formatAmountWithGroupSeparatorAndCode(totalUnlockedAmount));
|
||||
totalConfiscatedAmountTextField.setText(bsqFormatter.formatAmountWithGroupSeparatorAndCode(totalConfiscatedAmount));
|
||||
allTxTextField.setText(String.valueOf(daoFacade.getTxs().size()));
|
||||
utxoTextField.setText(String.valueOf(daoFacade.getUnspentTxOutputs().size()));
|
||||
compensationIssuanceTxTextField.setText(String.valueOf(daoFacade.getNumIssuanceTransactions(IssuanceType.COMPENSATION)));
|
||||
reimbursementIssuanceTxTextField.setText(String.valueOf(daoFacade.getNumIssuanceTransactions(IssuanceType.REIMBURSEMENT)));
|
||||
burntTxTextField.setText(String.valueOf(daoFacade.getFeeTxs().size()));
|
||||
}
|
||||
|
||||
private void updatePrice() {
|
||||
Optional<Price> optionalBsqPrice = priceFeedService.getBsqPrice();
|
||||
if (optionalBsqPrice.isPresent()) {
|
||||
Price bsqPrice = optionalBsqPrice.get();
|
||||
priceTextField.setText(bsqFormatter.formatPrice(bsqPrice) + " BSQ/BTC");
|
||||
|
||||
marketCapTextField.setText(bsqFormatter.formatMarketCap(priceFeedService.getMarketPrice("BSQ"),
|
||||
priceFeedService.getMarketPrice(preferences.getPreferredTradeCurrency().getCode()),
|
||||
availableAmount));
|
||||
} else {
|
||||
priceTextField.setText(Res.get("shared.na"));
|
||||
marketCapTextField.setText(Res.get("shared.na"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -61,6 +61,7 @@ import javafx.scene.control.TableCell;
|
|||
import javafx.scene.control.TableColumn;
|
||||
import javafx.scene.control.TableView;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.layout.AnchorPane;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.Priority;
|
||||
import javafx.scene.layout.Region;
|
||||
|
@ -106,6 +107,7 @@ public class OfferBookChartView extends ActivatableViewAndModel<VBox, OfferBookC
|
|||
private TableView<OfferListItem> buyOfferTableView;
|
||||
private TableView<OfferListItem> sellOfferTableView;
|
||||
private AreaChart<Number, Number> areaChart;
|
||||
private AnchorPane chartPane;
|
||||
private ComboBox<CurrencyListItem> currencyComboBox;
|
||||
private Subscription tradeCurrencySubscriber;
|
||||
private final StringProperty volumeColumnLabel = new SimpleStringProperty();
|
||||
|
@ -154,6 +156,8 @@ public class OfferBookChartView extends ActivatableViewAndModel<VBox, OfferBookC
|
|||
|
||||
createChart();
|
||||
|
||||
VBox.setMargin(chartPane, new Insets(0, 0, 5, 0));
|
||||
|
||||
Tuple4<TableView<OfferListItem>, VBox, Button, Label> tupleBuy = getOfferTable(OfferPayload.Direction.BUY);
|
||||
Tuple4<TableView<OfferListItem>, VBox, Button, Label> tupleSell = getOfferTable(OfferPayload.Direction.SELL);
|
||||
buyOfferTableView = tupleBuy.first;
|
||||
|
@ -175,7 +179,8 @@ public class OfferBookChartView extends ActivatableViewAndModel<VBox, OfferBookC
|
|||
tupleSell.second.setUserData(OfferPayload.Direction.SELL.name());
|
||||
bottomHBox.getChildren().addAll(tupleBuy.second, tupleSell.second);
|
||||
|
||||
root.getChildren().addAll(currencyComboBoxTuple.first, areaChart, bottomHBox);
|
||||
|
||||
root.getChildren().addAll(currencyComboBoxTuple.first, chartPane, bottomHBox);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -334,11 +339,21 @@ public class OfferBookChartView extends ActivatableViewAndModel<VBox, OfferBookC
|
|||
areaChart.setLegendVisible(false);
|
||||
areaChart.setAnimated(false);
|
||||
areaChart.setId("charts");
|
||||
areaChart.setMinHeight(300);
|
||||
areaChart.setPrefHeight(300);
|
||||
areaChart.setCreateSymbols(false);
|
||||
areaChart.setMinHeight(270);
|
||||
areaChart.setPrefHeight(270);
|
||||
areaChart.setCreateSymbols(true);
|
||||
areaChart.setPadding(new Insets(0, 10, 0, 10));
|
||||
areaChart.getData().addAll(seriesBuy, seriesSell);
|
||||
|
||||
chartPane = new AnchorPane();
|
||||
chartPane.getStyleClass().add("chart-pane");
|
||||
|
||||
AnchorPane.setTopAnchor(areaChart, 15d);
|
||||
AnchorPane.setBottomAnchor(areaChart, 10d);
|
||||
AnchorPane.setLeftAnchor(areaChart, 10d);
|
||||
AnchorPane.setRightAnchor(areaChart, 0d);
|
||||
|
||||
chartPane.getChildren().add(areaChart);
|
||||
}
|
||||
|
||||
private void updateChartData() {
|
||||
|
|
|
@ -59,6 +59,7 @@ import javafx.scene.control.TableView;
|
|||
import javafx.scene.control.Toggle;
|
||||
import javafx.scene.control.ToggleButton;
|
||||
import javafx.scene.control.ToggleGroup;
|
||||
import javafx.scene.layout.AnchorPane;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.Pane;
|
||||
import javafx.scene.layout.Priority;
|
||||
|
@ -126,6 +127,7 @@ public class TradesChartsView extends ActivatableViewAndModel<VBox, TradesCharts
|
|||
private ChangeListener<Number> parentHeightListener;
|
||||
private Pane rootParent;
|
||||
private ChangeListener<String> priceColumnLabelListener;
|
||||
private AnchorPane priceChartPane, volumeChartPane;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -152,7 +154,7 @@ public class TradesChartsView extends ActivatableViewAndModel<VBox, TradesCharts
|
|||
nrOfTradeStatisticsLabel = new AutoTooltipLabel(" "); // set empty string for layout
|
||||
nrOfTradeStatisticsLabel.setId("num-offers");
|
||||
nrOfTradeStatisticsLabel.setPadding(new Insets(-5, 0, -10, 5));
|
||||
root.getChildren().addAll(toolBox, priceChart, volumeChart, tableView, nrOfTradeStatisticsLabel);
|
||||
root.getChildren().addAll(toolBox, priceChartPane, volumeChartPane, tableView, nrOfTradeStatisticsLabel);
|
||||
|
||||
timeUnitChangeListener = (observable, oldValue, newValue) -> {
|
||||
if (newValue != null) {
|
||||
|
@ -348,6 +350,15 @@ public class TradesChartsView extends ActivatableViewAndModel<VBox, TradesCharts
|
|||
//noinspection unchecked
|
||||
priceChart.setData(FXCollections.observableArrayList(priceSeries));
|
||||
|
||||
priceChartPane = new AnchorPane();
|
||||
priceChartPane.getStyleClass().add("chart-pane");
|
||||
|
||||
AnchorPane.setTopAnchor(priceChart, 15d);
|
||||
AnchorPane.setBottomAnchor(priceChart, 10d);
|
||||
AnchorPane.setLeftAnchor(priceChart, 0d);
|
||||
AnchorPane.setRightAnchor(priceChart, 10d);
|
||||
|
||||
priceChartPane.getChildren().add(priceChart);
|
||||
|
||||
volumeSeries = new XYChart.Series<>();
|
||||
|
||||
|
@ -392,6 +403,16 @@ public class TradesChartsView extends ActivatableViewAndModel<VBox, TradesCharts
|
|||
volumeChart.setMaxHeight(200);
|
||||
volumeChart.setLegendVisible(false);
|
||||
volumeChart.setPadding(new Insets(0));
|
||||
|
||||
volumeChartPane = new AnchorPane();
|
||||
volumeChartPane.getStyleClass().add("chart-pane");
|
||||
|
||||
AnchorPane.setTopAnchor(volumeChart, 15d);
|
||||
AnchorPane.setBottomAnchor(volumeChart, 10d);
|
||||
AnchorPane.setLeftAnchor(volumeChart, 0d);
|
||||
AnchorPane.setRightAnchor(volumeChart, 10d);
|
||||
|
||||
volumeChartPane.getChildren().add(volumeChart);
|
||||
}
|
||||
|
||||
private void updateChartData() {
|
||||
|
|
|
@ -141,6 +141,28 @@ public class FormBuilder {
|
|||
return label;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Label + Subtext
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public static Tuple3<Label, Label, VBox> addLabelWithSubText(GridPane gridPane, int rowIndex, String title, String description) {
|
||||
return addLabelWithSubText(gridPane, rowIndex, title, description, 0);
|
||||
}
|
||||
|
||||
public static Tuple3<Label, Label, VBox> addLabelWithSubText(GridPane gridPane, int rowIndex, String title, String description, double top) {
|
||||
Label label = new AutoTooltipLabel(title);
|
||||
Label subText = new AutoTooltipLabel(description);
|
||||
|
||||
VBox vBox = new VBox();
|
||||
vBox.getChildren().setAll(label, subText);
|
||||
|
||||
GridPane.setRowIndex(vBox, rowIndex);
|
||||
GridPane.setMargin(vBox, new Insets(top, 0, 0, 0));
|
||||
gridPane.getChildren().add(vBox);
|
||||
|
||||
return new Tuple3<>(label, subText, vBox);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Multiline Label
|
||||
|
|
Loading…
Add table
Reference in a new issue