diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/trade_wizard/market/TradeWizardMarketController.java b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/trade_wizard/market/TradeWizardMarketController.java deleted file mode 100644 index 2294bc8970..0000000000 --- a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/trade_wizard/market/TradeWizardMarketController.java +++ /dev/null @@ -1,146 +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 . - */ - -package bisq.desktop.main.content.bisq_easy.trade_wizard.market; - -import bisq.bonded_roles.market_price.MarketPriceService; -import bisq.chat.ChatMessage; -import bisq.chat.ChatService; -import bisq.chat.bisqeasy.offerbook.BisqEasyOfferbookChannel; -import bisq.chat.bisqeasy.offerbook.BisqEasyOfferbookChannelService; -import bisq.chat.bisqeasy.offerbook.BisqEasyOfferbookMessage; -import bisq.chat.bisqeasy.offerbook.BisqEasyOfferbookSelectionService; -import bisq.common.currency.Market; -import bisq.common.currency.MarketRepository; -import bisq.desktop.ServiceProvider; -import bisq.desktop.common.view.Controller; -import bisq.i18n.Res; -import bisq.offer.Direction; -import javafx.beans.property.ReadOnlyObjectProperty; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; -import org.fxmisc.easybind.EasyBind; -import org.fxmisc.easybind.Subscription; - -import java.util.Optional; -import java.util.Set; -import java.util.stream.Collectors; - -@Slf4j -public class TradeWizardMarketController implements Controller { - private final TradeWizardMarketModel model; - @Getter - private final TradeWizardMarketView view; - private final Runnable onNextHandler; - private final BisqEasyOfferbookChannelService bisqEasyOfferbookChannelService; - private final BisqEasyOfferbookSelectionService bisqEasyOfferbookSelectionService; - private final MarketPriceService marketPriceService; - private Subscription searchTextPin; - - public TradeWizardMarketController(ServiceProvider serviceProvider, Runnable onNextHandler) { - this.onNextHandler = onNextHandler; - ChatService chatService = serviceProvider.getChatService(); - bisqEasyOfferbookChannelService = chatService.getBisqEasyOfferbookChannelService(); - bisqEasyOfferbookSelectionService = chatService.getBisqEasyOfferbookChannelSelectionService(); - marketPriceService = serviceProvider.getBondedRolesService().getMarketPriceService(); - model = new TradeWizardMarketModel(); - view = new TradeWizardMarketView(model, this); - } - - public ReadOnlyObjectProperty getMarket() { - return model.getSelectedMarket(); - } - - public void setDirection(Direction direction) { - if (direction != null) { - model.setDirection(direction); - } - } - - public void reset() { - model.reset(); - } - - @Override - public void onActivate() { - model.setHeadline(model.getDirection().isBuy() ? Res.get("bisqEasy.tradeWizard.market.headline.buyer") : Res.get("bisqEasy.tradeWizard.market.headline.seller")); - model.getSearchText().set(""); - if (model.getSelectedMarket().get() == null) { - // Use selected public channel or if private channel is selected we use any of the public channels for - // setting the default market - Optional.ofNullable(bisqEasyOfferbookSelectionService.getSelectedChannel().get()) - .filter(channel -> channel instanceof BisqEasyOfferbookChannel) - .map(channel -> (BisqEasyOfferbookChannel) channel) - .map(BisqEasyOfferbookChannel::getMarket) - .ifPresent(market -> model.getSelectedMarket().set(market)); - } - - model.getListItems().setAll(MarketRepository.getAllFiatMarkets().stream() - .filter(market -> marketPriceService.getMarketPriceByCurrencyMap().containsKey(market)) - .map(market -> { - Set allMessages = bisqEasyOfferbookChannelService.getChannels().stream() - .filter(channel -> channel.getMarket().equals(market)) - .flatMap(channel -> channel.getChatMessages().stream()) - .collect(Collectors.toSet()); - int numOffersInChannel = (int) allMessages.stream() - .filter(BisqEasyOfferbookMessage::hasBisqEasyOffer) - .distinct() - .count(); - int numUsersInChannel = (int) allMessages.stream() - .map(ChatMessage::getAuthorUserProfileId) - .distinct() - .count(); - TradeWizardMarketView.ListItem item = new TradeWizardMarketView.ListItem(market, numOffersInChannel, numUsersInChannel); - if (market.equals(model.getSelectedMarket().get())) { - model.getSelectedMarketListItem().set(item); - } - return item; - }) - .collect(Collectors.toList())); - - searchTextPin = EasyBind.subscribe(model.getSearchText(), searchText -> { - if (searchText == null || searchText.isEmpty()) { - model.getFilteredList().setPredicate(item -> true); - } else { - String search = searchText.toLowerCase(); - model.getFilteredList().setPredicate(item -> - item != null && - (item.getQuoteCurrencyDisplayName().toLowerCase().contains(search) || - item.getMarket().getQuoteCurrencyDisplayName().toLowerCase().contains(search)) - ); - } - }); - } - - @Override - public void onDeactivate() { - searchTextPin.unsubscribe(); - } - - void onMarketListItemClicked(TradeWizardMarketView.ListItem item) { - if (item == null) { - return; - } - if (item.equals(model.getSelectedMarketListItem().get())) { - onNextHandler.run(); - } - model.getSelectedMarketListItem().set(item); - model.getSelectedMarket().set(item.getMarket()); - bisqEasyOfferbookChannelService.findChannel(item.getMarket()) - .ifPresent(bisqEasyOfferbookSelectionService::selectChannel); - } -} diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/trade_wizard/market/TradeWizardMarketModel.java b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/trade_wizard/market/TradeWizardMarketModel.java deleted file mode 100644 index 9738af6cb7..0000000000 --- a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/trade_wizard/market/TradeWizardMarketModel.java +++ /dev/null @@ -1,56 +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 . - */ - -package bisq.desktop.main.content.bisq_easy.trade_wizard.market; - -import bisq.common.currency.Market; -import bisq.desktop.common.view.Model; -import bisq.offer.Direction; -import javafx.beans.property.ObjectProperty; -import javafx.beans.property.SimpleObjectProperty; -import javafx.beans.property.SimpleStringProperty; -import javafx.beans.property.StringProperty; -import javafx.collections.FXCollections; -import javafx.collections.ObservableList; -import javafx.collections.transformation.FilteredList; -import javafx.collections.transformation.SortedList; -import lombok.Getter; -import lombok.Setter; - -@Getter -public class TradeWizardMarketModel implements Model { - @Setter - private Direction direction; - @Setter - private String headline; - private final ObjectProperty selectedMarketListItem = new SimpleObjectProperty<>(); - private final StringProperty searchText = new SimpleStringProperty(); - private final ObjectProperty selectedMarket = new SimpleObjectProperty<>(); - private final ObservableList listItems = FXCollections.observableArrayList(); - private final FilteredList filteredList = new FilteredList<>(listItems); - private final SortedList sortedList = new SortedList<>(filteredList); - - - void reset() { - direction = null; - headline = null; - selectedMarketListItem.set(null); - searchText.set(null); - selectedMarket.set(null); - listItems.clear(); - } -} \ No newline at end of file diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/trade_wizard/market/TradeWizardMarketView.java b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/trade_wizard/market/TradeWizardMarketView.java deleted file mode 100644 index 30cfae1b27..0000000000 --- a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/trade_wizard/market/TradeWizardMarketView.java +++ /dev/null @@ -1,214 +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 . - */ - -package bisq.desktop.main.content.bisq_easy.trade_wizard.market; - -import bisq.common.currency.FiatCurrency; -import bisq.common.currency.Market; -import bisq.desktop.common.threading.UIThread; -import bisq.desktop.common.view.View; -import bisq.desktop.components.containers.Spacer; -import bisq.desktop.components.controls.BisqTooltip; -import bisq.desktop.components.controls.SearchBox; -import bisq.desktop.components.table.BisqTableColumn; -import bisq.desktop.components.table.BisqTableView; -import bisq.desktop.main.content.components.MarketImageComposition; -import bisq.i18n.Res; -import javafx.geometry.Insets; -import javafx.geometry.Pos; -import javafx.scene.CacheHint; -import javafx.scene.Node; -import javafx.scene.control.Label; -import javafx.scene.control.TableCell; -import javafx.scene.control.TableColumn; -import javafx.scene.control.Tooltip; -import javafx.scene.effect.ColorAdjust; -import javafx.scene.layout.StackPane; -import javafx.scene.layout.VBox; -import javafx.scene.text.TextAlignment; -import javafx.util.Callback; -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; - -import java.util.Comparator; - -@Slf4j -public class TradeWizardMarketView extends View { - private final BisqTableView tableView; - private final SearchBox searchBox; - private final Label headlineLabel; - - public TradeWizardMarketView(TradeWizardMarketModel model, TradeWizardMarketController controller) { - super(new VBox(10), model, controller); - - root.setAlignment(Pos.TOP_CENTER); - - headlineLabel = new Label(); - headlineLabel.getStyleClass().add("bisq-text-headline-2"); - - Label subtitleLabel = new Label(Res.get("bisqEasy.tradeWizard.market.subTitle")); - subtitleLabel.setTextAlignment(TextAlignment.CENTER); - subtitleLabel.setAlignment(Pos.CENTER); - subtitleLabel.getStyleClass().addAll("bisq-text-3", "wrap-text"); - - searchBox = new SearchBox(); - searchBox.setPromptText(Res.get("bisqEasy.tradeWizard.market.columns.name").toUpperCase()); - searchBox.setMinWidth(140); - searchBox.setMaxWidth(140); - searchBox.getStyleClass().add("bisq-easy-trade-wizard-market-search"); - - tableView = new BisqTableView<>(model.getSortedList()); - tableView.getStyleClass().add("bisq-easy-trade-wizard-market"); - double tableHeight = 290; - int tableWidth = 650; - tableView.setMinHeight(tableHeight); - tableView.setMaxHeight(tableHeight); - tableView.setMinWidth(tableWidth); - tableView.setMaxWidth(tableWidth); - configTableView(); - - StackPane.setMargin(searchBox, new Insets(5, 0, 0, 15)); - StackPane tableViewWithSearchBox = new StackPane(tableView, searchBox); - tableViewWithSearchBox.setAlignment(Pos.TOP_LEFT); - tableViewWithSearchBox.setPrefSize(tableWidth, tableHeight); - tableViewWithSearchBox.setMaxWidth(tableWidth); - tableViewWithSearchBox.getStyleClass().add("markets-table-container"); - - root.getChildren().addAll(Spacer.fillVBox(), headlineLabel, subtitleLabel, tableViewWithSearchBox, Spacer.fillVBox()); - } - - @Override - protected void onViewAttached() { - tableView.initialize(); - headlineLabel.setText(model.getHeadline()); - tableView.getSelectionModel().select(model.getSelectedMarketListItem().get()); - - searchBox.textProperty().bindBidirectional(model.getSearchText()); - - // We use setOnMouseClicked handler not a listener on - // tableView.getSelectionModel().getSelectedItem() to get triggered the handler only at user action and - // not when we set the selected item by code. - tableView.setOnMouseClicked(e -> controller.onMarketListItemClicked(tableView.getSelectionModel().getSelectedItem())); - - UIThread.runOnNextRenderFrame(() -> tableView.scrollTo(model.getSelectedMarketListItem().get())); - } - - @Override - protected void onViewDetached() { - tableView.dispose(); - searchBox.textProperty().unbindBidirectional(model.getSearchText()); - tableView.setOnMouseClicked(null); - } - - private void configTableView() { - tableView.getColumns().add(tableView.getSelectionMarkerColumn()); - tableView.getColumns().add(new BisqTableColumn.Builder() - .left() - .minWidth(120) - .comparator(Comparator.comparing(ListItem::getQuoteCurrencyDisplayName)) - .setCellFactory(getNameCellFactory()) - .build()); - tableView.getColumns().add(new BisqTableColumn.Builder() - .title(Res.get("bisqEasy.tradeWizard.market.columns.numOffers")) - .minWidth(60) - .valueSupplier(ListItem::getNumOffers) - .comparator(Comparator.comparing(ListItem::getNumOffersAsInteger)) - .build()); - tableView.getColumns().add(new BisqTableColumn.Builder() - .title(Res.get("bisqEasy.tradeWizard.market.columns.numPeers")) - .minWidth(60) - .valueSupplier(ListItem::getNumUsers) - .comparator(Comparator.comparing(ListItem::getNumUsersAsInteger)) - .build()); - } - - private Callback, TableCell> getNameCellFactory - () { - return column -> new TableCell<>() { - private final Label label = new Label(); - private final Tooltip tooltip = new BisqTooltip(); - - { - label.setPadding(new Insets(0, 0, 0, 10)); - label.setGraphicTextGap(8); - label.getStyleClass().add("bisq-text-8"); - } - - @Override - protected void updateItem(ListItem item, boolean empty) { - super.updateItem(item, empty); - - if (item != null && !empty) { - label.setGraphic(item.getMarketLogo()); - String quoteCurrencyName = item.getQuoteCurrencyDisplayName(); - label.setText(quoteCurrencyName); - if (quoteCurrencyName.length() > 20) { - tooltip.setText(quoteCurrencyName); - label.setTooltip(tooltip); - } - - setGraphic(label); - } else { - label.setTooltip(null); - label.setGraphic(null); - setGraphic(null); - } - } - }; - } - - - @EqualsAndHashCode(onlyExplicitlyIncluded = true) - @Getter - static class ListItem { - @EqualsAndHashCode.Include - private final Market market; - @EqualsAndHashCode.Include - private final int numOffersAsInteger; - @EqualsAndHashCode.Include - private final int numUsersAsInteger; - - private final String quoteCurrencyDisplayName; - private final String numOffers; - private final String numUsers; - - // TODO: move to cell - private final Node marketLogo; - - ListItem(Market market, int numOffersAsInteger, int numUsersAsInteger) { - this.market = market; - this.numOffersAsInteger = numOffersAsInteger; - this.numUsersAsInteger = numUsersAsInteger; - - this.numOffers = String.valueOf(numOffersAsInteger); - quoteCurrencyDisplayName = new FiatCurrency(market.getQuoteCurrencyCode()).getCodeAndDisplayName(); - this.numUsers = String.valueOf(numUsersAsInteger); - marketLogo = MarketImageComposition.createMarketLogo(market.getQuoteCurrencyCode()); - marketLogo.setCache(true); - marketLogo.setCacheHint(CacheHint.SPEED); - ColorAdjust colorAdjust = new ColorAdjust(); - colorAdjust.setBrightness(-0.1); - marketLogo.setEffect(colorAdjust); - } - - @Override - public String toString() { - return market.toString(); - } - } -}