Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 27 additions & 5 deletions HMCL/src/main/java/com/jfoenix/controls/JFXPopup.java
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,8 @@ public void show(Node node, PopupVPosition vAlign, PopupHPosition hAlign, double
}

public void show(Node node, PopupVPosition vAlign, PopupHPosition hAlign, double initOffsetX, double initOffsetY, boolean attachToNode) {
if (!isShowing()) {
boolean relocate = cancelCloseAnimation();
if (!isShowing() || relocate) {
Scene scene = node.getScene();
if (scene == null || scene.getWindow() == null) {
throw new IllegalStateException("Can not show popup. The node must be attached to a scene/window.");
Expand All @@ -144,18 +145,23 @@ public void show(Node node, PopupVPosition vAlign, PopupHPosition hAlign, double
double anchorX = parent.getX() + scene.getX() + origin.getX() + (hAlign == PopupHPosition.RIGHT ? ((Region) node).getWidth() : 0);
double anchorY = parent.getY() + origin.getY() + scene.getY() + (vAlign == PopupVPosition.BOTTOM ? ((Region) node).getHeight() : 0);

if (attachToNode)
if (relocate) {
setAnchorX(anchorX);
setAnchorY(anchorY);
} else if (attachToNode) {
this.show(node, anchorX, anchorY);
else
} else {
this.show(parent, anchorX, anchorY);
}

((JFXPopupSkin) getSkin()).reset(vAlign, isRTL ? hAlign.getOpposite() : hAlign, isRTL ? -initOffsetX : initOffsetX, initOffsetY);
Platform.runLater(() -> ((JFXPopupSkin) getSkin()).animate());
}
}

public void show(Window window, double x, double y, PopupVPosition vAlign, PopupHPosition hAlign, double initOffsetX, double initOffsetY) {
if (!isShowing()) {
boolean relocate = cancelCloseAnimation();
if (!isShowing() || relocate) {
if (window == null) {
throw new IllegalStateException("Can not show popup. The node must be attached to a scene/window.");
}
Expand All @@ -168,10 +174,26 @@ public void show(Window window, double x, double y, PopupVPosition vAlign, Popup
}
}

public boolean cancelCloseAnimation() {
return isShowing() && getSkin() instanceof JFXPopupSkin skin && skin.cancelCloseAnimation();
}

@Override
public void hide() {
if (!(getSkin() instanceof JFXPopupSkin skin)) {
super.hide();
return;
}

if (isShowing()) {
skin.animateClose(this::hideImmediately);
Comment thread
Wulian233 marked this conversation as resolved.
} else {
skin.init();
}
}

private void hideImmediately() {
super.hide();
((JFXPopupSkin) getSkin()).init();
}

/***************************************************************************
Expand Down
60 changes: 59 additions & 1 deletion HMCL/src/main/java/com/jfoenix/skins/JFXPopupSkin.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@
import javafx.animation.Animation.Status;
import javafx.scene.Node;
import javafx.scene.control.Skin;
import javafx.scene.layout.*;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;
import javafx.scene.transform.Scale;
import javafx.util.Duration;
import org.jackhuang.hmcl.ui.animation.AnimationUtils;
Expand All @@ -49,6 +50,8 @@ public class JFXPopupSkin implements Skin<JFXPopup> {
protected Node root;

private Animation animation;
private Animation closeAnimation;

protected Scale scale;

public JFXPopupSkin(JFXPopup control) {
Expand All @@ -74,6 +77,7 @@ public void reset(PopupVPosition vAlign, PopupHPosition hAlign, double offsetX,
}

public final void animate() {
container.setMouseTransparent(false);
if (animation != null) {
if (animation.getStatus() == Status.STOPPED) {
container.setOpacity(1);
Expand All @@ -87,6 +91,51 @@ public final void animate() {
}
}

public final void animateClose(Runnable onFinished) {
if (closeAnimation != null) {
return;
}

container.setMouseTransparent(true);
if (animation != null) {
animation.stop();
}

if (!AnimationUtils.isAnimationEnabled()) {
onFinished.run();
init();
return;
}

Interpolator interpolator = Motion.EASE;
closeAnimation = new Timeline(
new KeyFrame(Duration.ZERO,
new KeyValue(popupContent.opacityProperty(), popupContent.getOpacity(), interpolator),
new KeyValue(scale.xProperty(), scale.getX(), interpolator),
new KeyValue(scale.yProperty(), scale.getY(), interpolator)),
new KeyFrame(Motion.SHORT4,
new KeyValue(popupContent.opacityProperty(), 0, interpolator),
new KeyValue(scale.xProperty(), 0, interpolator),
new KeyValue(scale.yProperty(), 0.01, interpolator)));
closeAnimation.setOnFinished(event -> {
closeAnimation = null;
onFinished.run();
init();
});
closeAnimation.play();
}

public final boolean cancelCloseAnimation() {
if (closeAnimation == null) {
return false;
}

closeAnimation.stop();
closeAnimation = null;
container.setMouseTransparent(false);
return true;
}

@Override
public JFXPopup getSkinnable() {
return control;
Expand All @@ -103,6 +152,10 @@ public void dispose() {
animation.stop();
animation = null;
}
if (closeAnimation != null) {
closeAnimation.stop();
closeAnimation = null;
}
container = null;
control = null;
popupContent = null;
Expand Down Expand Up @@ -132,6 +185,11 @@ protected Animation getAnimation() {
public void init() {
if (animation != null)
animation.stop();
if (closeAnimation != null) {
closeAnimation.stop();
closeAnimation = null;
}
container.setMouseTransparent(false);
container.setOpacity(0);
scale.setX(1.0);
scale.setY(0.01);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ public final class GameListCell extends ListCell<GameListItem> {

private final StringProperty tag = new SimpleStringProperty();

private JFXPopup managementPopup;

private GameListItem managementPopupItem;

public GameListCell() {
BorderPane root = new BorderPane();
root.getStyleClass().add("md-list-cell");
Expand Down Expand Up @@ -132,7 +136,12 @@ public void fire() {
if (item == null)
return;

JFXPopup popup = getPopup(item);
JFXPopup popup = getManagementPopup(item);
if (popup.isShowing()) {
popup.hide();
return;
}

JFXPopup.PopupVPosition vPosition = determineOptimalPopupPosition(root, popup);
popup.show(root, vPosition, JFXPopup.PopupHPosition.RIGHT, 0, vPosition == JFXPopup.PopupVPosition.TOP ? root.getHeight() : -root.getHeight());
});
Expand All @@ -152,7 +161,12 @@ public void fire() {
item.modifyGameSettings();
}
} else if (e.getButton() == MouseButton.SECONDARY) {
JFXPopup popup = getPopup(item);
JFXPopup popup = getManagementPopup(item);
if (popup.isShowing()) {
popup.hide();
return;
}

JFXPopup.PopupVPosition vPosition = determineOptimalPopupPosition(root, popup);
popup.show(root, vPosition, JFXPopup.PopupHPosition.LEFT, e.getX(), vPosition == JFXPopup.PopupVPosition.TOP ? e.getY() : e.getY() - root.getHeight());
}
Expand All @@ -168,6 +182,12 @@ public void updateItem(GameListItem item, boolean empty) {

if (oldItem == item && oldEmpty == empty) return;

if (managementPopup != null) {
managementPopup.hide();
managementPopup = null;
managementPopupItem = null;
}

this.graphic.releaseRippleImmediately();

this.imageView.imageProperty().unbind();
Expand All @@ -193,9 +213,21 @@ public void updateItem(GameListItem item, boolean empty) {
}
}

private static JFXPopup getPopup(GameListItem item) {
private JFXPopup getManagementPopup(GameListItem item) {
if (managementPopup == null || managementPopupItem != item) {
if (managementPopup != null) {
managementPopup.hide();
}
managementPopup = createPopup(item);
managementPopupItem = item;
}
return managementPopup;
}

private static JFXPopup createPopup(GameListItem item) {
PopupMenu menu = new PopupMenu();
JFXPopup popup = new JFXPopup(menu);
popup.setConsumeAutoHidingEvents(true);

menu.getContent().setAll(
new IconedMenuItem(SVG.ROCKET_LAUNCH, i18n("instance.launch.test"), item::testGame, popup),
Expand Down
Loading