diff --git a/core/src/main/resources/i18n/displayStrings.properties b/core/src/main/resources/i18n/displayStrings.properties index a2c34c5fad9..fec863f6746 100644 --- a/core/src/main/resources/i18n/displayStrings.properties +++ b/core/src/main/resources/i18n/displayStrings.properties @@ -292,7 +292,8 @@ mainView.version.update=(Update available) #################################################################### market.tabs.offerBook=Offer book -market.tabs.spread=Details +market.tabs.spreadCurrency=Offers by Currency +market.tabs.spreadPayment=Offers by Payment Method market.tabs.trades=Trades # OfferBookChartView @@ -311,6 +312,7 @@ market.spread.numberOfBuyOffersColumn=Buy BTC ({0}) market.spread.numberOfSellOffersColumn=Sell BTC ({0}) market.spread.totalAmountColumn=Total BTC ({0}) market.spread.spreadColumn=Spread +market.spread.expanded=Expanded view # TradesChartsView market.trades.nrOfTrades=Trades: {0} diff --git a/desktop/src/main/java/bisq/desktop/main/market/MarketView.fxml b/desktop/src/main/java/bisq/desktop/main/market/MarketView.fxml index ead1b399048..74568ee5be3 100644 --- a/desktop/src/main/java/bisq/desktop/main/market/MarketView.fxml +++ b/desktop/src/main/java/bisq/desktop/main/market/MarketView.fxml @@ -32,6 +32,7 @@ AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"/> + { @FXML - Tab offerBookTab, tradesTab, spreadTab; + Tab offerBookTab, tradesTab, spreadTab, spreadTabPaymentMethod; private final ViewLoader viewLoader; private final TradeStatistics3StorageService tradeStatistics3StorageService; private final OfferBook offerBook; @@ -96,7 +97,8 @@ public MarketView(CachingViewLoader viewLoader, @Override public void initialize() { offerBookTab.setText(Res.get("market.tabs.offerBook").toUpperCase()); - spreadTab.setText(Res.get("market.tabs.spread").toUpperCase()); + spreadTab.setText(Res.get("market.tabs.spreadCurrency").toUpperCase()); + spreadTabPaymentMethod.setText(Res.get("market.tabs.spreadPayment").toUpperCase()); tradesTab.setText(Res.get("market.tabs.trades").toUpperCase()); navigationListener = viewPath -> { @@ -111,6 +113,8 @@ else if (newValue == tradesTab) navigation.navigateTo(MainView.class, MarketView.class, TradesChartsView.class); else if (newValue == spreadTab) navigation.navigateTo(MainView.class, MarketView.class, SpreadView.class); + else if (newValue == spreadTabPaymentMethod) + navigation.navigateTo(MainView.class, MarketView.class, SpreadViewPaymentMethod.class); }; keyEventEventHandler = keyEvent -> { @@ -139,8 +143,10 @@ protected void activate() { navigation.navigateTo(MainView.class, MarketView.class, OfferBookChartView.class); else if (root.getSelectionModel().getSelectedItem() == tradesTab) navigation.navigateTo(MainView.class, MarketView.class, TradesChartsView.class); - else + else if (root.getSelectionModel().getSelectedItem() == spreadTab) navigation.navigateTo(MainView.class, MarketView.class, SpreadView.class); + else + navigation.navigateTo(MainView.class, MarketView.class, SpreadViewPaymentMethod.class); if (root.getScene() != null) { scene = root.getScene(); @@ -164,6 +170,7 @@ private void loadView(Class viewClass) { if (view instanceof OfferBookChartView) tab = offerBookTab; else if (view instanceof TradesChartsView) tab = tradesTab; + else if (view instanceof SpreadViewPaymentMethod) tab = spreadTabPaymentMethod; else if (view instanceof SpreadView) tab = spreadTab; else throw new IllegalArgumentException("Navigation to " + viewClass + " is not supported"); diff --git a/desktop/src/main/java/bisq/desktop/main/market/spread/SpreadView.java b/desktop/src/main/java/bisq/desktop/main/market/spread/SpreadView.java index 539ab5ffad1..68325ba38fc 100644 --- a/desktop/src/main/java/bisq/desktop/main/market/spread/SpreadView.java +++ b/desktop/src/main/java/bisq/desktop/main/market/spread/SpreadView.java @@ -95,7 +95,8 @@ public void initialize() { tableView.getColumns().add(spreadColumn); tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY); - currencyColumn.setComparator(Comparator.comparing(o -> CurrencyUtil.getNameByCode(o.currencyCode))); + currencyColumn.setComparator(Comparator.comparing(o -> + model.isIncludePaymentMethod() ? o.currencyCode : CurrencyUtil.getNameByCode(o.currencyCode))); numberOfOffersColumn.setComparator(Comparator.comparingInt(o3 -> o3.numberOfOffers)); numberOfBuyOffersColumn.setComparator(Comparator.comparingInt(o3 -> o3.numberOfBuyOffers)); numberOfSellOffersColumn.setComparator(Comparator.comparingInt(o2 -> o2.numberOfSellOffers)); @@ -139,7 +140,7 @@ private void updateHeaders() { /////////////////////////////////////////////////////////////////////////////////////////// private TableColumn getCurrencyColumn() { - TableColumn column = new AutoTooltipTableColumn<>(Res.get("shared.currency")) { + TableColumn column = new AutoTooltipTableColumn<>(model.getKeyColumnName()) { { setMinWidth(160); } @@ -156,7 +157,10 @@ public TableCell call( public void updateItem(final SpreadItem item, boolean empty) { super.updateItem(item, empty); if (item != null && !empty) - setText(CurrencyUtil.getNameAndCode(item.currencyCode)); + if (model.isIncludePaymentMethod()) + setText(item.currencyCode); + else + setText(CurrencyUtil.getNameAndCode(item.currencyCode)); else setText(""); } diff --git a/desktop/src/main/java/bisq/desktop/main/market/spread/SpreadViewModel.java b/desktop/src/main/java/bisq/desktop/main/market/spread/SpreadViewModel.java index e5ee933ca0d..545c9478365 100644 --- a/desktop/src/main/java/bisq/desktop/main/market/spread/SpreadViewModel.java +++ b/desktop/src/main/java/bisq/desktop/main/market/spread/SpreadViewModel.java @@ -23,7 +23,7 @@ import bisq.desktop.main.overlays.popups.Popup; import bisq.desktop.util.GUIUtil; -import bisq.core.locale.CurrencyUtil; +import bisq.core.locale.Res; import bisq.core.monetary.Altcoin; import bisq.core.monetary.Price; import bisq.core.offer.Offer; @@ -60,6 +60,9 @@ import java.util.function.Predicate; import java.util.stream.Collectors; +import lombok.Getter; +import lombok.Setter; + class SpreadViewModel extends ActivatableViewModel { private final OfferBook offerBook; @@ -69,7 +72,11 @@ class SpreadViewModel extends ActivatableViewModel { private final ListChangeListener listChangeListener; final ObservableList spreadItems = FXCollections.observableArrayList(); final IntegerProperty maxPlacesForAmount = new SimpleIntegerProperty(); - + @Setter + @Getter + private boolean includePaymentMethod; + @Getter + private boolean expandedView; /////////////////////////////////////////////////////////////////////////////////////////// // Constructor, lifecycle @@ -80,11 +87,20 @@ public SpreadViewModel(OfferBook offerBook, PriceFeedService priceFeedService, @ this.offerBook = offerBook; this.priceFeedService = priceFeedService; this.formatter = formatter; - + includePaymentMethod = false; offerBookListItems = offerBook.getOfferBookListItems(); listChangeListener = c -> update(offerBookListItems); } + public String getKeyColumnName() { + return includePaymentMethod ? Res.get("shared.paymentMethod") : Res.get("shared.currency"); + } + + public void setExpandedView(boolean expandedView) { + this.expandedView = expandedView; + update(offerBookListItems); + } + @Override protected void activate() { offerBookListItems.addListener(listChangeListener); @@ -106,18 +122,24 @@ private void update(ObservableList offerBookListItems) { Map> offersByCurrencyMap = new HashMap<>(); for (OfferBookListItem offerBookListItem : offerBookListItems) { Offer offer = offerBookListItem.getOffer(); - String currencyCode = offer.getCurrencyCode(); - if (!offersByCurrencyMap.containsKey(currencyCode)) - offersByCurrencyMap.put(currencyCode, new ArrayList<>()); - offersByCurrencyMap.get(currencyCode).add(offer); + String key = offer.getCurrencyCode(); + if (includePaymentMethod) { + key = offer.getPaymentMethod().getShortName(); + if (expandedView) { + key += ":" + offer.getCurrencyCode(); + } + } + if (!offersByCurrencyMap.containsKey(key)) + offersByCurrencyMap.put(key, new ArrayList<>()); + offersByCurrencyMap.get(key).add(offer); } spreadItems.clear(); Coin totalAmount = null; - for (String currencyCode : offersByCurrencyMap.keySet()) { - List offers = offersByCurrencyMap.get(currencyCode); - final boolean isFiatCurrency = CurrencyUtil.isFiatCurrency(currencyCode); + for (String key : offersByCurrencyMap.keySet()) { + List offers = offersByCurrencyMap.get(key); + final boolean isFiatCurrency = (offers.size() > 0 && !offers.get(0).getPaymentMethod().isAsset()); List uniqueOffers = offers.stream().filter(distinctByKey(Offer::getId)).collect(Collectors.toList()); @@ -160,8 +182,9 @@ private void update(ObservableList offerBookListItems) { double percentageValue = 0; Price bestSellOfferPrice = sellOffers.isEmpty() ? null : sellOffers.get(0).getPrice(); Price bestBuyOfferPrice = buyOffers.isEmpty() ? null : buyOffers.get(0).getPrice(); - if (bestBuyOfferPrice != null && bestSellOfferPrice != null) { - MarketPrice marketPrice = priceFeedService.getMarketPrice(currencyCode); + if (bestBuyOfferPrice != null && bestSellOfferPrice != null && + sellOffers.get(0).getCurrencyCode().equals(buyOffers.get(0).getCurrencyCode())) { + MarketPrice marketPrice = priceFeedService.getMarketPrice(sellOffers.get(0).getCurrencyCode()); // There have been some bug reports that an offer caused an overflow exception. // We never found out which offer it was. So add here a try/catch to get better info if it @@ -213,7 +236,7 @@ private void update(ObservableList offerBookListItems) { } totalAmount = Coin.valueOf(offers.stream().mapToLong(offer -> offer.getAmount().getValue()).sum()); - spreadItems.add(new SpreadItem(currencyCode, buyOffers.size(), sellOffers.size(), + spreadItems.add(new SpreadItem(key, buyOffers.size(), sellOffers.size(), uniqueOffers.size(), spread, percentage, percentageValue, totalAmount)); } diff --git a/desktop/src/main/java/bisq/desktop/main/market/spread/SpreadViewPaymentMethod.fxml b/desktop/src/main/java/bisq/desktop/main/market/spread/SpreadViewPaymentMethod.fxml new file mode 100644 index 00000000000..6e8854fd099 --- /dev/null +++ b/desktop/src/main/java/bisq/desktop/main/market/spread/SpreadViewPaymentMethod.fxml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + diff --git a/desktop/src/main/java/bisq/desktop/main/market/spread/SpreadViewPaymentMethod.java b/desktop/src/main/java/bisq/desktop/main/market/spread/SpreadViewPaymentMethod.java new file mode 100644 index 00000000000..c89791d0032 --- /dev/null +++ b/desktop/src/main/java/bisq/desktop/main/market/spread/SpreadViewPaymentMethod.java @@ -0,0 +1,68 @@ +/* + * 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 . + */ + +package bisq.desktop.main.market.spread; + +import bisq.desktop.common.view.FxmlView; + +import bisq.core.locale.Res; +import bisq.core.util.FormattingUtils; +import bisq.core.util.coin.CoinFormatter; + +import javax.inject.Inject; +import javax.inject.Named; + +import javafx.scene.control.ToggleButton; + +import static bisq.desktop.util.FormBuilder.addSlideToggleButton; + +@FxmlView +public class SpreadViewPaymentMethod extends SpreadView { + private ToggleButton expandedMode; + + /////////////////////////////////////////////////////////////////////////////////////////// + // Constructor, lifecycle + /////////////////////////////////////////////////////////////////////////////////////////// + + @Inject + public SpreadViewPaymentMethod(SpreadViewModel model, @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter formatter) { + super(model, formatter); + model.setIncludePaymentMethod(true); + } + + @Override + public void initialize() { + super.initialize(); + int gridRow = 0; + expandedMode = addSlideToggleButton(root, ++gridRow, Res.get("market.spread.expanded")); + } + + @Override + protected void activate() { + super.activate(); + expandedMode.setSelected(model.isExpandedView()); + expandedMode.setOnAction(e -> model.setExpandedView(expandedMode.isSelected())); + } + + @Override + protected void deactivate() { + expandedMode.setOnAction(null); + super.deactivate(); + } +} + +