From ab264955f5f11b6a8ee1d19e186f1d6e4fddd8db Mon Sep 17 00:00:00 2001 From: Glavo Date: Tue, 14 Feb 2023 19:12:30 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=8A=A8=E7=94=BB=E5=BC=80?= =?UTF-8?q?=E5=85=B3=20(#2111)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/jackhuang/hmcl/setting/Config.java | 15 ++++ .../org/jackhuang/hmcl/setting/Settings.java | 2 + .../java/org/jackhuang/hmcl/ui/FXUtils.java | 4 +- .../hmcl/ui/animation/AnimationUtils.java | 23 ++++++ .../hmcl/ui/animation/TransitionPane.java | 27 ++++--- .../hmcl/ui/construct/ComponentListCell.java | 71 +++++++++++++------ .../org/jackhuang/hmcl/ui/main/MainPage.java | 29 ++++---- .../hmcl/ui/main/PersonalizationPage.java | 6 ++ .../resources/assets/lang/I18N.properties | 1 + .../resources/assets/lang/I18N_zh.properties | 1 + .../assets/lang/I18N_zh_CN.properties | 1 + 11 files changed, 135 insertions(+), 45 deletions(-) create mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/ui/animation/AnimationUtils.java diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Config.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Config.java index b622c5f06..0c93cd582 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Config.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Config.java @@ -191,6 +191,9 @@ public final class Config implements Cloneable, Observable { @SerializedName("preferredLoginType") private StringProperty preferredLoginType = new SimpleStringProperty(); + @SerializedName("animationDisabled") + private BooleanProperty animationDisabled = new SimpleBooleanProperty(); + private transient ObservableHelper helper = new ObservableHelper(this); public Config() { @@ -601,6 +604,18 @@ public final class Config implements Cloneable, Observable { return preferredLoginType; } + public boolean isAnimationDisabled() { + return animationDisabled.get(); + } + + public BooleanProperty animationDisabledProperty() { + return animationDisabled; + } + + public void setAnimationDisabled(boolean animationDisabled) { + this.animationDisabled.set(animationDisabled); + } + public boolean isTitleTransparent() { return titleTransparent.get(); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java index 0f20d995d..b2244dcb5 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java @@ -20,6 +20,7 @@ package org.jackhuang.hmcl.setting; import javafx.beans.binding.Bindings; import org.jackhuang.hmcl.Metadata; import org.jackhuang.hmcl.game.HMCLCacheRepository; +import org.jackhuang.hmcl.ui.animation.AnimationUtils; import org.jackhuang.hmcl.util.CacheRepository; import org.jackhuang.hmcl.util.io.FileUtils; @@ -54,6 +55,7 @@ public final class Settings { Accounts.init(); Profiles.init(); AuthlibInjectorServers.init(); + AnimationUtils.init(); CacheRepository.setInstance(HMCLCacheRepository.REPOSITORY); HMCLCacheRepository.REPOSITORY.directoryProperty().bind(Bindings.createStringBinding(() -> { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java index fe70b151f..9145b4d54 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java @@ -47,6 +47,7 @@ import javafx.util.Callback; import javafx.util.Duration; import javafx.util.StringConverter; import org.jackhuang.hmcl.task.Schedulers; +import org.jackhuang.hmcl.ui.animation.AnimationUtils; import org.jackhuang.hmcl.ui.construct.JFXHyperlink; import org.jackhuang.hmcl.util.Holder; import org.jackhuang.hmcl.util.Logging; @@ -275,7 +276,8 @@ public final class FXUtils { } public static void smoothScrolling(ScrollPane scrollPane) { - ScrollUtils.addSmoothScrolling(scrollPane); + if (AnimationUtils.isAnimationEnabled()) + ScrollUtils.addSmoothScrolling(scrollPane); } public static void installFastTooltip(Node node, Tooltip tooltip) { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/animation/AnimationUtils.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/animation/AnimationUtils.java new file mode 100644 index 000000000..4a3a725ed --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/animation/AnimationUtils.java @@ -0,0 +1,23 @@ +package org.jackhuang.hmcl.ui.animation; + +import org.jackhuang.hmcl.setting.ConfigHolder; + +public final class AnimationUtils { + + private AnimationUtils() { + } + + /** + * Trigger initialization of this class. + * Should be called from {@link org.jackhuang.hmcl.setting.Settings#init()}. + */ + @SuppressWarnings("JavadocReference") + public static void init() { + } + + private static final boolean enabled = !ConfigHolder.config().isAnimationDisabled(); + + public static boolean isAnimationEnabled() { + return enabled; + } +} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/animation/TransitionPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/animation/TransitionPane.java index a01ff3487..0d722d778 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/animation/TransitionPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/animation/TransitionPane.java @@ -69,18 +69,23 @@ public class TransitionPane extends StackPane implements AnimationHandler { return; } - transition.init(this); + if (AnimationUtils.isAnimationEnabled()) { + transition.init(this); - // runLater or "init" will not work - Platform.runLater(() -> { - Timeline newAnimation = new Timeline(); - newAnimation.getKeyFrames().addAll(transition.animate(this)); - newAnimation.getKeyFrames().add(new KeyFrame(duration, e -> { - setMouseTransparent(false); - getChildren().remove(previousNode); - })); - FXUtils.playAnimation(this, "transition_pane", newAnimation); - }); + // runLater or "init" will not work + Platform.runLater(() -> { + Timeline newAnimation = new Timeline(); + newAnimation.getKeyFrames().addAll(transition.animate(this)); + newAnimation.getKeyFrames().add(new KeyFrame(duration, e -> { + setMouseTransparent(false); + getChildren().remove(previousNode); + })); + FXUtils.playAnimation(this, "transition_pane", newAnimation); + }); + } else { + setMouseTransparent(false); + getChildren().remove(previousNode); + } } private void updateContent(Node newView) { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ComponentListCell.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ComponentListCell.java index b95dafe97..6ae405b5e 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ComponentListCell.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ComponentListCell.java @@ -25,6 +25,9 @@ import javafx.animation.Timeline; import javafx.application.Platform; import javafx.beans.property.BooleanProperty; import javafx.beans.property.SimpleBooleanProperty; +import javafx.event.ActionEvent; +import javafx.event.Event; +import javafx.event.EventHandler; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.Node; @@ -35,6 +38,7 @@ import javafx.util.Duration; import org.jackhuang.hmcl.setting.Theme; import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.ui.SVG; +import org.jackhuang.hmcl.ui.animation.AnimationUtils; /** * @author huangyuhui @@ -70,6 +74,7 @@ class ComponentListCell extends StackPane { } } + @SuppressWarnings("unchecked") private void updateLayout() { if (content instanceof ComponentList) { ComponentList list = (ComponentList) content; @@ -134,42 +139,66 @@ class ComponentListCell extends StackPane { container.getChildren().setAll(content); groupNode.getChildren().add(container); - Runnable onExpand = () -> { - if (expandAnimation != null && expandAnimation.getStatus() == Animation.Status.RUNNING) { - expandAnimation.stop(); - } + EventHandler onExpand; + if (AnimationUtils.isAnimationEnabled()) { + onExpand = e -> { + if (expandAnimation != null && expandAnimation.getStatus() == Animation.Status.RUNNING) { + expandAnimation.stop(); + } - setExpanded(!isExpanded()); + setExpanded(!isExpanded()); - if (isExpanded()) { - list.onExpand(); - list.layout(); - } + if (isExpanded()) { + list.onExpand(); + list.layout(); + } + + Platform.runLater(() -> { + double newAnimatedHeight = (content.prefHeight(-1) + 8 + 10) * (isExpanded() ? 1 : -1); + double newHeight = isExpanded() ? getHeight() + newAnimatedHeight : prefHeight(-1); + double contentHeight = isExpanded() ? newAnimatedHeight : 0; + + if (isExpanded()) { + updateClip(newHeight); + } + + expandAnimation = new Timeline(new KeyFrame(new Duration(320.0), + new KeyValue(container.minHeightProperty(), contentHeight, FXUtils.SINE), + new KeyValue(container.maxHeightProperty(), contentHeight, FXUtils.SINE) + )); + + if (!isExpanded()) { + expandAnimation.setOnFinished(e2 -> updateClip(newHeight)); + } + + expandAnimation.play(); + }); + }; + } else { + onExpand = e -> { + setExpanded(!isExpanded()); - Platform.runLater(() -> { double newAnimatedHeight = (content.prefHeight(-1) + 8 + 10) * (isExpanded() ? 1 : -1); double newHeight = isExpanded() ? getHeight() + newAnimatedHeight : prefHeight(-1); double contentHeight = isExpanded() ? newAnimatedHeight : 0; if (isExpanded()) { + list.onExpand(); + list.layout(); updateClip(newHeight); } - expandAnimation = new Timeline(new KeyFrame(new Duration(320.0), - new KeyValue(container.minHeightProperty(), contentHeight, FXUtils.SINE), - new KeyValue(container.maxHeightProperty(), contentHeight, FXUtils.SINE) - )); + container.setMinHeight(contentHeight); + container.setMaxHeight(contentHeight); if (!isExpanded()) { - expandAnimation.setOnFinished(e2 -> updateClip(newHeight)); + updateClip(newHeight); } + }; + } - expandAnimation.play(); - }); - }; - - headerRippler.setOnMouseClicked(e -> onExpand.run()); - expandButton.setOnMouseClicked(e -> onExpand.run()); + headerRippler.setOnMouseClicked(onExpand); + expandButton.setOnAction((EventHandler) (Object) onExpand); expandedProperty().addListener((a, b, newValue) -> expandIcon.setRotate(newValue ? 180 : 0)); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/MainPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/MainPage.java index 111fb82d8..dc15b1d16 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/MainPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/MainPage.java @@ -45,6 +45,7 @@ import org.jackhuang.hmcl.setting.Theme; import org.jackhuang.hmcl.ui.Controllers; import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.ui.SVG; +import org.jackhuang.hmcl.ui.animation.AnimationUtils; import org.jackhuang.hmcl.ui.construct.AnnouncementCard; import org.jackhuang.hmcl.ui.construct.MessageDialogPane; import org.jackhuang.hmcl.ui.construct.PopupMenu; @@ -254,18 +255,22 @@ public final class MainPage extends StackPane implements DecoratorPage { } private void doAnimation(boolean show) { - Duration duration = Duration.millis(320); - Timeline nowAnimation = new Timeline(); - nowAnimation.getKeyFrames().addAll( - new KeyFrame(Duration.ZERO, - new KeyValue(updatePane.translateXProperty(), show ? 260 : 0, SINE)), - new KeyFrame(duration, - new KeyValue(updatePane.translateXProperty(), show ? 0 : 260, SINE))); - if (show) nowAnimation.getKeyFrames().add( - new KeyFrame(Duration.ZERO, e -> updatePane.setVisible(true))); - else nowAnimation.getKeyFrames().add( - new KeyFrame(duration, e -> updatePane.setVisible(false))); - nowAnimation.play(); + if (AnimationUtils.isAnimationEnabled()) { + Duration duration = Duration.millis(320); + Timeline nowAnimation = new Timeline(); + nowAnimation.getKeyFrames().addAll( + new KeyFrame(Duration.ZERO, + new KeyValue(updatePane.translateXProperty(), show ? 260 : 0, SINE)), + new KeyFrame(duration, + new KeyValue(updatePane.translateXProperty(), show ? 0 : 260, SINE))); + if (show) nowAnimation.getKeyFrames().add( + new KeyFrame(Duration.ZERO, e -> updatePane.setVisible(true))); + else nowAnimation.getKeyFrames().add( + new KeyFrame(duration, e -> updatePane.setVisible(false))); + nowAnimation.play(); + } else { + updatePane.setVisible(show); + } } private void launch() { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/PersonalizationPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/PersonalizationPage.java index e2a9f548e..22e982a00 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/PersonalizationPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/PersonalizationPage.java @@ -88,6 +88,12 @@ public class PersonalizationPage extends StackPane { titleTransparentButton.selectedProperty().bindBidirectional(config().titleTransparentProperty()); titleTransparentButton.setTitle(i18n("settings.launcher.title_transparent")); } + { + OptionToggleButton animationButton = new OptionToggleButton(); + themeList.getContent().add(animationButton); + animationButton.selectedProperty().bindBidirectional(config().animationDisabledProperty()); + animationButton.setTitle(i18n("settings.launcher.turn_off_animations")); + } content.getChildren().addAll(ComponentList.createComponentListTitle(i18n("settings.launcher.appearance")), themeList); { diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 749dadb9a..4ed7bdd04 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -1066,6 +1066,7 @@ settings.launcher.proxy.socks=SOCKS settings.launcher.proxy.username=Username settings.launcher.theme=Theme settings.launcher.title_transparent=Transparent titlebar +settings.launcher.turn_off_animations=Turn off animation (applies after restart) settings.launcher.version_list_source=Version List settings.memory=Memory diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 0d6341811..7495ab818 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -936,6 +936,7 @@ settings.launcher.proxy.socks=Socks settings.launcher.proxy.username=帳戶 settings.launcher.theme=主題 settings.launcher.title_transparent=標題欄透明 +settings.launcher.turn_off_animations=關閉動畫 (重啟後生效) settings.launcher.version_list_source=版本列表來源 settings.memory=遊戲記憶體 diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties index 1cdadade5..846c3d215 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -934,6 +934,7 @@ settings.launcher.proxy.socks=Socks settings.launcher.proxy.username=帐户 settings.launcher.theme=主题 settings.launcher.title_transparent=标题栏透明 +settings.launcher.turn_off_animations=关闭动画 (重启后生效) settings.launcher.version_list_source=版本列表源 settings.memory=游戏内存