Add time interval selector

This commit is contained in:
chimp1984 2021-02-05 19:08:40 -05:00
parent 9dab4fd65a
commit 67d76cda27
No known key found for this signature in database
GPG key ID: 9801B4EC591F90E3
9 changed files with 273 additions and 97 deletions

View file

@ -21,6 +21,8 @@ import bisq.desktop.common.model.ActivatableViewModel;
import bisq.common.util.Tuple2;
import java.time.temporal.TemporalAdjuster;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Predicate;
@ -28,7 +30,7 @@ import java.util.function.Predicate;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class ChartModel extends ActivatableViewModel {
public abstract class ChartModel extends ActivatableViewModel {
public interface Listener {
/**
* @param fromDate Epoch date in millis for earliest data
@ -40,9 +42,12 @@ public class ChartModel extends ActivatableViewModel {
protected Number lowerBound, upperBound;
protected final Set<Listener> listeners = new HashSet<>();
private Predicate<Long> predicate = e -> true;
public ChartModel() {
}
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@ -84,8 +89,17 @@ public class ChartModel extends ActivatableViewModel {
return new Tuple2<>(fromDateSec, toDateSec);
}
Predicate<Long> getPredicate(Tuple2<Double, Double> fromToTuple) {
return value -> value >= fromToTuple.first && value <= fromToTuple.second;
protected abstract void applyTemporalAdjuster(TemporalAdjuster temporalAdjuster);
protected abstract TemporalAdjuster getTemporalAdjuster();
Predicate<Long> getPredicate() {
return predicate;
}
Predicate<Long> setAndGetPredicate(Tuple2<Double, Double> fromToTuple) {
predicate = value -> value >= fromToTuple.first && value <= fromToTuple.second;
return predicate;
}
void notifyListeners(Tuple2<Double, Double> fromToTuple) {

View file

@ -19,6 +19,9 @@ package bisq.desktop.components.chart;
import bisq.desktop.common.view.ActivatableView;
import bisq.desktop.components.AutoTooltipSlideToggleButton;
import bisq.desktop.components.AutoTooltipToggleButton;
import bisq.core.locale.Res;
import bisq.common.util.Tuple2;
@ -29,8 +32,12 @@ import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.control.Label;
import javafx.scene.control.SplitPane;
import javafx.scene.control.Toggle;
import javafx.scene.control.ToggleButton;
import javafx.scene.control.ToggleGroup;
import javafx.scene.control.Tooltip;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Priority;
@ -44,6 +51,8 @@ import javafx.beans.value.ChangeListener;
import javafx.util.StringConverter;
import java.time.temporal.TemporalAdjuster;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
@ -54,12 +63,15 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Stream;
import lombok.extern.slf4j.Slf4j;
import static bisq.desktop.util.FormBuilder.getTopLabelWithVBox;
@Slf4j
public abstract class ChartView<T extends ChartModel> extends ActivatableView<VBox, T> {
private final Pane center;
@ -72,28 +84,27 @@ public abstract class ChartView<T extends ChartModel> extends ActivatableView<VB
private final HBox timelineLabels;
private final List<Node> dividerNodes = new ArrayList<>();
private final Double[] dividerPositions = new Double[]{0d, 1d};
private final ToggleGroup timeUnitToggleGroup = new ToggleGroup();
private boolean pressed;
private double x;
private ChangeListener<Number> widthListener;
private int maxSeriesSize;
private ChangeListener<Toggle> timeUnitChangeListener;
protected String dateFormatPatters = "dd MMM\nyyyy";
public ChartView(T model) {
super(model);
root = new VBox();
Pane left = new Pane();
center = new Pane();
Pane right = new Pane();
splitPane = new SplitPane();
splitPane.getItems().addAll(left, center, right);
// time units
Pane timeIntervalBox = getTimeIntervalBox();
// chart
xAxis = getXAxis();
yAxis = getYAxis();
chart = getChart();
addSeries();
HBox legendBox1 = getLegendBox(getSeriesForLegend1());
Collection<XYChart.Series<Number, Number>> seriesForLegend2 = getSeriesForLegend2();
HBox legendBox2 = null;
@ -101,8 +112,15 @@ public abstract class ChartView<T extends ChartModel> extends ActivatableView<VB
legendBox2 = getLegendBox(seriesForLegend2);
}
// Time navigation
Pane left = new Pane();
center = new Pane();
Pane right = new Pane();
splitPane = new SplitPane();
splitPane.getItems().addAll(left, center, right);
timelineLabels = new HBox();
// Container
VBox box = new VBox();
int paddingRight = 89;
int paddingLeft = 15;
@ -114,14 +132,9 @@ public abstract class ChartView<T extends ChartModel> extends ActivatableView<VB
VBox.setMargin(legendBox2, new Insets(-20, paddingRight, 0, paddingLeft));
box.getChildren().add(legendBox2);
}
root.getChildren().addAll(chart, box);
root.getChildren().addAll(timeIntervalBox, chart, box);
}
protected abstract Collection<XYChart.Series<Number, Number>> getSeriesForLegend1();
protected abstract Collection<XYChart.Series<Number, Number>> getSeriesForLegend2();
///////////////////////////////////////////////////////////////////////////////////////////
// Lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@ -138,24 +151,37 @@ public abstract class ChartView<T extends ChartModel> extends ActivatableView<VB
splitPane.setDividerPosition(0, dividerPositions[0]);
splitPane.setDividerPosition(1, dividerPositions[1]);
};
timeUnitChangeListener = (observable, oldValue, newValue) -> {
TemporalAdjusterUtil.Interval interval = (TemporalAdjusterUtil.Interval) newValue.getUserData();
applyTemporalAdjuster(interval.getAdjuster());
};
}
@Override
public void activate() {
root.widthProperty().addListener(widthListener);
timeUnitToggleGroup.selectedToggleProperty().addListener(timeUnitChangeListener);
splitPane.setOnMousePressed(this::onMousePressedSplitPane);
splitPane.setOnMouseDragged(this::onMouseDragged);
center.setOnMousePressed(this::onMousePressedCenter);
center.setOnMouseReleased(this::onMouseReleasedCenter);
initData();
initDividerMouseHandlers();
// Need to get called again here as otherwise styles are not applied correctly
applySeriesStyles();
TemporalAdjuster temporalAdjuster = model.getTemporalAdjuster();
applyTemporalAdjuster(temporalAdjuster);
findToggleByTemporalAdjuster(temporalAdjuster).ifPresent(timeUnitToggleGroup::selectToggle);
}
@Override
public void deactivate() {
root.widthProperty().removeListener(widthListener);
timeUnitToggleGroup.selectedToggleProperty().removeListener(timeUnitChangeListener);
splitPane.setOnMousePressed(null);
splitPane.setOnMouseDragged(null);
center.setOnMousePressed(null);
@ -176,6 +202,40 @@ public abstract class ChartView<T extends ChartModel> extends ActivatableView<VB
// Customisations
///////////////////////////////////////////////////////////////////////////////////////////
protected Pane getTimeIntervalBox() {
ToggleButton year = getToggleButton(Res.get("time.year"), TemporalAdjusterUtil.Interval.YEAR,
timeUnitToggleGroup, "toggle-left");
ToggleButton month = getToggleButton(Res.get("time.month"), TemporalAdjusterUtil.Interval.MONTH,
timeUnitToggleGroup, "toggle-center");
ToggleButton week = getToggleButton(Res.get("time.week"), TemporalAdjusterUtil.Interval.WEEK,
timeUnitToggleGroup, "toggle-center");
ToggleButton day = getToggleButton(Res.get("time.day"), TemporalAdjusterUtil.Interval.DAY,
timeUnitToggleGroup, "toggle-center");
HBox toggleBox = new HBox();
toggleBox.setSpacing(0);
toggleBox.setAlignment(Pos.CENTER_LEFT);
toggleBox.getChildren().addAll(year, month, week, day);
Tuple2<Label, VBox> topLabelWithVBox = getTopLabelWithVBox(Res.get("shared.interval"), toggleBox);
AnchorPane pane = new AnchorPane();
VBox vBox = topLabelWithVBox.second;
pane.getChildren().add(vBox);
AnchorPane.setRightAnchor(vBox, 90d);
return pane;
}
protected ToggleButton getToggleButton(String label,
TemporalAdjusterUtil.Interval interval,
ToggleGroup toggleGroup,
String style) {
ToggleButton toggleButton = new AutoTooltipToggleButton(label);
toggleButton.setUserData(interval);
toggleButton.setToggleGroup(toggleGroup);
toggleButton.setId(style);
return toggleButton;
}
protected NumberAxis getXAxis() {
NumberAxis xAxis;
xAxis = new NumberAxis();
@ -214,7 +274,7 @@ public abstract class ChartView<T extends ChartModel> extends ActivatableView<VB
toggle.setText(seriesName);
toggle.setId("charts-legend-toggle" + seriesIndexMap.get(seriesName));
toggle.setSelected(true);
toggle.setOnAction(e -> onSelectToggle(series, toggle.isSelected()));
toggle.setOnAction(e -> onSelectLegendToggle(series, toggle.isSelected()));
hBox.getChildren().add(toggle);
});
Region spacer = new Region();
@ -223,27 +283,32 @@ public abstract class ChartView<T extends ChartModel> extends ActivatableView<VB
return hBox;
}
private void onSelectToggle(XYChart.Series<Number, Number> series, boolean isSelected) {
protected abstract Collection<XYChart.Series<Number, Number>> getSeriesForLegend1();
protected abstract Collection<XYChart.Series<Number, Number>> getSeriesForLegend2();
private void onSelectLegendToggle(XYChart.Series<Number, Number> series, boolean isSelected) {
if (isSelected) {
chart.getData().add(series);
} else {
chart.getData().remove(series);
}
applySeriesStyles();
applyTooltip();
}
protected void hideSeries(XYChart.Series<Number, Number> series) {
toggleBySeriesName.get(series.getName()).setSelected(false);
onSelectToggle(series, false);
onSelectLegendToggle(series, false);
}
protected StringConverter<Number> getTimeAxisStringConverter() {
return new StringConverter<>() {
@Override
public String toString(Number value) {
DateFormat f = new SimpleDateFormat("YYYY-MM");
DateFormat format = new SimpleDateFormat(dateFormatPatters);
Date date = new Date(Math.round(value.doubleValue()) * 1000);
return f.format(date);
return format.format(date);
}
@Override
@ -267,6 +332,30 @@ public abstract class ChartView<T extends ChartModel> extends ActivatableView<VB
};
}
protected void applyTemporalAdjuster(TemporalAdjuster temporalAdjuster) {
model.applyTemporalAdjuster(temporalAdjuster);
findToggleByTemporalAdjuster(temporalAdjuster)
.map(e -> (TemporalAdjusterUtil.Interval) e.getUserData())
.ifPresent(interval -> setDateFormatPatters(interval));
updateData(model.getPredicate());
}
private void setDateFormatPatters(TemporalAdjusterUtil.Interval interval) {
switch (interval) {
case YEAR:
dateFormatPatters = "yyyy";
break;
case MONTH:
dateFormatPatters = "MMM\nyyyy";
break;
default:
dateFormatPatters = "MMM dd\nyyyy";
break;
}
}
protected abstract void initData();
protected abstract void updateData(Predicate<Long> predicate);
@ -274,20 +363,25 @@ public abstract class ChartView<T extends ChartModel> extends ActivatableView<VB
protected void applyTooltip() {
chart.getData().forEach(series -> {
series.getData().forEach(data -> {
String xValue = getXAxis().getTickLabelFormatter().toString(data.getXValue());
String yValue = getYAxis().getTickLabelFormatter().toString(data.getYValue());
Node node = data.getNode();
Tooltip.install(node, new Tooltip(yValue + "\n" + xValue));
//Adding class on hover
node.setOnMouseEntered(event -> node.getStyleClass().add("onHover"));
//Removing class on exit
node.setOnMouseExited(event -> node.getStyleClass().remove("onHover"));
if (node == null) {
return;
}
String xValue = getTooltipDateConverter(data.getXValue());
String yValue = getYAxisStringConverter().toString(data.getYValue());
Tooltip.install(node, new Tooltip(Res.get("dao.factsAndFigures.supply.chart.tradeFee.toolTip", yValue, xValue)));
});
});
}
protected String getTooltipDateConverter(Number date) {
return getTimeAxisStringConverter().toString(date).replace("\n", " ");
}
protected String getTooltipValueConverter(Number value) {
return getYAxisStringConverter().toString(value);
}
// Only called once when initial data are applied. We want the min. and max. values so we have the max. scale for
// navigation.
protected void setTimeLineLabels() {
@ -317,7 +411,7 @@ public abstract class ChartView<T extends ChartModel> extends ActivatableView<VB
// The chart framework assigns the colored depending on the order it got added, but want to keep colors
// the same so they match with the legend toggle.
private void applySeriesStyles() {
protected void applySeriesStyles() {
for (int index = 0; index < chart.getData().size(); index++) {
XYChart.Series<Number, Number> series = chart.getData().get(index);
int staticIndex = seriesIndexMap.get(series.getName());
@ -350,6 +444,12 @@ public abstract class ChartView<T extends ChartModel> extends ActivatableView<VB
return maxSeriesSize;
}
private Optional<Toggle> findToggleByTemporalAdjuster(TemporalAdjuster adjuster) {
return timeUnitToggleGroup.getToggles().stream()
.filter(toggle -> ((TemporalAdjusterUtil.Interval) toggle.getUserData()).getAdjuster().equals(adjuster))
.findAny();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Timeline navigation
@ -371,8 +471,7 @@ public abstract class ChartView<T extends ChartModel> extends ActivatableView<VB
dividerPositions[1] = rightPos;
splitPane.setDividerPositions(leftPos, rightPos);
Tuple2<Double, Double> fromToTuple = model.timelinePositionToEpochSeconds(leftPos, rightPos);
updateData(model.getPredicate(fromToTuple));
applySeriesStyles();
updateData(model.setAndGetPredicate(fromToTuple));
model.notifyListeners(fromToTuple);
}

View file

@ -0,0 +1,53 @@
/*
* 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.components.chart;
import java.time.Instant;
import java.time.ZoneId;
import java.time.temporal.TemporalAdjuster;
import java.time.temporal.TemporalAdjusters;
import lombok.Getter;
public class TemporalAdjusterUtil {
public enum Interval {
YEAR(TemporalAdjusters.firstDayOfYear()),
MONTH(TemporalAdjusters.firstDayOfMonth()),
WEEK(TemporalAdjusters.ofDateAdjuster(date -> date.plusWeeks(1))),
DAY(TemporalAdjusters.ofDateAdjuster(d -> d));
@Getter
private final TemporalAdjuster adjuster;
Interval(TemporalAdjuster adjuster) {
this.adjuster = adjuster;
}
}
private static final ZoneId ZONE_ID = ZoneId.systemDefault();
public static long toTimeInterval(Instant instant, TemporalAdjuster temporalAdjuster) {
return instant
.atZone(ZONE_ID)
.toLocalDate()
.with(temporalAdjuster)
.atStartOfDay(ZONE_ID)
.toInstant()
.getEpochSecond();
}
}

View file

@ -17,6 +17,8 @@
package bisq.desktop.main.dao.economy.supply;
import bisq.desktop.components.chart.TemporalAdjusterUtil;
import bisq.core.dao.state.DaoStateService;
import bisq.core.dao.state.model.blockchain.Tx;
import bisq.core.dao.state.model.governance.Issuance;
@ -26,9 +28,7 @@ import javax.inject.Inject;
import javax.inject.Singleton;
import java.time.Instant;
import java.time.ZoneId;
import java.time.temporal.TemporalAdjuster;
import java.time.temporal.TemporalAdjusters;
import java.util.Collection;
import java.util.HashMap;
@ -46,11 +46,10 @@ import lombok.extern.slf4j.Slf4j;
@Slf4j
@Singleton
public class DaoEconomyDataProvider {
private static final ZoneId ZONE_ID = ZoneId.systemDefault();
private static final TemporalAdjuster FIRST_DAY_OF_MONTH = TemporalAdjusters.firstDayOfMonth();
private final DaoStateService daoStateService;
private final Function<Integer, Long> blockHeightToEpochSeconds;
private final Function<Issuance, Long> blockTimeOfIssuanceFunction;
private TemporalAdjuster temporalAdjuster = TemporalAdjusterUtil.Interval.MONTH.getAdjuster();
///////////////////////////////////////////////////////////////////////////////////////////
@ -62,8 +61,23 @@ public class DaoEconomyDataProvider {
super();
this.daoStateService = daoStateService;
blockHeightToEpochSeconds = memoize(height ->
toStartOfMonth(Instant.ofEpochMilli(daoStateService.getBlockTime(height))));
blockTimeOfIssuanceFunction = memoize(issuance -> {
int height = daoStateService.getStartHeightOfCurrentCycle(issuance.getChainHeight()).orElse(0);
return daoStateService.getBlockTime(height);
});
}
///////////////////////////////////////////////////////////////////////////////////////////
// API
///////////////////////////////////////////////////////////////////////////////////////////
public void setTemporalAdjuster(TemporalAdjuster temporalAdjuster) {
this.temporalAdjuster = temporalAdjuster;
}
public TemporalAdjuster getTemporalAdjuster() {
return temporalAdjuster;
}
/**
@ -109,7 +123,7 @@ public class DaoEconomyDataProvider {
public Map<Long, Long> getBurnedBsqByMonth(Collection<Tx> txs, Predicate<Long> predicate) {
return txs.stream()
.collect(Collectors.groupingBy(tx -> toStartOfMonth(Instant.ofEpochMilli(tx.getTime()))))
.collect(Collectors.groupingBy(tx -> toTimeInterval(Instant.ofEpochMilli(tx.getTime()))))
.entrySet()
.stream()
.filter(entry -> predicate.test(entry.getKey()))
@ -125,8 +139,8 @@ public class DaoEconomyDataProvider {
// as adjuster would be more complicate (though could be done in future).
public Map<Long, Long> getIssuedBsqByMonth(Set<Issuance> issuanceSet, Predicate<Long> predicate) {
return issuanceSet.stream()
.collect(Collectors.groupingBy(blockHeightToEpochSeconds.compose(issuance ->
daoStateService.getStartHeightOfCurrentCycle(issuance.getChainHeight()).orElse(0))))
.collect(Collectors.groupingBy(issuance ->
toTimeInterval(Instant.ofEpochMilli(blockTimeOfIssuanceFunction.apply(issuance)))))
.entrySet()
.stream()
.filter(entry -> predicate.test(entry.getKey()))
@ -165,18 +179,13 @@ public class DaoEconomyDataProvider {
// as we have clearly separated that now. In case we have duplicate data for a months we use the static data.
return historicalData.entrySet().stream()
.filter(e -> predicate.test(e.getKey()))
.collect(Collectors.toMap(e -> toStartOfMonth(Instant.ofEpochSecond(e.getKey())),
Map.Entry::getValue));
.collect(Collectors.toMap(e -> toTimeInterval(Instant.ofEpochSecond(e.getKey())),
Map.Entry::getValue,
(a, b) -> a + b));
}
public static long toStartOfMonth(Instant instant) {
return instant
.atZone(ZONE_ID)
.toLocalDate()
.with(FIRST_DAY_OF_MONTH)
.atStartOfDay(ZONE_ID)
.toInstant()
.getEpochSecond();
public long toTimeInterval(Instant instant) {
return TemporalAdjusterUtil.toTimeInterval(instant, temporalAdjuster);
}
///////////////////////////////////////////////////////////////////////////////////////////

View file

@ -44,8 +44,6 @@ import javafx.scene.layout.VBox;
import javafx.geometry.Insets;
import java.util.Date;
import static bisq.desktop.util.FormBuilder.addTitledGroupBg;
import static bisq.desktop.util.FormBuilder.addTopLabelReadOnlyTextField;
@ -104,6 +102,7 @@ public class SupplyView extends ActivatableView<GridPane, Void> implements DaoSt
protected void deactivate() {
daoEconomyChartView.removeListener(this);
daoFacade.removeBsqStateListener(this);
daoEconomyChartView.deactivate();
}
@ -115,8 +114,6 @@ public class SupplyView extends ActivatableView<GridPane, Void> implements DaoSt
public void onDateFilterChanged(long fromDate, long toDate) {
this.fromDate = fromDate;
this.toDate = toDate;
log.error(new Date(fromDate).toString());
log.error(new Date(toDate).toString());
updateEconomicsData();
}

View file

@ -28,6 +28,9 @@ import javax.inject.Inject;
import javafx.scene.chart.XYChart;
import java.time.Instant;
import java.time.temporal.TemporalAdjuster;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
@ -47,11 +50,21 @@ public class DaoEconomyChartModel extends ChartModel {
@Inject
public DaoEconomyChartModel(DaoStateService daoStateService, DaoEconomyDataProvider daoEconomyDataProvider) {
super();
this.daoStateService = daoStateService;
this.daoStateService = daoStateService;
this.daoEconomyDataProvider = daoEconomyDataProvider;
}
@Override
protected void applyTemporalAdjuster(TemporalAdjuster temporalAdjuster) {
daoEconomyDataProvider.setTemporalAdjuster(temporalAdjuster);
}
@Override
protected TemporalAdjuster getTemporalAdjuster() {
return daoEconomyDataProvider.getTemporalAdjuster();
}
List<XYChart.Data<Number, Number>> getBsqTradeFeeChartData(Predicate<Long> predicate) {
return toChartData(daoEconomyDataProvider.getBurnedBsqByMonth(daoStateService.getTradeFeeTxs(), predicate));
}
@ -91,6 +104,10 @@ public class DaoEconomyChartModel extends ChartModel {
upperBound = Math.max(xMinMaxTradeFee.second, xMinMaxCompensationRequest.second);
}
long toTimeInterval(Instant ofEpochSecond) {
return daoEconomyDataProvider.toTimeInterval(ofEpochSecond);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Utils
///////////////////////////////////////////////////////////////////////////////////////////

View file

@ -18,7 +18,6 @@
package bisq.desktop.main.dao.economy.supply.chart;
import bisq.desktop.components.chart.ChartView;
import bisq.desktop.main.dao.economy.supply.DaoEconomyDataProvider;
import bisq.desktop.util.DisplayUtils;
import bisq.core.locale.Res;
@ -32,7 +31,6 @@ import javafx.scene.Node;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.control.Tooltip;
import javafx.scene.text.Text;
import javafx.geometry.Side;
@ -145,8 +143,8 @@ public class DaoEconomyChartView extends ChartView<DaoEconomyChartModel> {
return new StringConverter<>() {
@Override
public String toString(Number epochSeconds) {
Date date = new Date(DaoEconomyDataProvider.toStartOfMonth(Instant.ofEpochSecond(epochSeconds.longValue())) * 1000);
return DisplayUtils.formatDateAxis(date, "dd/MMM\nyyyy");
Date date = new Date(model.toTimeInterval(Instant.ofEpochSecond(epochSeconds.longValue())) * 1000);
return DisplayUtils.formatDateAxis(date, dateFormatPatters);
}
@Override
@ -171,6 +169,11 @@ public class DaoEconomyChartView extends ChartView<DaoEconomyChartModel> {
};
}
@Override
protected String getTooltipValueConverter(Number value) {
return bsqFormatter.formatBSQSatoshisWithCode(value.longValue());
}
@Override
protected void addSeries() {
seriesTotalIssued = new XYChart.Series<>();
@ -241,7 +244,9 @@ public class DaoEconomyChartView extends ChartView<DaoEconomyChartModel> {
seriesCompensation.getData().setAll(model.getCompensationChartData(predicate));
updateOtherSeries(predicate);
applyTooltip();
applySeriesStyles();
}
private void updateOtherSeries(Predicate<Long> predicate) {
@ -250,22 +255,4 @@ public class DaoEconomyChartView extends ChartView<DaoEconomyChartModel> {
seriesTotalIssued.getData().setAll(model.getTotalIssuedChartData(predicate));
seriesTotalBurned.getData().setAll(model.getTotalBurnedChartData(predicate));
}
@Override
protected void applyTooltip() {
chart.getData().forEach(series -> {
String format = series == seriesCompensation || series == seriesReimbursement || series == seriesTotalIssued ?
"dd MMM yyyy" :
"MMM yyyy";
series.getData().forEach(data -> {
String xValue = DisplayUtils.formatDateAxis(new Date(data.getXValue().longValue() * 1000), format);
String yValue = bsqFormatter.formatBSQSatoshisWithCode(data.getYValue().longValue());
Node node = data.getNode();
if (node == null) {
return;
}
Tooltip.install(node, new Tooltip(Res.get("dao.factsAndFigures.supply.chart.tradeFee.toolTip", yValue, xValue)));
});
});
}
}

View file

@ -135,16 +135,16 @@
-bs-white: white;
-bs-prompt-text: -bs-color-gray-3;
-bs-decimals: #db6300;
-bs-soft-red: #680000;
-bs-turquoise-light: #BEDB39;
-bs-soft-red: #aa4c3b;
-bs-turquoise-light: #00dcdd;
/* dao chart colors */
-bs-chart-dao-line1: -bs-color-green-5;
-bs-chart-dao-line2: -bs-color-blue-2;
-bs-chart-dao-line1: -bs-color-blue-5;
-bs-chart-dao-line2: -bs-color-green-3;
-bs-chart-dao-line3: -bs-turquoise;
-bs-chart-dao-line4: -bs-yellow;
-bs-chart-dao-line5: -bs-soft-red;
-bs-chart-dao-line6: -bs-turquoise-light;
-bs-chart-dao-line4: -bs-turquoise-light;
-bs-chart-dao-line5: -bs-yellow;
-bs-chart-dao-line6: -bs-soft-red;
/* Monero orange color code */
-xmr-orange: #f26822;

View file

@ -102,16 +102,16 @@
-bs-progress-bar-track: #e0e0e0;
-bs-white: white;
-bs-prompt-text: -fx-control-inner-background;
-bs-soft-red: #E74C3B;
-bs-turquoise-light: #00DCFF;
-bs-soft-red: #aa4c3b;
-bs-turquoise-light: #00dcdd;
/* dao chart colors */
-bs-chart-dao-line1: -bs-color-green-3;
-bs-chart-dao-line2: -bs-color-blue-5;
-bs-chart-dao-line1: -bs-color-blue-5;
-bs-chart-dao-line2: -bs-color-green-3;
-bs-chart-dao-line3: -bs-turquoise;
-bs-chart-dao-line4: -bs-yellow;
-bs-chart-dao-line5: -bs-soft-red;
-bs-chart-dao-line6: -bs-turquoise-light;
-bs-chart-dao-line4: -bs-turquoise-light;
-bs-chart-dao-line5: -bs-yellow;
-bs-chart-dao-line6: -bs-soft-red;
/* Monero orange color code */
-xmr-orange: #f26822;