diff --git a/HMCL/src/main/java/com/jfoenix/controls/JFXRippler.java b/HMCL/src/main/java/com/jfoenix/controls/JFXRippler.java index 21041510e3..071800387a 100644 --- a/HMCL/src/main/java/com/jfoenix/controls/JFXRippler.java +++ b/HMCL/src/main/java/com/jfoenix/controls/JFXRippler.java @@ -30,6 +30,7 @@ import javafx.css.converter.BooleanConverter; import javafx.css.converter.PaintConverter; import javafx.css.converter.SizeConverter; +import javafx.event.EventHandler; import javafx.geometry.Bounds; import javafx.scene.CacheHint; import javafx.scene.Group; @@ -45,6 +46,9 @@ import javafx.scene.shape.Rectangle; import javafx.scene.shape.Shape; import javafx.util.Duration; +import org.jackhuang.hmcl.theme.Themes; +import org.jackhuang.hmcl.ui.animation.AnimationUtils; +import org.jackhuang.hmcl.ui.animation.Motion; import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; @@ -76,6 +80,8 @@ public enum RipplerMask { protected RippleGenerator rippler; protected Pane ripplerPane; protected Node control; + private Transition coverAnimation; + private Rectangle hoverOverlay; protected static final double RIPPLE_MAX_RADIUS = 300; private static final Interpolator RIPPLE_INTERPOLATOR = Interpolator.SPLINE(0.0825, @@ -128,6 +134,62 @@ public JFXRippler(Node control, RipplerMask mask, RipplerPos pos) { setCache(true); setCacheHint(CacheHint.SPEED); setCacheShape(true); + + EventHandler mouseEventHandler; + if (AnimationUtils.isAnimationEnabled()) { + mouseEventHandler = event -> { + if (coverAnimation != null) { + coverAnimation.stop(); + coverAnimation = null; + } + + if (event.getEventType() == MouseEvent.MOUSE_ENTERED) { + coverAnimation = new Transition() { + { + setCycleDuration(Motion.SHORT4); + setInterpolator(Motion.EASE_IN); + } + + @Override + protected void interpolate(double frac) { + interpolateBackground(frac); + } + }; + } else { + coverAnimation = new Transition() { + { + setCycleDuration(Motion.SHORT4); + setInterpolator(Motion.EASE_OUT); + } + + @Override + protected void interpolate(double frac) { + interpolateBackground(1 - frac); + } + }; + } + + coverAnimation.play(); + }; + } else { + mouseEventHandler = event -> + interpolateBackground(event.getEventType() == MouseEvent.MOUSE_ENTERED ? 1 : 0); + } + + addEventHandler(MouseEvent.MOUSE_ENTERED, mouseEventHandler); + addEventHandler(MouseEvent.MOUSE_EXITED, mouseEventHandler); + } + + private void interpolateBackground(double frac) { + if (hoverOverlay == null) return; + if (frac < 0.01) { + hoverOverlay.setOpacity(0); + return; + } + Color onSurface = Themes.getColorScheme().getOnSurface(); + Color fillColor = Color.color(onSurface.getRed(), onSurface.getGreen(), onSurface.getBlue(), frac * 0.04); + hoverOverlay.setFill(fillColor); + hoverOverlay.setOpacity(1); } protected final void createRippleUI() { @@ -135,7 +197,13 @@ protected final void createRippleUI() { rippler = new RippleGenerator(); ripplerPane = new StackPane(); ripplerPane.setMouseTransparent(true); - ripplerPane.getChildren().add(rippler); + + hoverOverlay = new Rectangle(); + hoverOverlay.setManaged(false); + hoverOverlay.setCache(true); + hoverOverlay.setCacheHint(CacheHint.SPEED); + hoverOverlay.setOpacity(0); + ripplerPane.getChildren().addAll(hoverOverlay, rippler); getChildren().add(ripplerPane); } @@ -560,6 +628,17 @@ private void resetClip() { protected void resetRippler() { resetOverLay(); resetClip(); + + if (hoverOverlay != null && control != null) { + Bounds bounds = control.getBoundsInParent(); + double diffMinX = Math.abs(control.getBoundsInLocal().getMinX() - control.getLayoutBounds().getMinX()); + double diffMinY = Math.abs(control.getBoundsInLocal().getMinY() - control.getLayoutBounds().getMinY()); + hoverOverlay.setX(bounds.getMinX() + diffMinX - snappedLeftInset()); + hoverOverlay.setY(bounds.getMinY() + diffMinY - snappedTopInset()); + hoverOverlay.setWidth(control.getLayoutBounds().getWidth()); + hoverOverlay.setHeight(control.getLayoutBounds().getHeight()); + hoverOverlay.setClip(getMask()); + } } /*************************************************************************** diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/RipplerContainer.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/RipplerContainer.java index 4c6fae21be..d3de640e2c 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/RipplerContainer.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/RipplerContainer.java @@ -18,13 +18,13 @@ package org.jackhuang.hmcl.ui.construct; import com.jfoenix.controls.JFXRippler; -import javafx.animation.Transition; -import javafx.css.*; +import javafx.css.CssMetaData; +import javafx.css.Styleable; +import javafx.css.StyleableObjectProperty; +import javafx.css.StyleableProperty; import javafx.css.converter.PaintConverter; -import javafx.event.EventHandler; import javafx.geometry.Insets; import javafx.scene.Node; -import javafx.scene.input.MouseEvent; import javafx.scene.layout.Background; import javafx.scene.layout.BackgroundFill; import javafx.scene.layout.CornerRadii; @@ -32,9 +32,6 @@ import javafx.scene.paint.Color; import javafx.scene.paint.Paint; import javafx.scene.shape.Rectangle; -import org.jackhuang.hmcl.theme.Themes; -import org.jackhuang.hmcl.ui.animation.AnimationUtils; -import org.jackhuang.hmcl.ui.animation.Motion; import java.util.ArrayList; import java.util.List; @@ -63,8 +60,6 @@ protected Node getMask() { } }; - private Transition coverAnimation; - public RipplerContainer(Node container) { this.container = container; @@ -90,61 +85,6 @@ public RipplerContainer(Node container) { shape.widthProperty().bind(widthProperty()); shape.heightProperty().bind(heightProperty()); setShape(shape); - - EventHandler mouseEventHandler; - if (AnimationUtils.isAnimationEnabled()) { - mouseEventHandler = event -> { - if (coverAnimation != null) { - coverAnimation.stop(); - coverAnimation = null; - } - - if (event.getEventType() == MouseEvent.MOUSE_ENTERED) { - coverAnimation = new Transition() { - { - setCycleDuration(Motion.SHORT4); - setInterpolator(Motion.EASE_IN); - } - - @Override - protected void interpolate(double frac) { - interpolateBackground(frac); - } - }; - } else { - coverAnimation = new Transition() { - { - setCycleDuration(Motion.SHORT4); - setInterpolator(Motion.EASE_OUT); - } - - @Override - protected void interpolate(double frac) { - interpolateBackground(1 - frac); - } - }; - } - - coverAnimation.play(); - }; - } else { - mouseEventHandler = event -> - interpolateBackground(event.getEventType() == MouseEvent.MOUSE_ENTERED ? 1 : 0); - } - - addEventHandler(MouseEvent.MOUSE_ENTERED, mouseEventHandler); - addEventHandler(MouseEvent.MOUSE_EXITED, mouseEventHandler); - } - - private void interpolateBackground(double frac) { - if (frac < 0.01) { - setBackground(null); - } else { - Color onSurface = Themes.getColorScheme().getOnSurface(); - setBackground(new Background(new BackgroundFill( - Color.color(onSurface.getRed(), onSurface.getGreen(), onSurface.getBlue(), frac * 0.04), - CornerRadii.EMPTY, Insets.EMPTY))); - } } protected void updateChildren() {