diff --git a/src/main/java/bisq/desktop/components/AutoTooltipTableColumn.java b/src/main/java/bisq/desktop/components/AutoTooltipTableColumn.java index 584b27b27d7..9f20b5bfae2 100644 --- a/src/main/java/bisq/desktop/components/AutoTooltipTableColumn.java +++ b/src/main/java/bisq/desktop/components/AutoTooltipTableColumn.java @@ -17,13 +17,86 @@ package bisq.desktop.components; +import bisq.common.UserThread; + +import de.jensd.fx.fontawesome.AwesomeDude; +import de.jensd.fx.fontawesome.AwesomeIcon; + +import org.controlsfx.control.PopOver; + +import javafx.scene.Node; +import javafx.scene.control.Label; import javafx.scene.control.TableColumn; +import javafx.scene.layout.HBox; + +import javafx.geometry.Insets; + +import java.util.concurrent.TimeUnit; public class AutoTooltipTableColumn extends TableColumn { + private Label helpIcon; + private Boolean hidePopover; + private PopOver infoPopover; + + public AutoTooltipTableColumn(String text) { super(); - setGraphic(new AutoTooltipLabel(text)); + setTitle(text); + } + + public AutoTooltipTableColumn(String text, String help) { + + setTitleWithHelpText(text, help); + } + + public void setTitle(String title) { + setGraphic(new AutoTooltipLabel(title)); + } + + public void setTitleWithHelpText(String title, String help) { + + final AutoTooltipLabel label = new AutoTooltipLabel(title); + + helpIcon = new Label(); + AwesomeDude.setIcon(helpIcon, AwesomeIcon.QUESTION_SIGN, "1em"); + helpIcon.setOpacity(0.4); + helpIcon.setOnMouseEntered(e -> { + hidePopover = false; + final Label helpLabel = new Label(help); + helpLabel.setMaxWidth(300); + helpLabel.setWrapText(true); + helpLabel.setPadding(new Insets(10)); + showInfoPopOver(helpLabel); + }); + helpIcon.setOnMouseExited(e -> { + if (infoPopover != null) + infoPopover.hide(); + hidePopover = true; + UserThread.runAfter(() -> { + if (hidePopover) { + infoPopover.hide(); + hidePopover = false; + } + }, 250, TimeUnit.MILLISECONDS); + }); + + final HBox hBox = new HBox(label, helpIcon); + hBox.setStyle("-fx-alignment: center"); + hBox.setSpacing(4); + setGraphic(hBox); + } + + private void showInfoPopOver(Node node) { + node.getStyleClass().add("default-text"); + + infoPopover = new PopOver(node); + if (helpIcon.getScene() != null) { + infoPopover.setDetachable(false); + infoPopover.setArrowLocation(PopOver.ArrowLocation.LEFT_CENTER); + + infoPopover.show(helpIcon, -10); + } } } diff --git a/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookView.java b/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookView.java index 4c24d865c6b..8152fdfc2b0 100644 --- a/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookView.java +++ b/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookView.java @@ -55,6 +55,8 @@ import bisq.network.p2p.NodeAddress; +import bisq.common.util.Tuple3; + import org.bitcoinj.core.Coin; import com.google.inject.name.Named; @@ -73,6 +75,7 @@ import javafx.scene.control.Tooltip; import javafx.scene.image.ImageView; import javafx.scene.layout.GridPane; +import javafx.scene.layout.HBox; import javafx.scene.layout.Priority; import javafx.geometry.HPos; @@ -96,6 +99,7 @@ import java.util.Optional; import static bisq.desktop.util.FormBuilder.addButton; +import static bisq.desktop.util.FormBuilder.addHBoxLabelComboBox; import static bisq.desktop.util.FormBuilder.addLabelComboBox; import static bisq.desktop.util.FormBuilder.addTitledGroupBg; @@ -111,7 +115,7 @@ public class OfferBookView extends ActivatableViewAndModel currencyComboBox; private ComboBox paymentMethodComboBox; private Button createOfferButton; - private TableColumn amountColumn, volumeColumn, marketColumn, priceColumn; + private AutoTooltipTableColumn amountColumn, volumeColumn, marketColumn, priceColumn; private TableView tableView; private OfferView.OfferActionHandler offerActionHandler; @@ -147,12 +151,16 @@ public void initialize() { addTitledGroupBg(root, gridRow, 3, Res.get("offerbook.availableOffers")); - //noinspection unchecked - currencyComboBox = addLabelComboBox(root, gridRow, Res.get("offerbook.filterByCurrency"), Layout.FIRST_ROW_DISTANCE).second; + final Tuple3 filterBoxTuple = addHBoxLabelComboBox(root, gridRow, Res.get("offerbook.filterByCurrency"), Layout.FIRST_ROW_DISTANCE); + final HBox filterBox = filterBoxTuple.first; + currencyComboBox = filterBoxTuple.third; currencyComboBox.setPromptText(Res.get("list.currency.select")); //noinspection unchecked - paymentMethodComboBox = addLabelComboBox(root, ++gridRow, Res.getWithCol("offerbook.filterByPaymentMethod")).second; + paymentMethodComboBox = new ComboBox<>(); + final Label paymentMethodLabel = new AutoTooltipLabel(Res.getWithCol("offerbook.filterByPaymentMethod")); + paymentMethodLabel.setPadding(new Insets(0,0,0,10)); + filterBox.getChildren().addAll(paymentMethodLabel, paymentMethodComboBox); paymentMethodComboBox.setPromptText(Res.get("shared.selectPaymentMethod")); paymentMethodComboBox.setVisibleRowCount(20); paymentMethodComboBox.setConverter(new StringConverter() { @@ -192,9 +200,9 @@ public PaymentMethod fromString(String s) { tableView.getColumns().add(volumeColumn); TableColumn paymentMethodColumn = getPaymentMethodColumn(); tableView.getColumns().add(paymentMethodColumn); - tableView.getColumns().add(getActionColumn()); TableColumn avatarColumn = getAvatarColumn(); tableView.getColumns().add(avatarColumn); + tableView.getColumns().add(getActionColumn()); tableView.getSortOrder().add(priceColumn); tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY); @@ -243,9 +251,7 @@ public PaymentMethod fromString(String s) { // Fixes incorrect ordering of Available offers: // https://github.com/bisq-network/exchange/issues/588 - priceFeedUpdateCounterListener = (observable, oldValue, newValue) -> { - tableView.sort(); - }; + priceFeedUpdateCounterListener = (observable, oldValue, newValue) -> tableView.sort(); } @Override @@ -266,9 +272,7 @@ protected void activate() { volumeColumn.sortableProperty().bind(model.showAllTradeCurrenciesProperty.not()); priceColumn.sortableProperty().bind(model.showAllTradeCurrenciesProperty.not()); model.getOfferList().comparatorProperty().bind(tableView.comparatorProperty()); - model.priceSortTypeProperty.addListener((observable, oldValue, newValue) -> { - priceColumn.setSortType(newValue); - }); + model.priceSortTypeProperty.addListener((observable, oldValue, newValue) -> priceColumn.setSortType(newValue)); priceColumn.setSortType(model.priceSortTypeProperty.get()); paymentMethodComboBox.setItems(model.getPaymentMethods()); @@ -285,14 +289,14 @@ protected void activate() { (showAll, code) -> { setDirectionTitles(); if (showAll) { - volumeColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.amountMinMax"))); - priceColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.price"))); + volumeColumn.setTitleWithHelpText(Res.get("shared.amountMinMax"), Res.get("shared.amountHelp")); + priceColumn.setTitle(Res.get("shared.price")); if (!tableView.getColumns().contains(marketColumn)) tableView.getColumns().add(0, marketColumn); } else { - volumeColumn.setGraphic(new AutoTooltipLabel(Res.get("offerbook.volume", code))); - priceColumn.setGraphic(new AutoTooltipLabel(formatter.getPriceWithCurrencyCode(code))); + volumeColumn.setTitleWithHelpText(Res.get("offerbook.volume", code),Res.get("shared.amountHelp")); + priceColumn.setTitle(formatter.getPriceWithCurrencyCode(code)); if (tableView.getColumns().contains(marketColumn)) tableView.getColumns().remove(marketColumn); @@ -517,8 +521,8 @@ private void openPopupForMissingAccountSetup(String headLine, String message, Cl // Table /////////////////////////////////////////////////////////////////////////////////////////// - private TableColumn getAmountColumn() { - TableColumn column = new AutoTooltipTableColumn(Res.get("shared.BTCMinMax")); + private AutoTooltipTableColumn getAmountColumn() { + AutoTooltipTableColumn column = new AutoTooltipTableColumn<>(Res.get("shared.BTCMinMax"), Res.get("shared.amountHelp")); column.setMinWidth(100); column.getStyleClass().add("number-column"); column.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue())); @@ -543,8 +547,8 @@ public void updateItem(final OfferBookListItem item, boolean empty) { return column; } - private TableColumn getMarketColumn() { - TableColumn column = new AutoTooltipTableColumn(Res.get("shared.market")) { + private AutoTooltipTableColumn getMarketColumn() { + AutoTooltipTableColumn column = new AutoTooltipTableColumn(Res.get("shared.market")) { { setMinWidth(40); } @@ -573,8 +577,8 @@ public void updateItem(final OfferBookListItem item, boolean empty) { return column; } - private TableColumn getPriceColumn() { - TableColumn column = new TableColumn() { + private AutoTooltipTableColumn getPriceColumn() { + AutoTooltipTableColumn column = new AutoTooltipTableColumn("") { { setMinWidth(100); } @@ -643,8 +647,8 @@ public void updateItem(final OfferBookListItem item, boolean empty) { return column; } - private TableColumn getVolumeColumn() { - TableColumn column = new TableColumn() { + private AutoTooltipTableColumn getVolumeColumn() { + AutoTooltipTableColumn column = new AutoTooltipTableColumn("") { { setMinWidth(125); } @@ -734,7 +738,7 @@ public void updateItem(final OfferBookListItem item, boolean empty) { } private TableColumn getActionColumn() { - TableColumn column = new AutoTooltipTableColumn(Res.get("offerbook.wantTo")) { + TableColumn column = new AutoTooltipTableColumn("") { { setMinWidth(80); setSortable(false); @@ -862,10 +866,10 @@ public void updateItem(final OfferBookListItem newItem, boolean empty) { } private TableColumn getAvatarColumn() { - TableColumn column = new AutoTooltipTableColumn("") { + TableColumn column = new AutoTooltipTableColumn(Res.get("offerbook.trader")) { { - setMinWidth(40); - setMaxWidth(40); + setMinWidth(80); + setMaxWidth(80); setSortable(true); } }; diff --git a/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookViewModel.java b/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookViewModel.java index 30a7f4aa524..77767e6c505 100644 --- a/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookViewModel.java +++ b/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookViewModel.java @@ -456,7 +456,7 @@ else if (offer.getPaymentMethod().equals(PaymentMethod.SPECIFIC_BANKS)) } String getDirectionLabel(Offer offer) { - return formatter.getDirectionWithCode(offer.getMirroredDirection(), offer.getCurrencyCode()); + return Res.get("offerbook.takeOffer"); } String getDirectionLabelTooltip(Offer offer) { diff --git a/src/main/java/bisq/desktop/util/FormBuilder.java b/src/main/java/bisq/desktop/util/FormBuilder.java index 011623c90a1..a167e6a88fc 100644 --- a/src/main/java/bisq/desktop/util/FormBuilder.java +++ b/src/main/java/bisq/desktop/util/FormBuilder.java @@ -657,6 +657,26 @@ public static Tuple2 addLabelSearchComboBox(GridPane grid return new Tuple2<>(label, comboBox); } + /////////////////////////////////////////////////////////////////////////////////////////// + // HBox + Label + ComboBox + /////////////////////////////////////////////////////////////////////////////////////////// + + public static Tuple3 addHBoxLabelComboBox(GridPane gridPane, int rowIndex, String title, double top) { + HBox hBox = new HBox(); + hBox.setAlignment(Pos.CENTER_LEFT); + hBox.setSpacing(4); + + final AutoTooltipLabel label = new AutoTooltipLabel(title); + final ComboBox comboBox = new ComboBox<>(); + hBox.getChildren().addAll(label, comboBox); + + GridPane.setRowIndex(hBox, rowIndex); + GridPane.setColumnSpan(hBox, 2); + GridPane.setMargin(hBox, new Insets(top, 0,0,24)); + gridPane.getChildren().add(hBox); + + return new Tuple3<>(hBox, label, comboBox); + } /////////////////////////////////////////////////////////////////////////////////////////// // Label + ComboBox + ComboBox