Skip to content

Commit

Permalink
Merge pull request #3211 from stejbac/fix-info-pane-flicker
Browse files Browse the repository at this point in the history
Prevent tooltip popover flicker upon mouseover
  • Loading branch information
ripcurlx authored Nov 12, 2019
2 parents e0de998 + dd56b3a commit 3d5ba5b
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 102 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -28,14 +27,10 @@
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();
Expand All @@ -53,46 +48,36 @@ public void setTitle(String 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);
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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@

import bisq.desktop.components.controlsfx.control.PopOver;

import bisq.common.UserThread;

import de.jensd.fx.fontawesome.AwesomeIcon;
import de.jensd.fx.glyphs.GlyphIcons;

Expand All @@ -30,16 +28,13 @@

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) {
Expand Down Expand Up @@ -82,42 +77,31 @@ public void hideIcon() {
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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -29,8 +28,6 @@
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;
Expand All @@ -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);
Expand Down Expand Up @@ -161,34 +157,22 @@ private void setActionHandlers(Node node) {
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);
popover.setArrowIndent(5);

popover.show(currentIcon, -17);
}
return popover;
}
}
29 changes: 7 additions & 22 deletions desktop/src/main/java/bisq/desktop/components/InfoTextField.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -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);
Expand Down Expand Up @@ -124,34 +121,22 @@ private void setActionHandlers(Node node) {
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);
popover.setArrowIndent(5);

popover.show(currentIcon, -17);
}
return popover;
}

///////////////////////////////////////////////////////////////////////////////////////////
Expand Down
73 changes: 73 additions & 0 deletions desktop/src/main/java/bisq/desktop/components/PopOverWrapper.java
Original file line number Diff line number Diff line change
@@ -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);
}
}
}

0 comments on commit 3d5ba5b

Please sign in to comment.