Skip to content

Commit

Permalink
Merge pull request #2691 from axpoems/further-imp-payment-filter
Browse files Browse the repository at this point in the history
Further improvements in offer list payments filter
  • Loading branch information
HenrikJannsen authored Aug 26, 2024
2 parents a99624c + 8b9327e commit 402543c
Show file tree
Hide file tree
Showing 12 changed files with 171 additions and 74 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* 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.controls;

import javafx.event.ActionEvent;
import javafx.event.Event;
import javafx.scene.control.CustomMenuItem;
import lombok.Getter;

@Getter
public class DropdownBisqMenuItem extends CustomMenuItem {
private final BisqMenuItem bisqMenuItem;

public DropdownBisqMenuItem(String defaultIconId, String activeIconId, String text) {
bisqMenuItem = new BisqMenuItem(defaultIconId, activeIconId, text);
bisqMenuItem.getStyleClass().add("dropdown-menu-item-content");
setContent(bisqMenuItem);

// Using DropdownMenuItem.setOnAction leads to duplicate execution of the handler on MacOS 14.5 / M3.
// Might be a bug in the MacOS specific JavaFX libraries as other devs could not reproduce the issue.
// Using an eventFilter and consuming the event solves the issue.
// This happens only when bisqMenuItem is used inside the DropdownMenuItem
bisqMenuItem.addEventFilter(ActionEvent.ANY, Event::consume);
}

public DropdownBisqMenuItem(String text) {
this(null, null, text);
}

public DropdownBisqMenuItem(String defaultIconId, String activeIconId) {
this(defaultIconId, activeIconId, "");
}

public void setLabelText(String text) {
bisqMenuItem.setText(text);
}

public Double getWidth() {
return bisqMenuItem.getWidth();
}

public void updateWidth(Double width) {
bisqMenuItem.setPrefWidth(width);
}

public String getLabelText() {
return bisqMenuItem.getText();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ public class DropdownMenu extends HBox {
private boolean openUpwards = false;
@Setter
private boolean openToTheRight = false;
private Double prefWidth = null;

public DropdownMenu(String defaultIconId, String activeIconId, boolean useIconOnly) {
defaultIcon = ImageUtil.getImageViewById(defaultIconId);
Expand Down Expand Up @@ -151,6 +152,10 @@ private void attachListeners() {
getStyleClass().add("dropdown-menu-active");
updateIcon(activeIcon);
isMenuShowing.setValue(true);
if (prefWidth != null && !contextMenu.getItems().isEmpty()
&& contextMenu.getItems().getFirst() instanceof DropdownMenuItem) {
updateMenuItemWidth();
}
});
contextMenu.setOnHidden(e -> {
getStyleClass().remove("dropdown-menu-active");
Expand All @@ -163,16 +168,24 @@ private void attachListeners() {
isFirstRun = true;
// Once the contextMenu has calculated the width on the first render time we update the items
// so that they all have the same size.
for (MenuItem item : contextMenu.getItems()) {
if (item instanceof DropdownMenuItem dropdownMenuItem) {
dropdownMenuItem.updateWidth(contextMenu.getWidth() - 18); // Remove margins
}
}
prefWidth = contextMenu.getWidth() - 18; // Remove margins
updateMenuItemWidth();
}
};
contextMenu.widthProperty().addListener(new WeakChangeListener<>(widthPropertyChangeListener));
}

private void updateMenuItemWidth() {
for (MenuItem item : contextMenu.getItems()) {
if (item instanceof DropdownBisqMenuItem dropdownBisqMenuItem) {
dropdownBisqMenuItem.updateWidth(prefWidth);
}
if (item instanceof DropdownMenuItem dropdownMenuItem) {
dropdownMenuItem.updateWidth(prefWidth);
}
}
}

private void updateIcon(ImageView newIcon) {
if (buttonIcon != newIcon) {
getChildren().remove(buttonIcon);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,48 +17,61 @@

package bisq.desktop.components.controls;

import bisq.desktop.common.utils.ImageUtil;
import javafx.event.ActionEvent;
import javafx.event.Event;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.CustomMenuItem;
import lombok.Getter;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;

@Getter
public class DropdownMenuItem extends CustomMenuItem {
private final BisqMenuItem bisqMenuItem;
public static final String ICON_CSS_STYLE = "menu-item-icon";

public DropdownMenuItem(String defaultIconId, String activeIconId, String text) {
bisqMenuItem = new BisqMenuItem(defaultIconId, activeIconId, text);
bisqMenuItem.getStyleClass().add("dropdown-menu-item-content");
setContent(bisqMenuItem);
private final HBox hBox;
private ImageView defaultIcon, activeIcon, buttonIcon;

// Using DropdownMenuItem.setOnAction leads to duplicate execution of the handler on MacOS 14.5 / M3.
// Might be a bug in the MacOS specific JavaFX libraries as other devs could not reproduce the issue.
// Using an eventFilter and consuming the event solves the issue.
// This happens only when bisqMenuItem is used inside the DropdownMenuItem
bisqMenuItem.addEventFilter(ActionEvent.ANY, Event::consume);
}
public DropdownMenuItem(String defaultIconId, String activeIconId, Node node) {
hBox = new HBox(10);
hBox.getStyleClass().add("dropdown-menu-item-content");

public DropdownMenuItem(String text) {
this(null, null, text);
}
if (defaultIconId != null && activeIconId != null) {
defaultIcon = ImageUtil.getImageViewById(defaultIconId);
activeIcon = ImageUtil.getImageViewById(activeIconId);
defaultIcon.getStyleClass().add(ICON_CSS_STYLE);
activeIcon.getStyleClass().add(ICON_CSS_STYLE);
buttonIcon = defaultIcon;
hBox.getChildren().add(buttonIcon);
attachListeners();
}

public DropdownMenuItem(String defaultIconId, String activeIconId) {
this(defaultIconId, activeIconId, "");
}
if (node != null) {
hBox.getChildren().add(node);
}

public void setLabelText(String text) {
bisqMenuItem.setText(text);
hBox.setAlignment(Pos.CENTER_LEFT);
hBox.getStyleClass().add("bisq-menu-item");
hBox.addEventFilter(ActionEvent.ANY, Event::consume);
setContent(hBox);
setHideOnClick(false);
}

public Double getWidth() {
return bisqMenuItem.getWidth();
public void updateWidth(Double width) {
hBox.setPrefWidth(width);
}

public void updateWidth(Double width) {
bisqMenuItem.setPrefWidth(width);
private void attachListeners() {
hBox.setOnMouseEntered(e -> updateIcon(activeIcon));
hBox.setOnMouseExited(e -> updateIcon(defaultIcon));
hBox.setOnMouseClicked(e -> updateIcon(defaultIcon));
}

public String getLabelText() {
return bisqMenuItem.getText();
private void updateIcon(ImageView newIcon) {
if (buttonIcon != newIcon) {
buttonIcon = newIcon;
hBox.getChildren().removeFirst();
hBox.getChildren().addFirst(buttonIcon);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import bisq.desktop.components.containers.Spacer;
import bisq.desktop.components.controls.BisqTooltip;
import bisq.desktop.components.controls.DropdownMenu;
import bisq.desktop.components.controls.DropdownMenuItem;
import bisq.desktop.components.controls.DropdownBisqMenuItem;
import bisq.desktop.components.controls.SearchBox;
import bisq.desktop.components.overlay.Popup;
import bisq.desktop.main.content.user.reputation.list.ReputationListView;
Expand Down Expand Up @@ -286,7 +286,7 @@ private void listItemsChanged() {

@ToString
@EqualsAndHashCode(onlyExplicitlyIncluded = true, callSuper = false)
public static final class FilterMenuItem<T> extends DropdownMenuItem implements Toggle {
public static final class FilterMenuItem<T> extends DropdownBisqMenuItem implements Toggle {
private static final PseudoClass SELECTED_PSEUDO_CLASS = PseudoClass.getPseudoClass("selected");

public static FilterMenuItem<ReputationListView.ListItem> getShowAllFilterMenuItem(ToggleGroup toggleGroup) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,7 @@ private void updateAppliedFiltersSectionStyles(boolean shouldShowAppliedFilters)
}

@Getter
private static final class SortAndFilterMarketsDropdownMenuItem<T> extends DropdownMenuItem {
private static final class SortAndFilterMarketsDropdownMenuItem<T> extends DropdownBisqMenuItem {
private static final PseudoClass SELECTED_PSEUDO_CLASS = PseudoClass.getPseudoClass("selected");

private final T menuItem;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import bisq.desktop.common.utils.ImageUtil;
import bisq.desktop.components.controls.BisqTooltip;
import bisq.desktop.components.controls.DropdownMenu;
import bisq.desktop.components.controls.DropdownBisqMenuItem;
import bisq.desktop.components.controls.DropdownMenuItem;
import bisq.desktop.components.table.BisqTableColumn;
import bisq.desktop.components.table.BisqTableView;
Expand All @@ -49,6 +50,7 @@
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.util.Callback;
import lombok.extern.slf4j.Slf4j;
Expand All @@ -63,6 +65,7 @@ public class OfferbookListView extends bisq.desktop.common.view.View<VBox, Offer
private static final double COLLAPSED_LIST_WIDTH = BisqEasyOfferbookView.COLLAPSED_LIST_WIDTH;
private static final double HEADER_HEIGHT = BaseChatView.HEADER_HEIGHT;
private static final double LIST_CELL_HEIGHT = BisqEasyOfferbookView.LIST_CELL_HEIGHT;
private static final String ACTIVE_PAYMENT_FILTER_CLASS = "active-payment-filter";

private final Label title;
private final BisqTableView<OfferbookListItem> tableView;
Expand All @@ -71,9 +74,10 @@ public class OfferbookListView extends bisq.desktop.common.view.View<VBox, Offer
private final ImageView offerListWhiteIcon, offerListGreyIcon, offerListGreenIcon;
private final DropdownMenu offerDirectionFilterMenu, paymentsFilterMenu;
private final ListChangeListener<FiatPaymentMethod> listChangeListener;
private DropdownMenuItem buyFromOffers, sellToOffers;
private DropdownBisqMenuItem buyFromOffers, sellToOffers;
private Label offerDirectionFilterLabel, paymentsFilterLabel;
private Subscription showOfferListExpandedPin, showBuyFromOffersPin, offerListTableViewSelectionPin;
private Subscription showOfferListExpandedPin, showBuyFromOffersPin,
offerListTableViewSelectionPin, activeMarketPaymentsCountPin;

OfferbookListView(OfferbookListModel model, OfferbookListController controller) {
super(new VBox(), model, controller);
Expand Down Expand Up @@ -174,6 +178,16 @@ protected void onViewAttached() {
}
});

activeMarketPaymentsCountPin = EasyBind.subscribe(model.getActiveMarketPaymentsCount(), count -> {
if (count.intValue() != 0) {
if (!paymentsFilterLabel.getStyleClass().contains(ACTIVE_PAYMENT_FILTER_CLASS)) {
paymentsFilterLabel.getStyleClass().add(ACTIVE_PAYMENT_FILTER_CLASS);
}
} else {
paymentsFilterLabel.getStyleClass().remove(ACTIVE_PAYMENT_FILTER_CLASS);
}
});

model.getAvailableMarketPayments().addListener(listChangeListener);
updateMarketPaymentFilters();

Expand All @@ -192,6 +206,7 @@ protected void onViewDetached() {
showOfferListExpandedPin.unsubscribe();
offerListTableViewSelectionPin.unsubscribe();
showBuyFromOffersPin.unsubscribe();
activeMarketPaymentsCountPin.unsubscribe();

model.getAvailableMarketPayments().removeListener(listChangeListener);

Expand All @@ -212,8 +227,8 @@ private DropdownMenu createAndGetOffersDirectionFilterMenu() {
menu.setOpenToTheRight(true);
offerDirectionFilterLabel = new Label();
menu.setLabel(offerDirectionFilterLabel);
buyFromOffers = new DropdownMenuItem(Res.get("bisqEasy.offerbook.offerList.table.filters.offerDirection.buyFrom"));
sellToOffers = new DropdownMenuItem(Res.get("bisqEasy.offerbook.offerList.table.filters.offerDirection.sellTo"));
buyFromOffers = new DropdownBisqMenuItem(Res.get("bisqEasy.offerbook.offerList.table.filters.offerDirection.buyFrom"));
sellToOffers = new DropdownBisqMenuItem(Res.get("bisqEasy.offerbook.offerList.table.filters.offerDirection.sellTo"));
menu.addMenuItems(buyFromOffers, sellToOffers);
return menu;
}
Expand All @@ -231,15 +246,22 @@ private void updateMarketPaymentFilters() {
cleanUpPaymentsFilterMenu();

model.getAvailableMarketPayments().forEach(payment -> {
PaymentMenuItem item = new PaymentMenuItem(payment.getDisplayString());
ImageView paymentIcon = ImageUtil.getImageViewById(payment.getName());
Label paymentLabel = new Label(payment.getDisplayString(), paymentIcon);
paymentLabel.setGraphicTextGap(10);
PaymentMenuItem item = new PaymentMenuItem(paymentLabel);
item.setOnAction(e -> {
item.updateSelection(!item.isSelected());
controller.toggleMethodFilter(payment, item.isSelected());
});
paymentsFilterMenu.addMenuItems(item);
});

PaymentMenuItem customItem = new PaymentMenuItem(Res.get("bisqEasy.offerbook.offerList.table.filters.paymentMethods.customMethod"));
StackPane customPaymentIcon = BisqEasyViewUtils.getCustomPaymentMethodIcon("C");
Label customPaymentLabel = new Label(
Res.get("bisqEasy.offerbook.offerList.table.filters.paymentMethods.customPayments"), customPaymentIcon);
customPaymentLabel.setGraphicTextGap(10);
PaymentMenuItem customItem = new PaymentMenuItem(customPaymentLabel);
customItem.setOnAction(e -> {
customItem.updateSelection(!customItem.isSelected());
controller.toggleCustomMethodFilter(customItem.isSelected());
Expand Down Expand Up @@ -469,9 +491,8 @@ protected void updateItem(OfferbookListItem item, boolean empty) {
private static final class PaymentMenuItem extends DropdownMenuItem {
private static final PseudoClass SELECTED_PSEUDO_CLASS = PseudoClass.getPseudoClass("selected");

PaymentMenuItem(String displayName) {
// TODO: Update code so that we can pass label instead of text
super("check-white", "check-white", displayName);
private PaymentMenuItem(Label displayLabel) {
super("check-white", "check-white", displayLabel);

getStyleClass().add("dropdown-menu-item");
updateSelection(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import bisq.desktop.common.utils.ImageUtil;
import bisq.desktop.common.view.NavigationView;
import bisq.desktop.components.controls.DropdownMenu;
import bisq.desktop.components.controls.DropdownMenuItem;
import bisq.desktop.components.controls.DropdownBisqMenuItem;
import bisq.desktop.components.controls.SearchBox;
import bisq.i18n.Res;
import javafx.scene.control.Label;
Expand All @@ -40,7 +40,7 @@ public abstract class BaseChatView extends NavigationView<ScrollPane, BaseChatMo
protected final Label channelTitle = new Label();
protected final Label channelDescription = new Label();
protected Label channelIcon = new Label();
protected DropdownMenuItem helpButton, infoButton;
protected DropdownBisqMenuItem helpButton, infoButton;
protected final VBox sideBar = new VBox();
protected final VBox centerVBox = new VBox();
protected final HBox titleHBox = new HBox(10);
Expand Down Expand Up @@ -72,8 +72,8 @@ public BaseChatView(BaseChatModel model,
}

private void setUpHeaderDropdownMenu() {
helpButton = new DropdownMenuItem("icon-help-grey", "icon-help-white");
infoButton = new DropdownMenuItem("icon-info-grey", "icon-info-white",
helpButton = new DropdownBisqMenuItem("icon-help-grey", "icon-help-white");
infoButton = new DropdownBisqMenuItem("icon-info-grey", "icon-info-white",
Res.get("chat.dropdownMenu.channelInfo"));
headerDropdownMenu.addMenuItems(helpButton, infoButton);
headerDropdownMenu.setTooltip(Res.get("chat.dropdownMenu.tooltip"));
Expand Down
Loading

0 comments on commit 402543c

Please sign in to comment.