mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-24 23:18:17 +01:00
Merge pull request #3211 from stejbac/fix-info-pane-flicker
Prevent tooltip popover flicker upon mouseover
This commit is contained in:
commit
3d5ba5b380
5 changed files with 113 additions and 102 deletions
|
@ -17,7 +17,6 @@
|
|||
|
||||
package bisq.desktop.components;
|
||||
|
||||
import bisq.common.UserThread;
|
||||
import bisq.desktop.components.controlsfx.control.PopOver;
|
||||
|
||||
import de.jensd.fx.fontawesome.AwesomeDude;
|
||||
|
@ -28,14 +27,10 @@ import javafx.scene.control.Label;
|
|||
import javafx.scene.control.TableColumn;
|
||||
import javafx.scene.layout.HBox;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class AutoTooltipTableColumn<S, T> extends TableColumn<S, T> {
|
||||
|
||||
private Label helpIcon;
|
||||
private Boolean hidePopover;
|
||||
private PopOver infoPopover;
|
||||
|
||||
private PopOverWrapper popoverWrapper = new PopOverWrapper();
|
||||
|
||||
public AutoTooltipTableColumn(String text) {
|
||||
super();
|
||||
|
@ -53,46 +48,36 @@ public class AutoTooltipTableColumn<S, T> extends TableColumn<S, T> {
|
|||
}
|
||||
|
||||
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);
|
||||
showInfoPopOver(helpLabel);
|
||||
});
|
||||
helpIcon.setOnMouseExited(e -> {
|
||||
if (infoPopover != null)
|
||||
infoPopover.hide();
|
||||
hidePopover = true;
|
||||
UserThread.runAfter(() -> {
|
||||
if (hidePopover) {
|
||||
infoPopover.hide();
|
||||
hidePopover = false;
|
||||
}
|
||||
}, 250, TimeUnit.MILLISECONDS);
|
||||
});
|
||||
helpIcon.setOnMouseEntered(e -> popoverWrapper.showPopOver(() -> createInfoPopOver(help)));
|
||||
helpIcon.setOnMouseExited(e -> popoverWrapper.hidePopOver());
|
||||
|
||||
final AutoTooltipLabel label = new AutoTooltipLabel(title);
|
||||
final HBox hBox = new HBox(label, helpIcon);
|
||||
hBox.setStyle("-fx-alignment: center-left");
|
||||
hBox.setSpacing(4);
|
||||
setGraphic(hBox);
|
||||
}
|
||||
|
||||
private void showInfoPopOver(Node node) {
|
||||
private PopOver createInfoPopOver(String help) {
|
||||
Label helpLabel = new Label(help);
|
||||
helpLabel.setMaxWidth(300);
|
||||
helpLabel.setWrapText(true);
|
||||
return createInfoPopOver(helpLabel);
|
||||
}
|
||||
|
||||
private PopOver createInfoPopOver(Node node) {
|
||||
node.getStyleClass().add("default-text");
|
||||
|
||||
infoPopover = new PopOver(node);
|
||||
PopOver infoPopover = new PopOver(node);
|
||||
if (helpIcon.getScene() != null) {
|
||||
infoPopover.setDetachable(false);
|
||||
infoPopover.setArrowLocation(PopOver.ArrowLocation.LEFT_CENTER);
|
||||
|
||||
infoPopover.show(helpIcon, -10);
|
||||
}
|
||||
return infoPopover;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,8 +19,6 @@ package bisq.desktop.components;
|
|||
|
||||
import bisq.desktop.components.controlsfx.control.PopOver;
|
||||
|
||||
import bisq.common.UserThread;
|
||||
|
||||
import de.jensd.fx.fontawesome.AwesomeIcon;
|
||||
import de.jensd.fx.glyphs.GlyphIcons;
|
||||
|
||||
|
@ -30,16 +28,13 @@ import javafx.scene.control.Label;
|
|||
|
||||
import javafx.geometry.Insets;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static bisq.desktop.util.FormBuilder.getIcon;
|
||||
|
||||
public class InfoAutoTooltipLabel extends AutoTooltipLabel {
|
||||
|
||||
public static final int DEFAULT_WIDTH = 300;
|
||||
private Node textIcon;
|
||||
private Boolean hidePopover;
|
||||
private PopOver infoPopover;
|
||||
private PopOverWrapper popoverWrapper = new PopOverWrapper();
|
||||
private ContentDisplay contentDisplay;
|
||||
|
||||
public InfoAutoTooltipLabel(String text, GlyphIcons icon, ContentDisplay contentDisplay, String info) {
|
||||
|
@ -82,42 +77,31 @@ public class InfoAutoTooltipLabel extends AutoTooltipLabel {
|
|||
private void positionAndActivateIcon(ContentDisplay contentDisplay, String info, double width) {
|
||||
textIcon.setOpacity(0.4);
|
||||
textIcon.getStyleClass().add("tooltip-icon");
|
||||
|
||||
textIcon.setOnMouseEntered(e -> {
|
||||
hidePopover = false;
|
||||
final Label helpLabel = new Label(info);
|
||||
helpLabel.setMaxWidth(width);
|
||||
helpLabel.setWrapText(true);
|
||||
helpLabel.setPadding(new Insets(10));
|
||||
showInfoPopOver(helpLabel);
|
||||
});
|
||||
|
||||
textIcon.setOnMouseExited(e -> {
|
||||
if (infoPopover != null)
|
||||
infoPopover.hide();
|
||||
hidePopover = true;
|
||||
UserThread.runAfter(() -> {
|
||||
if (hidePopover) {
|
||||
infoPopover.hide();
|
||||
hidePopover = false;
|
||||
}
|
||||
}, 250, TimeUnit.MILLISECONDS);
|
||||
});
|
||||
textIcon.setOnMouseEntered(e -> popoverWrapper.showPopOver(() -> createInfoPopOver(info, width)));
|
||||
textIcon.setOnMouseExited(e -> popoverWrapper.hidePopOver());
|
||||
|
||||
setGraphic(textIcon);
|
||||
setContentDisplay(contentDisplay);
|
||||
}
|
||||
|
||||
private PopOver createInfoPopOver(String info, double width) {
|
||||
Label helpLabel = new Label(info);
|
||||
helpLabel.setMaxWidth(width);
|
||||
helpLabel.setWrapText(true);
|
||||
helpLabel.setPadding(new Insets(10));
|
||||
return createInfoPopOver(helpLabel);
|
||||
}
|
||||
|
||||
private void showInfoPopOver(Node node) {
|
||||
private PopOver createInfoPopOver(Node node) {
|
||||
node.getStyleClass().add("default-text");
|
||||
|
||||
infoPopover = new PopOver(node);
|
||||
PopOver infoPopover = new PopOver(node);
|
||||
if (textIcon.getScene() != null) {
|
||||
infoPopover.setDetachable(false);
|
||||
infoPopover.setArrowLocation(PopOver.ArrowLocation.LEFT_CENTER);
|
||||
|
||||
infoPopover.show(textIcon, -10);
|
||||
}
|
||||
return infoPopover;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
|
||||
package bisq.desktop.components;
|
||||
|
||||
import bisq.common.UserThread;
|
||||
import bisq.desktop.components.controlsfx.control.PopOver;
|
||||
|
||||
import de.jensd.fx.fontawesome.AwesomeIcon;
|
||||
|
@ -29,8 +28,6 @@ import javafx.scene.layout.AnchorPane;
|
|||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.beans.property.StringProperty;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
import static bisq.desktop.util.FormBuilder.getIcon;
|
||||
|
@ -49,8 +46,7 @@ public class InfoInputTextField extends AnchorPane {
|
|||
private final Label privacyIcon;
|
||||
|
||||
private Label currentIcon;
|
||||
private PopOver popover;
|
||||
private boolean hidePopover;
|
||||
private PopOverWrapper popoverWrapper = new PopOverWrapper();
|
||||
|
||||
public InfoInputTextField() {
|
||||
this(0);
|
||||
|
@ -161,28 +157,15 @@ public class InfoInputTextField extends AnchorPane {
|
|||
currentIcon.setVisible(true);
|
||||
|
||||
// As we don't use binding here we need to recreate it on mouse over to reflect the current state
|
||||
currentIcon.setOnMouseEntered(e -> {
|
||||
hidePopover = false;
|
||||
showPopOver(node);
|
||||
});
|
||||
currentIcon.setOnMouseExited(e -> {
|
||||
if (popover != null)
|
||||
popover.hide();
|
||||
hidePopover = true;
|
||||
UserThread.runAfter(() -> {
|
||||
if (hidePopover) {
|
||||
popover.hide();
|
||||
hidePopover = false;
|
||||
}
|
||||
}, 250, TimeUnit.MILLISECONDS);
|
||||
});
|
||||
currentIcon.setOnMouseEntered(e -> popoverWrapper.showPopOver(() -> createPopOver(node)));
|
||||
currentIcon.setOnMouseExited(e -> popoverWrapper.hidePopOver());
|
||||
}
|
||||
}
|
||||
|
||||
private void showPopOver(Node node) {
|
||||
private PopOver createPopOver(Node node) {
|
||||
node.getStyleClass().add("default-text");
|
||||
|
||||
popover = new PopOver(node);
|
||||
PopOver popover = new PopOver(node);
|
||||
if (currentIcon.getScene() != null) {
|
||||
popover.setDetachable(false);
|
||||
popover.setArrowLocation(PopOver.ArrowLocation.LEFT_TOP);
|
||||
|
@ -190,5 +173,6 @@ public class InfoInputTextField extends AnchorPane {
|
|||
|
||||
popover.show(currentIcon, -17);
|
||||
}
|
||||
return popover;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,8 +34,6 @@ import javafx.scene.text.Text;
|
|||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.beans.property.StringProperty;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -53,13 +51,12 @@ public class InfoTextField extends AnchorPane {
|
|||
private final StringProperty text = new SimpleStringProperty();
|
||||
protected final Label infoIcon;
|
||||
private Label currentIcon;
|
||||
private Boolean hidePopover;
|
||||
private PopOver popover;
|
||||
private PopOverWrapper popoverWrapper = new PopOverWrapper();
|
||||
private PopOver.ArrowLocation arrowLocation;
|
||||
|
||||
public InfoTextField() {
|
||||
|
||||
arrowLocation = PopOver.ArrowLocation.RIGHT_TOP;;
|
||||
arrowLocation = PopOver.ArrowLocation.RIGHT_TOP;
|
||||
textField = new BisqTextField();
|
||||
textField.setLabelFloat(true);
|
||||
textField.setEditable(false);
|
||||
|
@ -124,27 +121,14 @@ public class InfoTextField extends AnchorPane {
|
|||
currentIcon.setVisible(true);
|
||||
|
||||
// As we don't use binding here we need to recreate it on mouse over to reflect the current state
|
||||
currentIcon.setOnMouseEntered(e -> {
|
||||
hidePopover = false;
|
||||
showPopOver(node);
|
||||
});
|
||||
currentIcon.setOnMouseExited(e -> {
|
||||
if (popover != null)
|
||||
popover.hide();
|
||||
hidePopover = true;
|
||||
UserThread.runAfter(() -> {
|
||||
if (hidePopover) {
|
||||
popover.hide();
|
||||
hidePopover = false;
|
||||
}
|
||||
}, 250, TimeUnit.MILLISECONDS);
|
||||
});
|
||||
currentIcon.setOnMouseEntered(e -> popoverWrapper.showPopOver(() -> createPopOver(node)));
|
||||
currentIcon.setOnMouseExited(e -> popoverWrapper.hidePopOver());
|
||||
}
|
||||
|
||||
private void showPopOver(Node node) {
|
||||
private PopOver createPopOver(Node node) {
|
||||
node.getStyleClass().add("default-text");
|
||||
|
||||
popover = new PopOver(node);
|
||||
PopOver popover = new PopOver(node);
|
||||
if (currentIcon.getScene() != null) {
|
||||
popover.setDetachable(false);
|
||||
popover.setArrowLocation(arrowLocation);
|
||||
|
@ -152,6 +136,7 @@ public class InfoTextField extends AnchorPane {
|
|||
|
||||
popover.show(currentIcon, -17);
|
||||
}
|
||||
return popover;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
import bisq.desktop.components.controlsfx.control.PopOver;
|
||||
|
||||
import bisq.common.UserThread;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class PopOverWrapper {
|
||||
|
||||
private PopOver popover;
|
||||
private Supplier<PopOver> popoverSupplier;
|
||||
private boolean hidePopover;
|
||||
private PopOverState state = PopOverState.HIDDEN;
|
||||
|
||||
enum PopOverState {
|
||||
HIDDEN, SHOWING, SHOWN, HIDING
|
||||
}
|
||||
|
||||
public void showPopOver(Supplier<PopOver> popoverSupplier) {
|
||||
this.popoverSupplier = popoverSupplier;
|
||||
hidePopover = false;
|
||||
|
||||
if (state == PopOverState.HIDDEN) {
|
||||
state = PopOverState.SHOWING;
|
||||
popover = popoverSupplier.get();
|
||||
|
||||
UserThread.runAfter(() -> {
|
||||
state = PopOverState.SHOWN;
|
||||
if (hidePopover) {
|
||||
// For some reason, this can result in a brief flicker when invoked
|
||||
// from a 'runAfter' callback, rather than directly. So make the delay
|
||||
// very short (25ms) so that we don't reach here often:
|
||||
hidePopOver();
|
||||
}
|
||||
}, 25, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
public void hidePopOver() {
|
||||
hidePopover = true;
|
||||
|
||||
if (state == PopOverState.SHOWN) {
|
||||
state = PopOverState.HIDING;
|
||||
popover.hide();
|
||||
|
||||
UserThread.runAfter(() -> {
|
||||
state = PopOverState.HIDDEN;
|
||||
if (!hidePopover) {
|
||||
showPopOver(popoverSupplier);
|
||||
}
|
||||
}, 250, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue