mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-24 15:10:44 +01:00
Adapt offer book chart view to new navigational structure
This commit is contained in:
parent
98f355d3fa
commit
875e5f4e87
4 changed files with 89 additions and 91 deletions
|
@ -301,10 +301,10 @@ market.tabs.spreadPayment=Offers by Payment Method
|
|||
market.tabs.trades=Trades
|
||||
|
||||
# OfferBookChartView
|
||||
market.offerBook.buyAltcoin=Buy {0} (sell {1})
|
||||
market.offerBook.sellAltcoin=Sell {0} (buy {1})
|
||||
market.offerBook.buyWithFiat=Buy {0}
|
||||
market.offerBook.sellWithFiat=Sell {0}
|
||||
market.offerBook.buyAltcoin=Buy {0}
|
||||
market.offerBook.sellAltcoin=Sell {0}
|
||||
market.offerBook.buyWith=Buy {0}
|
||||
market.offerBook.sellWith=Sell {0}
|
||||
market.offerBook.sellOffersHeaderLabel=Sell {0} to
|
||||
market.offerBook.buyOffersHeaderLabel=Buy {0} from
|
||||
market.offerBook.buy=I want to buy bitcoin
|
||||
|
|
|
@ -29,7 +29,14 @@ import bisq.desktop.components.PeerInfoIconSmall;
|
|||
import bisq.desktop.main.MainView;
|
||||
import bisq.desktop.main.offer.BuyOfferView;
|
||||
import bisq.desktop.main.offer.SellOfferView;
|
||||
import bisq.desktop.main.offer.offerbook.BsqOfferBookView;
|
||||
import bisq.desktop.main.offer.offerbook.BsqOfferBookViewModel;
|
||||
import bisq.desktop.main.offer.offerbook.BtcOfferBookView;
|
||||
import bisq.desktop.main.offer.offerbook.OfferBookListItem;
|
||||
import bisq.desktop.main.offer.offerbook.OfferBookView;
|
||||
import bisq.desktop.main.offer.offerbook.OtherOfferBookView;
|
||||
import bisq.desktop.main.offer.offerbook.TopAltcoinOfferBookView;
|
||||
import bisq.desktop.main.offer.offerbook.TopAltcoinOfferBookViewModel;
|
||||
import bisq.desktop.util.CurrencyListItem;
|
||||
import bisq.desktop.util.DisplayUtils;
|
||||
import bisq.desktop.util.GUIUtil;
|
||||
|
@ -85,9 +92,7 @@ import javafx.beans.property.StringProperty;
|
|||
import javafx.beans.value.ChangeListener;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ListChangeListener;
|
||||
import javafx.collections.ObservableList;
|
||||
|
||||
import javafx.util.Callback;
|
||||
import javafx.util.StringConverter;
|
||||
|
@ -118,19 +123,19 @@ public class OfferBookChartView extends ActivatableViewAndModel<VBox, OfferBookC
|
|||
private Subscription tradeCurrencySubscriber;
|
||||
private final StringProperty volumeColumnLabel = new SimpleStringProperty();
|
||||
private final StringProperty priceColumnLabel = new SimpleStringProperty();
|
||||
private AutoTooltipButton leftButton;
|
||||
private AutoTooltipButton rightButton;
|
||||
private AutoTooltipButton sellButton;
|
||||
private AutoTooltipButton buyButton;
|
||||
private ChangeListener<Number> selectedTabIndexListener;
|
||||
private SingleSelectionModel<Tab> tabPaneSelectionModel;
|
||||
private Label leftHeaderLabel, rightHeaderLabel;
|
||||
private Label sellHeaderLabel, buyHeaderLabel;
|
||||
private ChangeListener<OfferListItem> sellTableRowSelectionListener, buyTableRowSelectionListener;
|
||||
private HBox bottomHBox;
|
||||
private ListChangeListener<OfferBookListItem> changeListener;
|
||||
private ListChangeListener<CurrencyListItem> currencyListItemsListener;
|
||||
private final double dataLimitFactor = 3;
|
||||
private final double initialOfferTableViewHeight = 121;
|
||||
private final double pixelsPerOfferTableRow = (initialOfferTableViewHeight - 30) / 5.0; // initial visible row count=5, header height=30
|
||||
private final Function<Double, Double> offerTableViewHeight = (screenSize) -> {
|
||||
// initial visible row count=5, header height=30
|
||||
double pixelsPerOfferTableRow = (initialOfferTableViewHeight - 30) / 5.0;
|
||||
int extraRows = screenSize <= INITIAL_WINDOW_HEIGHT ? 0 : (int) ((screenSize - INITIAL_WINDOW_HEIGHT) / pixelsPerOfferTableRow);
|
||||
return extraRows == 0 ? initialOfferTableViewHeight : Math.ceil(initialOfferTableViewHeight + ((extraRows + 1) * pixelsPerOfferTableRow));
|
||||
};
|
||||
|
@ -169,13 +174,13 @@ public class OfferBookChartView extends ActivatableViewAndModel<VBox, OfferBookC
|
|||
buyOfferTableView = tupleBuy.first;
|
||||
sellOfferTableView = tupleSell.first;
|
||||
|
||||
leftButton = (AutoTooltipButton) tupleBuy.third;
|
||||
rightButton = (AutoTooltipButton) tupleSell.third;
|
||||
sellButton = (AutoTooltipButton) tupleBuy.third;
|
||||
buyButton = (AutoTooltipButton) tupleSell.third;
|
||||
|
||||
leftHeaderLabel = tupleBuy.fourth;
|
||||
rightHeaderLabel = tupleSell.fourth;
|
||||
sellHeaderLabel = tupleBuy.fourth;
|
||||
buyHeaderLabel = tupleSell.fourth;
|
||||
|
||||
bottomHBox = new HBox();
|
||||
HBox bottomHBox = new HBox();
|
||||
bottomHBox.setSpacing(20); //30
|
||||
bottomHBox.setAlignment(Pos.CENTER);
|
||||
VBox.setMargin(bottomHBox, new Insets(-5, 0, 0, 0));
|
||||
|
@ -225,15 +230,15 @@ public class OfferBookChartView extends ActivatableViewAndModel<VBox, OfferBookC
|
|||
String code = tradeCurrency.getCode();
|
||||
volumeColumnLabel.set(Res.get("offerbook.volume", code));
|
||||
xAxis.setTickLabelFormatter(new StringConverter<>() {
|
||||
int cryptoPrecision = 3;
|
||||
DecimalFormat df = new DecimalFormat(",###");
|
||||
final int cryptoPrecision = 3;
|
||||
final DecimalFormat df = new DecimalFormat(",###");
|
||||
|
||||
@Override
|
||||
public String toString(Number object) {
|
||||
final double doubleValue = (double) object;
|
||||
if (CurrencyUtil.isCryptoCurrency(model.getCurrencyCode())) {
|
||||
final String withCryptoPrecision = FormattingUtils.formatRoundedDoubleWithPrecision(doubleValue, cryptoPrecision);
|
||||
if (withCryptoPrecision.substring(0, 3).equals("0.0")) {
|
||||
if (withCryptoPrecision.startsWith("0.0")) {
|
||||
return FormattingUtils.formatRoundedDoubleWithPrecision(doubleValue, 8).replaceFirst("0+$", "");
|
||||
} else {
|
||||
return withCryptoPrecision.replaceFirst("0+$", "");
|
||||
|
@ -249,37 +254,21 @@ public class OfferBookChartView extends ActivatableViewAndModel<VBox, OfferBookC
|
|||
}
|
||||
});
|
||||
|
||||
if (CurrencyUtil.isCryptoCurrency(code)) {
|
||||
if (bottomHBox.getChildren().size() == 2 && bottomHBox.getChildren().get(0).getUserData().equals(OfferDirection.BUY.name())) {
|
||||
bottomHBox.getChildren().get(0).toFront();
|
||||
reverseTableColumns();
|
||||
}
|
||||
String viewBaseCurrencyCode = CurrencyUtil.isCryptoCurrency(code) ? code : Res.getBaseCurrencyCode();
|
||||
String viewPriceCurrencyCode = CurrencyUtil.isCryptoCurrency(code) ? Res.getBaseCurrencyCode() : code;
|
||||
|
||||
leftHeaderLabel.setText(Res.get("market.offerBook.buyOffersHeaderLabel", code));
|
||||
leftButton.updateText(Res.get("market.offerBook.buyAltcoin", code, Res.getBaseCurrencyCode()));
|
||||
sellHeaderLabel.setText(Res.get("market.offerBook.sellOffersHeaderLabel", viewBaseCurrencyCode));
|
||||
sellButton.updateText(Res.get("market.offerBook.sellWith", viewBaseCurrencyCode, viewPriceCurrencyCode));
|
||||
|
||||
rightHeaderLabel.setText(Res.get("market.offerBook.sellOffersHeaderLabel", code));
|
||||
rightButton.updateText(Res.get("market.offerBook.sellAltcoin", code, Res.getBaseCurrencyCode()));
|
||||
buyHeaderLabel.setText(Res.get("market.offerBook.buyOffersHeaderLabel", viewBaseCurrencyCode));
|
||||
buyButton.updateText(Res.get("market.offerBook.buyWith", viewBaseCurrencyCode, viewPriceCurrencyCode));
|
||||
|
||||
priceColumnLabel.set(Res.get("shared.priceWithCur", Res.getBaseCurrencyCode()));
|
||||
} else {
|
||||
if (bottomHBox.getChildren().size() == 2 && bottomHBox.getChildren().get(0).getUserData().equals(OfferDirection.SELL.name())) {
|
||||
bottomHBox.getChildren().get(0).toFront();
|
||||
reverseTableColumns();
|
||||
}
|
||||
priceColumnLabel.set(Res.get("shared.priceWithCur", viewPriceCurrencyCode));
|
||||
|
||||
leftHeaderLabel.setText(Res.get("market.offerBook.sellOffersHeaderLabel", Res.getBaseCurrencyCode()));
|
||||
leftButton.updateText(Res.get("market.offerBook.sellWithFiat", Res.getBaseCurrencyCode(), code));
|
||||
|
||||
rightHeaderLabel.setText(Res.get("market.offerBook.buyOffersHeaderLabel", Res.getBaseCurrencyCode()));
|
||||
rightButton.updateText(Res.get("market.offerBook.buyWithFiat", Res.getBaseCurrencyCode(), code));
|
||||
|
||||
priceColumnLabel.set(Res.get("shared.priceWithCur", code));
|
||||
}
|
||||
xAxis.setLabel(CurrencyUtil.getPriceWithCurrencyCode(code));
|
||||
|
||||
seriesBuy.setName(leftHeaderLabel.getText() + " ");
|
||||
seriesSell.setName(rightHeaderLabel.getText());
|
||||
seriesBuy.setName(sellHeaderLabel.getText() + " ");
|
||||
seriesSell.setName(buyHeaderLabel.getText());
|
||||
});
|
||||
|
||||
buyOfferTableView.setItems(model.getTopBuyOfferList());
|
||||
|
@ -295,7 +284,7 @@ public class OfferBookChartView extends ActivatableViewAndModel<VBox, OfferBookC
|
|||
}
|
||||
|
||||
static class CurrencyListItemStringConverter extends StringConverter<CurrencyListItem> {
|
||||
private ComboBox<CurrencyListItem> comboBox;
|
||||
private final ComboBox<CurrencyListItem> comboBox;
|
||||
|
||||
CurrencyListItemStringConverter(ComboBox<CurrencyListItem> comboBox) {
|
||||
this.comboBox = comboBox;
|
||||
|
@ -390,33 +379,30 @@ public class OfferBookChartView extends ActivatableViewAndModel<VBox, OfferBookC
|
|||
seriesSell.getData().clear();
|
||||
areaChart.getData().clear();
|
||||
|
||||
boolean isCrypto = CurrencyUtil.isCryptoCurrency(model.getCurrencyCode());
|
||||
|
||||
// crypto: left-sell, right-buy. fiat: left-buy, right-sell
|
||||
seriesBuy.getData().addAll(filterOutliersBuy(model.getBuyData(), isCrypto));
|
||||
seriesSell.getData().addAll(filterOutliersSell(model.getSellData(), isCrypto));
|
||||
seriesBuy.getData().addAll(filterOutliersBuy(model.getBuyData()));
|
||||
seriesSell.getData().addAll(filterOutliersSell(model.getSellData()));
|
||||
|
||||
areaChart.getData().addAll(List.of(seriesBuy, seriesSell));
|
||||
}
|
||||
|
||||
List<XYChart.Data<Number, Number>> filterOutliersBuy(List<XYChart.Data<Number, Number>> buy, boolean isCrypto) {
|
||||
List<Double> mnmx = isCrypto ? minMaxFilterRight(buy) : minMaxFilterLeft(buy);
|
||||
if (mnmx.get(0).doubleValue() == Double.MAX_VALUE ||
|
||||
mnmx.get(1).doubleValue() == Double.MIN_VALUE) { // no filtering
|
||||
List<XYChart.Data<Number, Number>> filterOutliersBuy(List<XYChart.Data<Number, Number>> buy) {
|
||||
List<Double> mnmx = minMaxFilterLeft(buy);
|
||||
if (mnmx.get(0) == Double.MAX_VALUE ||
|
||||
mnmx.get(1) == Double.MIN_VALUE) { // no filtering
|
||||
return buy;
|
||||
}
|
||||
// apply filtering
|
||||
return isCrypto ? filterRight(buy, mnmx.get(0)) : filterLeft(buy, mnmx.get(1));
|
||||
return filterLeft(buy, mnmx.get(1));
|
||||
}
|
||||
|
||||
List<XYChart.Data<Number, Number>> filterOutliersSell(List<XYChart.Data<Number, Number>> sell, boolean isCrypto) {
|
||||
List<Double> mnmx = isCrypto ? minMaxFilterLeft(sell) : minMaxFilterRight(sell);
|
||||
if (mnmx.get(0).doubleValue() == Double.MAX_VALUE ||
|
||||
mnmx.get(1).doubleValue() == Double.MIN_VALUE) { // no filtering
|
||||
List<XYChart.Data<Number, Number>> filterOutliersSell(List<XYChart.Data<Number, Number>> sell) {
|
||||
List<Double> mnmx = minMaxFilterRight(sell);
|
||||
if (mnmx.get(0) == Double.MAX_VALUE ||
|
||||
mnmx.get(1) == Double.MIN_VALUE) { // no filtering
|
||||
return sell;
|
||||
}
|
||||
// apply filtering
|
||||
return isCrypto ? filterLeft(sell, mnmx.get(1)) : filterRight(sell, mnmx.get(0));
|
||||
return filterRight(sell, mnmx.get(0));
|
||||
}
|
||||
|
||||
private List<Double> minMaxFilterLeft(List<XYChart.Data<Number, Number>> data) {
|
||||
|
@ -674,12 +660,35 @@ public class OfferBookChartView extends ActivatableViewAndModel<VBox, OfferBookC
|
|||
button.setMinHeight(32);
|
||||
button.setId(isSellOffer ? "buy-button-big" : "sell-button-big");
|
||||
button.setOnAction(e -> {
|
||||
if (isSellOffer) {
|
||||
model.preferences.setBuyScreenCurrencyCode(model.getCurrencyCode());
|
||||
navigation.navigateTo(MainView.class, BuyOfferView.class);
|
||||
Class<? extends OfferBookView<?, ?>> offerBookViewClazz;
|
||||
if (CurrencyUtil.isFiatCurrency(model.getCurrencyCode())) {
|
||||
offerBookViewClazz = BtcOfferBookView.class;
|
||||
} else if (model.getCurrencyCode().equals(BsqOfferBookViewModel.BSQ.getCode())) {
|
||||
offerBookViewClazz = BsqOfferBookView.class;
|
||||
} else if (model.getCurrencyCode().equals(TopAltcoinOfferBookViewModel.TOP_ALTCOIN.getCode())) {
|
||||
offerBookViewClazz = TopAltcoinOfferBookView.class;
|
||||
} else {
|
||||
model.preferences.setSellScreenCurrencyCode(model.getCurrencyCode());
|
||||
navigation.navigateTo(MainView.class, SellOfferView.class);
|
||||
offerBookViewClazz = OtherOfferBookView.class;
|
||||
}
|
||||
|
||||
if (isSellOffer) {
|
||||
if (CurrencyUtil.isFiatCurrency(model.getCurrencyCode())) {
|
||||
model.preferences.setBuyScreenCurrencyCode(model.getCurrencyCode());
|
||||
} else if (!model.getCurrencyCode().equals(BsqOfferBookViewModel.BSQ.getCode()) &&
|
||||
model.getCurrencyCode().equals(TopAltcoinOfferBookViewModel.TOP_ALTCOIN.getCode())) {
|
||||
model.preferences.setBuyScreenCryptoCurrencyCode(model.getCurrencyCode());
|
||||
}
|
||||
|
||||
navigation.navigateTo(MainView.class, BuyOfferView.class, offerBookViewClazz);
|
||||
} else {
|
||||
if (CurrencyUtil.isFiatCurrency(model.getCurrencyCode())) {
|
||||
model.preferences.setSellScreenCurrencyCode(model.getCurrencyCode());
|
||||
} else if (!model.getCurrencyCode().equals(BsqOfferBookViewModel.BSQ.getCode()) &&
|
||||
model.getCurrencyCode().equals(TopAltcoinOfferBookViewModel.TOP_ALTCOIN.getCode())) {
|
||||
model.preferences.setSellScreenCryptoCurrencyCode(model.getCurrencyCode());
|
||||
}
|
||||
|
||||
navigation.navigateTo(MainView.class, SellOfferView.class, offerBookViewClazz);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -700,18 +709,6 @@ public class OfferBookChartView extends ActivatableViewAndModel<VBox, OfferBookC
|
|||
return new Tuple4<>(tableView, vBox, button, titleLabel);
|
||||
}
|
||||
|
||||
private void reverseTableColumns() {
|
||||
ObservableList<TableColumn<OfferListItem, ?>> columns = FXCollections.observableArrayList(buyOfferTableView.getColumns());
|
||||
buyOfferTableView.getColumns().clear();
|
||||
FXCollections.reverse(columns);
|
||||
buyOfferTableView.getColumns().addAll(columns);
|
||||
|
||||
columns = FXCollections.observableArrayList(sellOfferTableView.getColumns());
|
||||
sellOfferTableView.getColumns().clear();
|
||||
FXCollections.reverse(columns);
|
||||
sellOfferTableView.getColumns().addAll(columns);
|
||||
}
|
||||
|
||||
private void layout() {
|
||||
UserThread.runAfter(() -> {
|
||||
if (root.getScene() != null) {
|
||||
|
|
|
@ -293,7 +293,7 @@ class OfferBookChartViewModel extends ActivatableViewModel {
|
|||
// the buy column is actually the sell column and vice versa. To maintain the expected
|
||||
// ordering, we have to reverse the price comparator.
|
||||
boolean isCrypto = CurrencyUtil.isCryptoCurrency(getCurrencyCode());
|
||||
if (isCrypto) offerPriceComparator = offerPriceComparator.reversed();
|
||||
// if (isCrypto) offerPriceComparator = offerPriceComparator.reversed();
|
||||
|
||||
// Offer amounts are used for the secondary sort. They are sorted from high to low.
|
||||
Comparator<Offer> offerAmountComparator = Comparator.comparing(Offer::getAmount).reversed();
|
||||
|
@ -305,10 +305,12 @@ class OfferBookChartViewModel extends ActivatableViewModel {
|
|||
offerPriceComparator
|
||||
.thenComparing(offerAmountComparator);
|
||||
|
||||
OfferDirection buyOfferDirection = isCrypto ? OfferDirection.SELL : OfferDirection.BUY;
|
||||
|
||||
List<Offer> allBuyOffers = offerBookListItems.stream()
|
||||
.map(OfferBookListItem::getOffer)
|
||||
.filter(e -> e.getCurrencyCode().equals(selectedTradeCurrencyProperty.get().getCode())
|
||||
&& e.getDirection().equals(OfferDirection.BUY))
|
||||
&& e.getDirection().equals(buyOfferDirection))
|
||||
.sorted(buyOfferSortComparator)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
|
@ -334,10 +336,12 @@ class OfferBookChartViewModel extends ActivatableViewModel {
|
|||
|
||||
buildChartAndTableEntries(allBuyOffers, OfferDirection.BUY, buyData, topBuyOfferList);
|
||||
|
||||
OfferDirection sellOfferDirection = isCrypto ? OfferDirection.BUY : OfferDirection.SELL;
|
||||
|
||||
List<Offer> allSellOffers = offerBookListItems.stream()
|
||||
.map(OfferBookListItem::getOffer)
|
||||
.filter(e -> e.getCurrencyCode().equals(selectedTradeCurrencyProperty.get().getCode())
|
||||
&& e.getDirection().equals(OfferDirection.SELL))
|
||||
&& e.getDirection().equals(sellOfferDirection))
|
||||
.sorted(sellOfferSortComparator)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
|
@ -377,17 +381,10 @@ class OfferBookChartViewModel extends ActivatableViewModel {
|
|||
offerTableListTemp.add(new OfferListItem(offer, accumulatedAmount));
|
||||
|
||||
double priceAsDouble = (double) price.getValue() / LongMath.pow(10, price.smallestUnitExponent());
|
||||
if (CurrencyUtil.isCryptoCurrency(getCurrencyCode())) {
|
||||
if (direction.equals(OfferDirection.SELL))
|
||||
data.add(0, new XYChart.Data<>(priceAsDouble, accumulatedAmount));
|
||||
else
|
||||
data.add(new XYChart.Data<>(priceAsDouble, accumulatedAmount));
|
||||
} else {
|
||||
if (direction.equals(OfferDirection.BUY))
|
||||
data.add(0, new XYChart.Data<>(priceAsDouble, accumulatedAmount));
|
||||
else
|
||||
data.add(new XYChart.Data<>(priceAsDouble, accumulatedAmount));
|
||||
}
|
||||
if (direction.equals(OfferDirection.BUY))
|
||||
data.add(0, new XYChart.Data<>(priceAsDouble, accumulatedAmount));
|
||||
else
|
||||
data.add(new XYChart.Data<>(priceAsDouble, accumulatedAmount));
|
||||
}
|
||||
}
|
||||
offerTableList.setAll(offerTableListTemp);
|
||||
|
|
|
@ -260,23 +260,27 @@ public abstract class OfferView extends ActivatableView<TabPane, Void> {
|
|||
btcOfferBookTab.setContent(btcOfferBookView.getRoot());
|
||||
btcOfferBookView.setOfferActionHandler(offerActionHandler);
|
||||
btcOfferBookView.setDirection(direction);
|
||||
tabPane.getSelectionModel().select(btcOfferBookTab);
|
||||
btcOfferBookView.onTabSelected(true);
|
||||
} else if (viewClass == BsqOfferBookView.class) {
|
||||
bsqOfferBookView = (OfferBookView) viewLoader.load(BsqOfferBookView.class);
|
||||
bsqOfferBookView.setOfferActionHandler(offerActionHandler);
|
||||
bsqOfferBookView.setDirection(direction);
|
||||
tabPane.getSelectionModel().select(bsqOfferBookTab);
|
||||
bsqOfferBookTab.setContent(bsqOfferBookView.getRoot());
|
||||
bsqOfferBookView.onTabSelected(true);
|
||||
} else if (viewClass == TopAltcoinOfferBookView.class) {
|
||||
topAltcoinOfferBookView = (OfferBookView) viewLoader.load(TopAltcoinOfferBookView.class);
|
||||
topAltcoinOfferBookView.setOfferActionHandler(offerActionHandler);
|
||||
topAltcoinOfferBookView.setDirection(direction);
|
||||
tabPane.getSelectionModel().select(topAltcoinOfferBookTab);
|
||||
topAltcoinOfferBookTab.setContent(topAltcoinOfferBookView.getRoot());
|
||||
topAltcoinOfferBookView.onTabSelected(true);
|
||||
} else if (viewClass == OtherOfferBookView.class) {
|
||||
otherOfferBookView = (OfferBookView) viewLoader.load(OtherOfferBookView.class);
|
||||
otherOfferBookView.setOfferActionHandler(offerActionHandler);
|
||||
otherOfferBookView.setDirection(direction);
|
||||
tabPane.getSelectionModel().select(otherOfferBookTab);
|
||||
otherOfferBookTab.setContent(otherOfferBookView.getRoot());
|
||||
otherOfferBookView.onTabSelected(true);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue