From 12fa94627db12f7abcfe0bf41d562d46aadbe6a5 Mon Sep 17 00:00:00 2001 From: huangyuhui Date: Thu, 25 Jan 2018 22:41:15 +0800 Subject: [PATCH] TransitionHandler update --- .../hmcl/game/HMCLGameRepository.java | 9 +- .../jackhuang/hmcl/game/LauncherHelper.java | 42 +++---- .../org/jackhuang/hmcl/game/LoadingState.java | 22 +++- .../org/jackhuang/hmcl/setting/Settings.java | 2 +- .../jackhuang/hmcl/ui/AdvancedListBox.java | 4 + .../org/jackhuang/hmcl/ui/Controllers.java | 14 ++- .../java/org/jackhuang/hmcl/ui/Decorator.java | 11 +- .../hmcl/ui/InstallerController.java | 5 +- .../org/jackhuang/hmcl/ui/InstallerItem.java | 3 +- .../java/org/jackhuang/hmcl/ui/MainPage.java | 17 ++- .../org/jackhuang/hmcl/ui/ModController.java | 2 +- .../java/org/jackhuang/hmcl/ui/ModItem.java | 3 +- .../org/jackhuang/hmcl/ui/ProfilePage.java | 2 +- .../org/jackhuang/hmcl/ui/VersionItem.java | 6 + .../org/jackhuang/hmcl/ui/VersionPage.java | 21 ++-- .../hmcl/ui/VersionSettingsController.java | 6 +- .../hmcl/ui/animation/AnimationHandler.java | 3 +- .../ui/animation/ContainerAnimations.java | 48 ++++---- .../hmcl/ui/animation/TransitionHandler.java | 48 ++++---- .../jackhuang/hmcl/ui/construct/FileItem.java | 3 + .../hmcl/ui/construct/MessageDialogPane.java | 15 ++- .../TaskExecutorDialogPane.java} | 51 ++++++++- .../TaskExecutorDialogWizardDisplayer.java | 84 ++++++++++++++ .../hmcl/ui/construct/TaskListPane.java | 34 +++--- .../ui/download/AdditionalInstallersPage.java | 79 +++++++------ .../ui/download/DownloadWizardProvider.java | 6 +- .../ui/download/InstallerWizardProvider.java | 12 +- .../hmcl/ui/export/ModpackInfoPage.java | 2 +- .../ui/wizard/AbstractWizardDisplayer.java | 55 +-------- .../ui/wizard/DefaultWizardDisplayer.java | 1 + .../hmcl/ui/wizard/ResultProgressHandle.java | 104 ------------------ .../org/jackhuang/hmcl/ui/wizard/Summary.java | 5 + .../hmcl/ui/wizard/WizardController.java | 3 +- .../hmcl/ui/wizard/WizardDisplayer.java | 1 - .../main/resources/assets/fxml/account.fxml | 2 +- .../fxml/download/additional-installers.fxml | 4 +- .../assets/fxml/download/installers.fxml | 2 +- .../assets/fxml/download/modpack.fxml | 4 +- .../resources/assets/fxml/input-dialog.fxml | 2 +- .../assets/fxml/launching-steps.fxml | 10 +- HMCL/src/main/resources/assets/fxml/log.fxml | 2 +- .../resources/assets/fxml/message-dialog.fxml | 2 +- .../resources/assets/fxml/modpack/info.fxml | 4 +- .../main/resources/assets/fxml/profile.fxml | 4 +- .../resources/assets/fxml/version-item.fxml | 18 +-- .../assets/fxml/version/version-settings.fxml | 4 +- .../assets/fxml/yggdrasil-account-login.fxml | 4 +- .../resources/assets/lang/I18N.properties | 83 +++++++------- .../assets/lang/I18N_zh_CN.properties | 81 +++++++------- .../hmcl/download/forge/ForgeInstallTask.java | 4 +- .../download/game/GameAssetDownloadTask.java | 7 +- .../download/game/GameAssetRefreshTask.java | 3 + .../jackhuang/hmcl/game/GameRepository.java | 6 + .../hmcl/launch/DefaultLauncher.java | 29 ++--- .../org/jackhuang/hmcl/launch/Launcher.java | 5 +- .../jackhuang/hmcl/task/FileDownloadTask.java | 1 + .../jackhuang/hmcl/task/SchedulerImpl.java | 1 + .../org/jackhuang/hmcl/task/Schedulers.java | 15 ++- .../org/jackhuang/hmcl/task/SimpleTask.java | 11 +- .../jackhuang/hmcl/task/SimpleTaskResult.java | 30 ++--- .../java/org/jackhuang/hmcl/task/Task.java | 25 ++++- .../org/jackhuang/hmcl/task/TaskExecutor.java | 44 +++++--- .../org/jackhuang/hmcl/task/TaskListener.java | 6 + .../org/jackhuang/hmcl/util/JavaVersion.java | 2 +- .../java/org/jackhuang/hmcl/util/Lang.java | 15 ++- .../org/jackhuang/hmcl/util/StringUtils.java | 15 +++ 66 files changed, 646 insertions(+), 522 deletions(-) rename HMCL/src/main/java/org/jackhuang/hmcl/ui/{LaunchingStepsPane.java => construct/TaskExecutorDialogPane.java} (51%) create mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskExecutorDialogWizardDisplayer.java delete mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/ResultProgressHandle.java rename HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/DeferredWizardResult.java => HMCLCore/src/main/java/org/jackhuang/hmcl/task/SimpleTaskResult.java (59%) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java index b70637481..3917d6f64 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java @@ -26,6 +26,7 @@ import org.jackhuang.hmcl.setting.Profile; import org.jackhuang.hmcl.setting.Settings; import org.jackhuang.hmcl.setting.VersionSetting; import org.jackhuang.hmcl.task.Schedulers; +import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.util.FileUtils; import org.jackhuang.hmcl.util.Lang; import org.jackhuang.hmcl.util.Logging; @@ -109,15 +110,13 @@ public class HMCLGameRepository extends DefaultGameRepository { @Override public void refreshVersions() { EventBus.EVENT_BUS.fireEvent(new RefreshingVersionsEvent(this)); - Schedulers.newThread().schedule(() -> { - refreshVersionsImpl(); - EventBus.EVENT_BUS.fireEvent(new RefreshedVersionsEvent(this)); - }); + refreshVersionsImpl(); + EventBus.EVENT_BUS.fireEvent(new RefreshedVersionsEvent(this)); } public void changeDirectory(File newDirectory) { setBaseDirectory(newDirectory); - refreshVersions(); + refreshVersionsAsync().start(); } private void checkModpack() { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java index 0791332c2..3a64e82a1 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java @@ -37,13 +37,12 @@ import org.jackhuang.hmcl.task.TaskExecutor; import org.jackhuang.hmcl.task.TaskListener; import org.jackhuang.hmcl.ui.Controllers; import org.jackhuang.hmcl.ui.DialogController; -import org.jackhuang.hmcl.ui.LaunchingStepsPane; +import org.jackhuang.hmcl.ui.construct.TaskExecutorDialogPane; import org.jackhuang.hmcl.ui.LogWindow; import org.jackhuang.hmcl.ui.construct.MessageBox; import org.jackhuang.hmcl.util.*; import java.io.*; -import java.nio.Buffer; import java.util.*; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicInteger; @@ -52,10 +51,11 @@ public final class LauncherHelper { public static final LauncherHelper INSTANCE = new LauncherHelper(); private LauncherHelper(){} - private final LaunchingStepsPane launchingStepsPane = new LaunchingStepsPane(); + private TaskExecutor executor; public static final Queue PROCESSES = new ConcurrentLinkedQueue<>(); + private final TaskExecutorDialogPane launchingStepsPane = new TaskExecutorDialogPane(() -> {}); - public void launch(String selectedVersion, String launcherName) { + public void launch(String selectedVersion, File scriptFile) { Profile profile = Settings.INSTANCE.getSelectedProfile(); GameRepository repository = profile.getRepository(); DefaultDependencyManager dependencyManager = profile.getDependency(); @@ -67,12 +67,12 @@ public final class LauncherHelper { VersionSetting setting = profile.getVersionSetting(selectedVersion); Controllers.dialog(launchingStepsPane); - TaskExecutor executor = Task.of(Schedulers.javafx(), () -> emitStatus(LoadingState.DEPENDENCIES)) + executor = Task.of(Schedulers.javafx(), () -> emitStatus(LoadingState.DEPENDENCIES)) .then(dependencyManager.checkGameCompletionAsync(version)) .then(Task.of(Schedulers.javafx(), () -> emitStatus(LoadingState.MODS))) .then(new CurseCompletionTask(dependencyManager, selectedVersion)) - .then(Task.of(Schedulers.javafx(), () -> emitStatus(LoadingState.LOGIN))) - .then(Task.of(variables -> { + .then(Task.of(Schedulers.javafx(), () -> emitStatus(LoadingState.LOGGING_IN))) + .then(Task.of(Main.i18n("account.methods"), variables -> { try { variables.set("account", account.logIn(HMCLMultiCharacterSelector.INSTANCE, Settings.INSTANCE.getProxy())); } catch (AuthenticationException e) { @@ -87,22 +87,24 @@ public final class LauncherHelper { )); })) .then(variables -> { - if (launcherName == null) { - return variables.get("launcher").launchAsync(); + if (scriptFile == null) { + return variables.get("launcher").launchAsync().setName("version.launch"); } else { - variables.set("script", variables.get("launcher").makeLaunchScript(launcherName)); - return null; + return variables.get("launcher").makeLaunchScriptAsync(scriptFile).setName("version.launch"); } }) .then(Task.of(variables -> { - if (launcherName == null) { + if (scriptFile == null) { PROCESSES.add(variables.get(DefaultLauncher.LAUNCH_ASYNC_ID)); if (setting.getLauncherVisibility() == LauncherVisibility.CLOSE) Main.stopApplication(); - } + } else + Platform.runLater(() -> + Controllers.dialog(Main.i18n("version.launch_script.success", scriptFile.getAbsolutePath()))); })) .executor(); + launchingStepsPane.setExecutor(executor); executor.addTaskListener(new TaskListener() { AtomicInteger finished = new AtomicInteger(0); @@ -113,17 +115,6 @@ public final class LauncherHelper { launchingStepsPane.setProgress(1.0 * finished.get() / executor.getRunningTasks()); }); } - - @Override - public void onTerminate(AutoTypingMap variables) { - Platform.runLater(() -> { - Controllers.closeDialog(); - - if (variables.containsKey("script")) { - Controllers.dialog(Main.i18n("version.launch_script.success", variables.get("script").getAbsolutePath())); - } - }); - } }); executor.start(); @@ -163,8 +154,9 @@ public final class LauncherHelper { if (state == LoadingState.DONE) Controllers.closeDialog(); - launchingStepsPane.setCurrentState(state.toString()); + launchingStepsPane.setCurrentState(state.getLocalizedMessage()); launchingStepsPane.setSteps((state.ordinal() + 1) + " / " + LoadingState.values().length); + Controllers.dialog(launchingStepsPane); } private void checkExit(LauncherVisibility v) { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/LoadingState.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/LoadingState.java index 9cac32a47..e5dd94e24 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/LoadingState.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/LoadingState.java @@ -17,10 +17,22 @@ */ package org.jackhuang.hmcl.game; +import org.jackhuang.hmcl.Main; + public enum LoadingState { - DEPENDENCIES, - MODS, - LOGIN, - LAUNCHING, - DONE + DEPENDENCIES("launch.state.dependencies"), + MODS("launch.state.modpack"), + LOGGING_IN("launch.state.logging_in"), + LAUNCHING("launch.state.waiting_launching"), + DONE(""); + + private final String key; + + LoadingState(String key) { + this.key = key; + } + + public String getLocalizedMessage() { + return Main.i18n(key); + } } 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 a9c60ece2..d91c3fc36 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java @@ -428,7 +428,7 @@ public class Settings { } private void onProfileChanged() { - getSelectedProfile().getRepository().refreshVersions(); + getSelectedProfile().getRepository().refreshVersionsAsync().start(); EventBus.EVENT_BUS.fireEvent(new ProfileChangedEvent(SETTINGS, getSelectedProfile())); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/AdvancedListBox.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/AdvancedListBox.java index 2becb9568..ca89dd02c 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/AdvancedListBox.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/AdvancedListBox.java @@ -77,4 +77,8 @@ public class AdvancedListBox extends ScrollPane { public void setSpacing(double spacing) { container.setSpacing(spacing); } + + public void clear() { + container.getChildren().clear(); + } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java index 75ec72525..ec54448df 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java @@ -99,12 +99,24 @@ public final class Controllers { stage.setTitle(Main.TITLE); } + public static Region getDialogContent() { + return decorator.getDialog().getContent(); + } + public static JFXDialog dialog(Region content) { return decorator.showDialog(content); } public static void dialog(String text) { - dialog(new MessageDialogPane(text, decorator.getDialog())); + dialog(text, null); + } + + public static void dialog(String text, String title) { + dialog(text, title, null); + } + + public static void dialog(String text, String title, Runnable onAccept) { + dialog(new MessageDialogPane(text, title, decorator.getDialog(), onAccept)); } public static void inputDialog(String text, Consumer onResult) { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Decorator.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Decorator.java index 31761de4a..55a8d686c 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Decorator.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Decorator.java @@ -47,13 +47,14 @@ import org.jackhuang.hmcl.Main; import org.jackhuang.hmcl.ui.animation.AnimationProducer; import org.jackhuang.hmcl.ui.animation.ContainerAnimations; import org.jackhuang.hmcl.ui.animation.TransitionHandler; +import org.jackhuang.hmcl.ui.construct.TaskExecutorDialogWizardDisplayer; import org.jackhuang.hmcl.ui.wizard.*; import org.jackhuang.hmcl.util.Lang; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; -public final class Decorator extends StackPane implements AbstractWizardDisplayer { +public final class Decorator extends StackPane implements TaskExecutorDialogWizardDisplayer { private static final SVGGlyph minus = Lang.apply(new SVGGlyph(0, "MINUS", "M804.571 420.571v109.714q0 22.857-16 38.857t-38.857 16h-694.857q-22.857 0-38.857-16t-16-38.857v-109.714q0-22.857 16-38.857t38.857-16h694.857q22.857 0 38.857 16t16 38.857z", Color.WHITE), glyph -> { glyph.setSize(12, 2); glyph.setTranslateY(4); }); private static final SVGGlyph resizeMax = Lang.apply(new SVGGlyph(0, "RESIZE_MAX", "M726 810v-596h-428v596h428zM726 44q34 0 59 25t25 59v768q0 34-25 60t-59 26h-428q-34 0-59-26t-25-60v-768q0-34 25-60t59-26z", Color.WHITE), @@ -421,9 +422,11 @@ public final class Decorator extends StackPane implements AbstractWizardDisplaye } public JFXDialog showDialog(Region content) { - dialog.setContent(content); - if (!dialogShown) - dialog.show(); + if (dialog.getContent() != content) { + dialog.setContent(content); + if (!dialogShown) + dialog.show(); + } return dialog; } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerController.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerController.java index 33fe78fff..9ab785ec7 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerController.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerController.java @@ -25,6 +25,7 @@ import org.jackhuang.hmcl.game.GameVersion; import org.jackhuang.hmcl.game.Library; import org.jackhuang.hmcl.game.Version; import org.jackhuang.hmcl.setting.Profile; +import org.jackhuang.hmcl.task.Schedulers; import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.ui.download.InstallerWizardProvider; @@ -59,8 +60,8 @@ public class InstallerController { LinkedList newList = new LinkedList<>(version.getLibraries()); newList.remove(library); new VersionJsonSaveTask(profile.getRepository(), version.setLibraries(newList)) - .with(Task.of(profile.getRepository()::refreshVersions)) - .with(Task.of(() -> loadVersion(this.profile, this.versionId))) + .with(profile.getRepository().refreshVersionsAsync()) + .with(Task.of(Schedulers.javafx(), () -> loadVersion(this.profile, this.versionId))) .start(); }; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerItem.java index 0c61891c2..a08ba9d7e 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerItem.java @@ -21,6 +21,7 @@ import com.jfoenix.effects.JFXDepthManager; import javafx.fxml.FXML; import javafx.scene.control.Label; import javafx.scene.layout.BorderPane; +import org.jackhuang.hmcl.Main; import java.util.function.Consumer; @@ -43,7 +44,7 @@ public class InstallerItem extends BorderPane { setStyle("-fx-background-radius: 2; -fx-background-color: white; -fx-padding: 8;"); JFXDepthManager.setDepth(this, 1); lblInstallerArtifact.setText(artifact); - lblInstallerVersion.setText(version); + lblInstallerVersion.setText(Main.i18n("archive.version") + ": " + version); } public void onDelete() { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPage.java index aaaafaef4..cc47c138d 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPage.java @@ -24,8 +24,10 @@ import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; import javafx.fxml.FXML; import javafx.scene.Node; +import javafx.scene.control.Tooltip; import javafx.scene.image.Image; import javafx.scene.layout.StackPane; +import javafx.stage.FileChooser; import org.jackhuang.hmcl.Main; import org.jackhuang.hmcl.event.EventBus; import org.jackhuang.hmcl.event.ProfileChangedEvent; @@ -39,6 +41,7 @@ import org.jackhuang.hmcl.setting.Settings; import org.jackhuang.hmcl.ui.download.DownloadWizardProvider; import org.jackhuang.hmcl.ui.wizard.DecoratorPage; import org.jackhuang.hmcl.util.Lang; +import org.jackhuang.hmcl.util.OperatingSystem; import java.io.File; import java.util.LinkedList; @@ -65,7 +68,9 @@ public final class MainPage extends StackPane implements DecoratorPage { EventBus.EVENT_BUS.channel(ProfileChangedEvent.class).register(this::onProfileChanged); btnAdd.setOnMouseClicked(e -> Controllers.getDecorator().startWizard(new DownloadWizardProvider(), Main.i18n("install"))); - btnRefresh.setOnMouseClicked(e -> Settings.INSTANCE.getSelectedProfile().getRepository().refreshVersions()); + FXUtils.installTooltip(btnAdd, 0, 5000, 0, new Tooltip(Main.i18n("install"))); + btnRefresh.setOnMouseClicked(e -> Settings.INSTANCE.getSelectedProfile().getRepository().refreshVersionsAsync().start()); + FXUtils.installTooltip(btnRefresh, 0, 5000, 0, new Tooltip(Main.i18n("button.refresh"))); } private Node buildNode(Profile profile, String version, String game) { @@ -82,9 +87,15 @@ public final class MainPage extends StackPane implements DecoratorPage { if (Settings.INSTANCE.getSelectedAccount() == null) Controllers.dialog(Main.i18n("login.no_Player007")); else { - Controllers.inputDialog(Main.i18n("mainwindow.enter_script_name"), file -> { + FileChooser chooser = new FileChooser(); + chooser.setInitialDirectory(profile.getRepository().getRunDirectory(version)); + chooser.setTitle(Main.i18n("version.launch_script.save")); + chooser.getExtensionFilters().add(OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS + ? new FileChooser.ExtensionFilter(Main.i18n("extension.bat"), "*.bat") + : new FileChooser.ExtensionFilter(Main.i18n("extension.sh"), "*.sh")); + File file = chooser.showSaveDialog(Controllers.getStage()); + if (file != null) LauncherHelper.INSTANCE.launch(version, file); - }); } }); item.setOnSettingsButtonClicked(e -> { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/ModController.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/ModController.java index dfc3e098b..5bcc8b3a7 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/ModController.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/ModController.java @@ -138,7 +138,7 @@ public final class ModController { public void onAdd() { FileChooser chooser = new FileChooser(); chooser.setTitle(Main.i18n("mods.choose_mod")); - chooser.getExtensionFilters().setAll(new FileChooser.ExtensionFilter("Mod", "*.jar", "*.zip", "*.litemod")); + chooser.getExtensionFilters().setAll(new FileChooser.ExtensionFilter(Main.i18n("extension.mod"), "*.jar", "*.zip", "*.litemod")); File res = chooser.showOpenDialog(Controllers.getStage()); if (res == null) return; Task.of(() -> modManager.addMod(versionId, res)) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/ModItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/ModItem.java index 859de8e2a..322266eb3 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/ModItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/ModItem.java @@ -24,6 +24,7 @@ import javafx.geometry.Pos; import javafx.scene.control.Label; import javafx.scene.layout.BorderPane; import javafx.scene.layout.VBox; +import org.jackhuang.hmcl.Main; import org.jackhuang.hmcl.mod.ModInfo; import java.util.function.Consumer; @@ -54,7 +55,7 @@ public final class ModItem extends BorderPane { setStyle("-fx-background-radius: 2; -fx-background-color: white; -fx-padding: 8;"); JFXDepthManager.setDepth(this, 1); lblModFileName.setText(info.getFileName()); - lblModAuthor.setText(info.getName() + ", Version: " + info.getVersion() + ", Game: " + info.getGameVersion() + ", Authors: " + info.getAuthors()); + lblModAuthor.setText(info.getName() + ", " + Main.i18n("archive.version") + ": " + info.getVersion() + ", " + Main.i18n("archive.game_version") + ": " + info.getGameVersion() + ", " + Main.i18n("archive.author") + ": " + info.getAuthors()); chkEnabled.setSelected(info.isActive()); chkEnabled.selectedProperty().addListener((a, b, newValue) -> { info.activeProperty().set(newValue); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/ProfilePage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/ProfilePage.java index 22b782e8e..32bd56bdb 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/ProfilePage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/ProfilePage.java @@ -52,7 +52,7 @@ public final class ProfilePage extends StackPane implements DecoratorPage { this.profile = profile; title = new SimpleStringProperty(this, "title", - profile == null ? Main.i18n("ui.newProfileWindow.title") : Main.i18n("profile") + " - " + profile.getName()); + profile == null ? Main.i18n("profile.new") : Main.i18n("profile") + " - " + profile.getName()); location = new SimpleStringProperty(this, "location", Optional.ofNullable(profile).map(Profile::getGameDir).map(File::getAbsolutePath).orElse("")); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/VersionItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/VersionItem.java index 254c0ab24..1ad5262c7 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/VersionItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/VersionItem.java @@ -22,6 +22,7 @@ import javafx.beans.binding.Bindings; import javafx.event.EventHandler; import javafx.fxml.FXML; import javafx.scene.control.Label; +import javafx.scene.control.Tooltip; import javafx.scene.effect.BlurType; import javafx.scene.effect.DropShadow; import javafx.scene.image.Image; @@ -32,6 +33,7 @@ import javafx.scene.layout.Pane; import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; import javafx.scene.paint.Color; +import org.jackhuang.hmcl.Main; import java.util.Optional; @@ -68,6 +70,10 @@ public final class VersionItem extends StackPane { btnLaunch.setGraphic(SVG.launch("black", 15, 15)); btnScript.setGraphic(SVG.script("black", 15, 15)); + FXUtils.installTooltip(btnSettings, 0, 5000, 0, new Tooltip(Main.i18n("version.manage.settings"))); + FXUtils.installTooltip(btnLaunch, 0, 5000, 0, new Tooltip(Main.i18n("version.launch"))); + FXUtils.installTooltip(btnScript, 0, 5000, 0, new Tooltip(Main.i18n("version.launch_script"))); + icon.translateYProperty().bind(Bindings.createDoubleBinding(() -> header.getBoundsInParent().getHeight() - icon.getHeight() / 2 - 16, header.boundsInParentProperty(), icon.heightProperty())); FXUtils.limitSize(iconView, 32, 32); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/VersionPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/VersionPage.java index 9c5ced658..9ccc55bf4 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/VersionPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/VersionPage.java @@ -56,6 +56,8 @@ public final class VersionPage extends StackPane implements DecoratorPage { @FXML private JFXButton btnBrowseMenu; @FXML + private JFXButton btnDelete; + @FXML private JFXButton btnManagementMenu; @FXML private JFXButton btnExport; @@ -80,6 +82,7 @@ public final class VersionPage extends StackPane implements DecoratorPage { browsePopup = new JFXPopup(browseList); managementPopup = new JFXPopup(managementList); + FXUtils.installTooltip(btnDelete, 0, 5000, 0, new Tooltip(Main.i18n("version.manage.remove"))); FXUtils.installTooltip(btnBrowseMenu, 0, 5000, 0, new Tooltip(Main.i18n("game_settings.exploration"))); FXUtils.installTooltip(btnManagementMenu, 0, 5000, 0, new Tooltip(Main.i18n("game_settings.management"))); FXUtils.installTooltip(btnExport, 0, 5000, 0, new Tooltip(Main.i18n("modpack.export"))); @@ -109,9 +112,12 @@ public final class VersionPage extends StackPane implements DecoratorPage { } public void onDelete() { - profile.getRepository().removeVersionFromDisk(version); - profile.getRepository().refreshVersions(); - Controllers.navigate(null); + if (FXUtils.alert(Alert.AlertType.CONFIRMATION, "Confirm", Main.i18n("version.manage.remove.confirm") + version)) { + if (profile.getRepository().removeVersionFromDisk(version)) { + profile.getRepository().refreshVersionsAsync().start(); + Controllers.navigate(null); + } + } } public void onExport() { @@ -154,18 +160,13 @@ public final class VersionPage extends StackPane implements DecoratorPage { Optional res = FXUtils.inputDialog("Input", Main.i18n("version.manage.rename.message"), null, version); if (res.isPresent()) { if (profile.getRepository().renameVersion(version, res.get())) { - profile.getRepository().refreshVersions(); + profile.getRepository().refreshVersionsAsync().start(); Controllers.navigate(null); } } break; case 1: // remove a version - if (FXUtils.alert(Alert.AlertType.CONFIRMATION, "Confirm", Main.i18n("version.manage.remove.confirm") + version)) { - if (profile.getRepository().removeVersionFromDisk(version)) { - profile.getRepository().refreshVersions(); - Controllers.navigate(null); - } - } + onDelete(); break; case 2: // redownload asset index new GameAssetIndexDownloadTask(profile.getDependency(), profile.getRepository().getVersion(version).resolve(profile.getRepository())).start(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/VersionSettingsController.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/VersionSettingsController.java index 9a95ecb13..9c28fb719 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/VersionSettingsController.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/VersionSettingsController.java @@ -24,6 +24,7 @@ import javafx.scene.Node; import javafx.scene.control.Label; import javafx.scene.control.ScrollPane; import javafx.scene.control.Toggle; +import javafx.scene.control.Tooltip; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.VBox; @@ -73,6 +74,7 @@ public final class VersionSettingsController { @FXML private MultiFileItem javaItem; @FXML private MultiFileItem gameDirItem; @FXML private JFXToggleButton chkShowLogs; + @FXML private JFXButton btnIconSelection; @FXML private ImageView iconView; public void initialize() { @@ -114,6 +116,8 @@ public final class VersionSettingsController { gameDirItem.createChildren(Main.i18n("advancedsettings.game_dir.default"), EnumGameDirectory.ROOT_FOLDER), gameDirItem.createChildren(Main.i18n("advancedsettings.game_dir.independent"), EnumGameDirectory.VERSION_FOLDER) )); + + FXUtils.installTooltip(btnIconSelection, 0, 5000, 0, new Tooltip(Main.i18n("button.edit"))); } public void loadVersionSetting(Profile profile, String versionId, VersionSetting versionSetting) { @@ -245,7 +249,7 @@ public final class VersionSettingsController { public void onExploreIcon() { FileChooser chooser = new FileChooser(); - chooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("Image", "*.png")); + chooser.getExtensionFilters().add(new FileChooser.ExtensionFilter(Main.i18n("extension.png"), "*.png")); File selectedFile = chooser.showOpenDialog(Controllers.getStage()); if (selectedFile != null) { File iconFile = profile.getRepository().getVersionIcon(versionId); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/animation/AnimationHandler.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/animation/AnimationHandler.java index 2dc98c13a..b8e50c9a6 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/animation/AnimationHandler.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/animation/AnimationHandler.java @@ -22,7 +22,8 @@ import javafx.scene.layout.Pane; import javafx.util.Duration; public interface AnimationHandler { - Node getSnapshot(); Duration getDuration(); Pane getCurrentRoot(); + Node getPreviousNode(); + Node getCurrentNode(); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/animation/ContainerAnimations.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/animation/ContainerAnimations.java index 5bad93864..4bbacc1b2 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/animation/ContainerAnimations.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/animation/ContainerAnimations.java @@ -31,53 +31,57 @@ public enum ContainerAnimations { * A fade between the old and new view */ FADE(c -> - Arrays.asList(new KeyFrame(Duration.ZERO, new KeyValue(c.getSnapshot().opacityProperty(), 1.0D, Interpolator.EASE_BOTH)), - new KeyFrame(c.getDuration(), new KeyValue(c.getSnapshot().opacityProperty(), 0.0D, Interpolator.EASE_BOTH)))), + Arrays.asList(new KeyFrame(Duration.ZERO, + new KeyValue(c.getPreviousNode().opacityProperty(), 1.0D, Interpolator.EASE_BOTH), + new KeyValue(c.getCurrentNode().opacityProperty(), 0.0D, Interpolator.EASE_BOTH)), + new KeyFrame(c.getDuration(), + new KeyValue(c.getPreviousNode().opacityProperty(), 0.0D, Interpolator.EASE_BOTH), + new KeyValue(c.getCurrentNode().opacityProperty(), 1.0D, Interpolator.EASE_BOTH)))), /** * A zoom effect */ ZOOM_IN(c -> Arrays.asList(new KeyFrame(Duration.ZERO, - new KeyValue(c.getSnapshot().scaleXProperty(), 1, Interpolator.EASE_BOTH), - new KeyValue(c.getSnapshot().scaleYProperty(), 1, Interpolator.EASE_BOTH), - new KeyValue(c.getSnapshot().opacityProperty(), 1.0D, Interpolator.EASE_BOTH)), + new KeyValue(c.getPreviousNode().scaleXProperty(), 1, Interpolator.EASE_BOTH), + new KeyValue(c.getPreviousNode().scaleYProperty(), 1, Interpolator.EASE_BOTH), + new KeyValue(c.getPreviousNode().opacityProperty(), 1.0D, Interpolator.EASE_BOTH)), new KeyFrame(c.getDuration(), - new KeyValue(c.getSnapshot().scaleXProperty(), 4, Interpolator.EASE_BOTH), - new KeyValue(c.getSnapshot().scaleYProperty(), 4, Interpolator.EASE_BOTH), - new KeyValue(c.getSnapshot().opacityProperty(), 0, Interpolator.EASE_BOTH)))), + new KeyValue(c.getPreviousNode().scaleXProperty(), 4, Interpolator.EASE_BOTH), + new KeyValue(c.getPreviousNode().scaleYProperty(), 4, Interpolator.EASE_BOTH), + new KeyValue(c.getPreviousNode().opacityProperty(), 0, Interpolator.EASE_BOTH)))), /** * A zoom effect */ ZOOM_OUT(c -> (Arrays.asList(new KeyFrame(Duration.ZERO, - new KeyValue(c.getSnapshot().scaleXProperty(), 1, Interpolator.EASE_BOTH), - new KeyValue(c.getSnapshot().scaleYProperty(), 1, Interpolator.EASE_BOTH), - new KeyValue(c.getSnapshot().opacityProperty(), 1.0D, Interpolator.EASE_BOTH)), + new KeyValue(c.getPreviousNode().scaleXProperty(), 1, Interpolator.EASE_BOTH), + new KeyValue(c.getPreviousNode().scaleYProperty(), 1, Interpolator.EASE_BOTH), + new KeyValue(c.getPreviousNode().opacityProperty(), 1.0D, Interpolator.EASE_BOTH)), new KeyFrame(c.getDuration(), - new KeyValue(c.getSnapshot().scaleXProperty(), 0, Interpolator.EASE_BOTH), - new KeyValue(c.getSnapshot().scaleYProperty(), 0, Interpolator.EASE_BOTH), - new KeyValue(c.getSnapshot().opacityProperty(), 0, Interpolator.EASE_BOTH))))), + new KeyValue(c.getPreviousNode().scaleXProperty(), 0, Interpolator.EASE_BOTH), + new KeyValue(c.getPreviousNode().scaleYProperty(), 0, Interpolator.EASE_BOTH), + new KeyValue(c.getPreviousNode().opacityProperty(), 0, Interpolator.EASE_BOTH))))), /** * A swipe effect */ SWIPE_LEFT(c -> Arrays.asList(new KeyFrame(Duration.ZERO, - new KeyValue(c.getCurrentRoot().translateXProperty(), c.getCurrentRoot().getWidth(), Interpolator.EASE_BOTH), - new KeyValue(c.getSnapshot().translateXProperty(), -c.getCurrentRoot().getWidth(), Interpolator.EASE_BOTH)), + new KeyValue(c.getCurrentNode().translateXProperty(), c.getCurrentRoot().getWidth(), Interpolator.EASE_BOTH), + new KeyValue(c.getPreviousNode().translateXProperty(), 0, Interpolator.EASE_BOTH)), new KeyFrame(c.getDuration(), - new KeyValue(c.getCurrentRoot().translateXProperty(), 0, Interpolator.EASE_BOTH), - new KeyValue(c.getSnapshot().translateXProperty(), -c.getCurrentRoot().getWidth(), Interpolator.EASE_BOTH)))), + new KeyValue(c.getCurrentNode().translateXProperty(), 0, Interpolator.EASE_BOTH), + new KeyValue(c.getPreviousNode().translateXProperty(), -c.getCurrentRoot().getWidth(), Interpolator.EASE_BOTH)))), /** * A swipe effect */ SWIPE_RIGHT(c -> Arrays.asList(new KeyFrame(Duration.ZERO, - new KeyValue(c.getCurrentRoot().translateXProperty(), -c.getCurrentRoot().getWidth(), Interpolator.EASE_BOTH), - new KeyValue(c.getSnapshot().translateXProperty(), c.getCurrentRoot().getWidth(), Interpolator.EASE_BOTH)), + new KeyValue(c.getCurrentNode().translateXProperty(), -c.getCurrentRoot().getWidth(), Interpolator.EASE_BOTH), + new KeyValue(c.getPreviousNode().translateXProperty(), 0, Interpolator.EASE_BOTH)), new KeyFrame(c.getDuration(), - new KeyValue(c.getCurrentRoot().translateXProperty(), 0, Interpolator.EASE_BOTH), - new KeyValue(c.getSnapshot().translateXProperty(), c.getCurrentRoot().getWidth(), Interpolator.EASE_BOTH)))); + new KeyValue(c.getCurrentNode().translateXProperty(), 0, Interpolator.EASE_BOTH), + new KeyValue(c.getPreviousNode().translateXProperty(), c.getCurrentRoot().getWidth(), Interpolator.EASE_BOTH)))); private AnimationProducer animationProducer; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/animation/TransitionHandler.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/animation/TransitionHandler.java index d1e06eae5..edf164eca 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/animation/TransitionHandler.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/animation/TransitionHandler.java @@ -32,22 +32,24 @@ public final class TransitionHandler implements AnimationHandler { private final StackPane view; private Timeline animation; private Duration duration; - private final ImageView snapshot; + private Node previousNode, currentNode; /** - * @param view A stack pane that contains another control that is [Parent] + * @param view A stack pane that contains another control that is {@link Parent} */ public TransitionHandler(StackPane view) { this.view = view; - - snapshot = new ImageView(); - snapshot.setPreserveRatio(true); - snapshot.setSmooth(true); + currentNode = view.getChildren().stream().findFirst().orElse(null); } @Override - public Node getSnapshot() { - return snapshot; + public Node getPreviousNode() { + return previousNode; + } + + @Override + public Node getCurrentNode() { + return currentNode; } @Override @@ -76,10 +78,7 @@ public final class TransitionHandler implements AnimationHandler { Timeline nowAnimation = new Timeline(); nowAnimation.getKeyFrames().addAll(transition.animate(this)); nowAnimation.getKeyFrames().add(new KeyFrame(duration, e -> { - snapshot.setImage(null); - snapshot.setX(0); - snapshot.setY(0); - snapshot.setVisible(false); + view.getChildren().remove(previousNode); })); nowAnimation.play(); animation = nowAnimation; @@ -87,23 +86,16 @@ public final class TransitionHandler implements AnimationHandler { private void updateContent(Node newView) { if (view.getWidth() > 0 && view.getHeight() > 0) { - Node content = view.getChildren().stream().findFirst().orElse(null); - WritableImage image; - if (content != null && content instanceof Parent) { - view.getChildren().setAll(); - image = FXUtils.takeSnapshot((Parent) content, view.getWidth(), view.getHeight()); - view.getChildren().setAll(content); - } else - image = view.snapshot(new SnapshotParameters(), new WritableImage((int) view.getWidth(), (int) view.getHeight())); - snapshot.setImage(image); - snapshot.setFitWidth(view.getWidth()); - snapshot.setFitHeight(view.getHeight()); + previousNode = currentNode; + if (previousNode == null) + previousNode = NULL; } else - snapshot.setImage(null); + previousNode = NULL; - snapshot.setVisible(true); - snapshot.setOpacity(1.0); - view.getChildren().setAll(snapshot, newView); - snapshot.toFront(); + currentNode = newView; + + view.getChildren().setAll(previousNode, currentNode); } + + private static final StackPane NULL = new StackPane(); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/FileItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/FileItem.java index 3126c187d..04f51bb49 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/FileItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/FileItem.java @@ -26,7 +26,9 @@ import javafx.scene.control.Tooltip; import javafx.scene.layout.BorderPane; import javafx.scene.layout.VBox; import javafx.stage.DirectoryChooser; +import org.jackhuang.hmcl.Main; import org.jackhuang.hmcl.ui.Controllers; +import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.ui.SVG; import java.io.File; @@ -51,6 +53,7 @@ public class FileItem extends BorderPane { right.setGraphic(SVG.pencil("black", 15, 15)); right.getStyleClass().add("toggle-icon4"); right.setOnMouseClicked(e -> onExplore()); + FXUtils.installTooltip(right, 0, 5000, 0, new Tooltip(Main.i18n("button.edit"))); setRight(right); Tooltip tip = new Tooltip(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MessageDialogPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MessageDialogPane.java index ba9322a72..081c638f3 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MessageDialogPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MessageDialogPane.java @@ -24,6 +24,8 @@ import javafx.scene.control.Label; import javafx.scene.layout.StackPane; import org.jackhuang.hmcl.ui.FXUtils; +import java.util.Optional; + public final class MessageDialogPane extends StackPane { private final String text; private final JFXDialog dialog; @@ -32,13 +34,22 @@ public final class MessageDialogPane extends StackPane { private JFXButton acceptButton; @FXML private Label content; + @FXML + private Label title; - public MessageDialogPane(String text, JFXDialog dialog) { + public MessageDialogPane(String text, String title, JFXDialog dialog, Runnable onAccept) { this.text = text; this.dialog = dialog; FXUtils.loadFXML(this, "/assets/fxml/message-dialog.fxml"); + + if (title != null) + this.title.setText(title); + content.setText(text); - acceptButton.setOnMouseClicked(e -> dialog.close()); + acceptButton.setOnMouseClicked(e -> { + dialog.close(); + Optional.ofNullable(onAccept).ifPresent(Runnable::run); + }); } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/LaunchingStepsPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskExecutorDialogPane.java similarity index 51% rename from HMCL/src/main/java/org/jackhuang/hmcl/ui/LaunchingStepsPane.java rename to HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskExecutorDialogPane.java index 996a8511f..5d09f599f 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/LaunchingStepsPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskExecutorDialogPane.java @@ -15,37 +15,80 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see {http://www.gnu.org/licenses/}. */ -package org.jackhuang.hmcl.ui; +package org.jackhuang.hmcl.ui.construct; +import com.jfoenix.controls.JFXButton; import com.jfoenix.controls.JFXProgressBar; +import javafx.beans.property.StringProperty; import javafx.fxml.FXML; import javafx.scene.control.Label; import javafx.scene.layout.StackPane; +import javafx.scene.layout.VBox; +import org.jackhuang.hmcl.task.TaskExecutor; +import org.jackhuang.hmcl.ui.FXUtils; +import org.jackhuang.hmcl.ui.construct.TaskListPane; + +import java.util.Optional; + +public class TaskExecutorDialogPane extends StackPane { + private TaskExecutor executor; -public class LaunchingStepsPane extends StackPane { @FXML private JFXProgressBar pgsTasks; @FXML private Label lblCurrentState; @FXML private Label lblSteps; + @FXML + private JFXButton btnCancel; + @FXML + private TaskListPane taskListPane; - public LaunchingStepsPane() { + public TaskExecutorDialogPane(Runnable cancel) { FXUtils.loadFXML(this, "/assets/fxml/launching-steps.fxml"); FXUtils.limitHeight(this, 200); FXUtils.limitWidth(this, 400); + + btnCancel.setOnMouseClicked(e -> { + Optional.ofNullable(executor).ifPresent(TaskExecutor::cancel); + cancel.run(); + }); + } + + public void setExecutor(TaskExecutor executor) { + this.executor = executor; + taskListPane.setExecutor(executor); + } + + public StringProperty currentStateProperty() { + return lblCurrentState.textProperty(); + } + + public String getCurrentState() { + return lblCurrentState.getText(); } public void setCurrentState(String currentState) { lblCurrentState.setText(currentState); } + public StringProperty stepsProperty() { + return lblSteps.textProperty(); + } + + public String getSteps() { + return lblSteps.getText(); + } + public void setSteps(String steps) { lblSteps.setText(steps); } public void setProgress(double progress) { - pgsTasks.setProgress(progress); + if (progress == Double.MAX_VALUE) + pgsTasks.setVisible(false); + else + pgsTasks.setProgress(progress); } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskExecutorDialogWizardDisplayer.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskExecutorDialogWizardDisplayer.java new file mode 100644 index 000000000..8fc9f3acc --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskExecutorDialogWizardDisplayer.java @@ -0,0 +1,84 @@ +/* + * Hello Minecraft! Launcher. + * Copyright (C) 2017 huangyuhui + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see {http://www.gnu.org/licenses/}. + */ +package org.jackhuang.hmcl.ui.construct; + +import com.jfoenix.concurrency.JFXUtilities; +import javafx.beans.property.StringProperty; +import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.task.Task; +import org.jackhuang.hmcl.task.TaskExecutor; +import org.jackhuang.hmcl.task.TaskListener; +import org.jackhuang.hmcl.ui.Controllers; +import org.jackhuang.hmcl.ui.wizard.AbstractWizardDisplayer; +import org.jackhuang.hmcl.util.OperatingSystem; +import org.jackhuang.hmcl.util.StringUtils; + +import java.util.Map; + +public interface TaskExecutorDialogWizardDisplayer extends AbstractWizardDisplayer { + + @Override + default void handleTask(Map settings, Task task) { + TaskExecutorDialogPane pane = new TaskExecutorDialogPane(() -> { + Controllers.closeDialog(); + Controllers.navigate(null); + }); + + pane.setCurrentState(Main.i18n("message.doing")); + pane.setProgress(Double.MAX_VALUE); + if (settings.containsKey("title")) { + Object title = settings.get("title"); + if (title instanceof StringProperty) + pane.currentStateProperty().bind((StringProperty) title); + else if (title instanceof String) + pane.setCurrentState((String) title); + } + + if (settings.containsKey("subtitle")) { + Object subtitle = settings.get("subtitle"); + if (subtitle instanceof StringProperty) + pane.stepsProperty().bind((StringProperty) subtitle); + else if (subtitle instanceof String) + pane.setSteps((String) subtitle); + } + + JFXUtilities.runInFX(() -> { + TaskExecutor executor = task.executor(e -> new TaskListener() { + @Override + public void onSucceed() { + if (settings.containsKey("success_message") && settings.get("success_message") instanceof String) + JFXUtilities.runInFX(() -> Controllers.dialog((String) settings.get("success_message"), null, () -> Controllers.navigate(null))); + else if (!settings.containsKey("forbid_success_message")) + JFXUtilities.runInFX(() -> Controllers.dialog(Main.i18n("message.success"), null, () -> Controllers.navigate(null))); + } + + @Override + public void onTerminate() { + String appendix = StringUtils.getStackTrace(e.getLastException()); + if (settings.containsKey("failure_message") && settings.get("failure_message") instanceof String) + JFXUtilities.runInFX(() -> Controllers.dialog(appendix, (String) settings.get("failure_message"), () -> Controllers.navigate(null))); + else if (!settings.containsKey("forbid_failure_message")) + JFXUtilities.runInFX(() -> Controllers.dialog(appendix, Main.i18n("wizard.failed"), () -> Controllers.navigate(null))); + } + }); + pane.setExecutor(executor); + Controllers.dialog(pane); + executor.start(); + }); + } +} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskListPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskListPane.java index 7e3157279..70b23dee2 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskListPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskListPane.java @@ -23,6 +23,7 @@ import javafx.scene.control.Label; import javafx.scene.layout.BorderPane; import javafx.scene.layout.Region; import javafx.scene.layout.StackPane; +import javafx.scene.layout.VBox; import org.jackhuang.hmcl.Main; import org.jackhuang.hmcl.download.forge.ForgeInstallTask; import org.jackhuang.hmcl.download.game.GameAssetDownloadTask; @@ -45,22 +46,26 @@ import java.util.Map; import java.util.Optional; public final class TaskListPane extends StackPane { - private final TaskExecutor executor; private final AdvancedListBox listBox = new AdvancedListBox(); private final Map nodes = new HashMap<>(); - public TaskListPane(TaskExecutor executor, Runnable onTerminate) { - this.executor = executor; + public TaskListPane() { listBox.setSpacing(0); + getChildren().setAll(listBox); + } + + public void setExecutor(TaskExecutor executor) { executor.addTaskListener(new TaskListener() { + @Override + public void onStart() { + Platform.runLater(listBox::clear); + } + @Override public void onReady(Task task) { if (!task.getSignificance().shouldShow()) return; - ProgressListNode node = new ProgressListNode(task); - nodes.put(task, node); - Platform.runLater(() -> listBox.add(node)); if (task instanceof GameAssetRefreshTask) { task.setName(Main.i18n("assets.download")); @@ -83,6 +88,11 @@ public final class TaskListPane extends StackPane { } else if (task instanceof HMCLModpackExportTask) { task.setName(Main.i18n("modpack.export")); } + + ProgressListNode node = new ProgressListNode(task); + nodes.put(task, node); + Platform.runLater(() -> listBox.add(node)); + } @Override @@ -101,17 +111,10 @@ public final class TaskListPane extends StackPane { return; Platform.runLater(() -> node.setThrowable(throwable)); } - - @Override - public void onTerminate() { - Optional.ofNullable(onTerminate).ifPresent(Runnable::run); - } }); - - getChildren().setAll(listBox); } - private static class ProgressListNode extends StackPane { + private static class ProgressListNode extends VBox { private final JFXProgressBar bar = new JFXProgressBar(); private final Label title = new Label(); private final Label state = new Label(); @@ -124,9 +127,8 @@ public final class TaskListPane extends StackPane { BorderPane borderPane = new BorderPane(); borderPane.setLeft(title); borderPane.setRight(state); - getChildren().addAll(bar, borderPane); + getChildren().addAll(borderPane, bar); - bar.setMinHeight(20); bar.minWidthProperty().bind(widthProperty()); bar.prefWidthProperty().bind(widthProperty()); bar.maxWidthProperty().bind(widthProperty()); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/AdditionalInstallersPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/AdditionalInstallersPage.java index d2cc404f0..e36e5b137 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/AdditionalInstallersPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/AdditionalInstallersPage.java @@ -22,6 +22,7 @@ import javafx.fxml.FXML; import javafx.scene.control.Label; import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; +import org.jackhuang.hmcl.Main; import org.jackhuang.hmcl.download.DownloadProvider; import org.jackhuang.hmcl.game.GameRepository; import org.jackhuang.hmcl.ui.FXUtils; @@ -36,26 +37,31 @@ import static org.jackhuang.hmcl.Main.i18n; class AdditionalInstallersPage extends StackPane implements WizardPage { private final InstallerWizardProvider provider; private final WizardController controller; - private final GameRepository repository; - private final DownloadProvider downloadProvider; - @FXML private VBox list; - @FXML private JFXButton btnForge; - @FXML private JFXButton btnLiteLoader; - @FXML private JFXButton btnOptiFine; - @FXML private Label lblGameVersion; - @FXML private Label lblVersionName; - @FXML private Label lblForge; - @FXML private Label lblLiteLoader; + @FXML + private VBox list; + @FXML + private JFXButton btnForge; + @FXML + private JFXButton btnLiteLoader; + @FXML + private JFXButton btnOptiFine; + @FXML + private Label lblGameVersion; + @FXML + private Label lblVersionName; + @FXML + private Label lblForge; + @FXML + private Label lblLiteLoader; @FXML private Label lblOptiFine; - @FXML private JFXButton btnInstall; + @FXML + private JFXButton btnInstall; public AdditionalInstallersPage(InstallerWizardProvider provider, WizardController controller, GameRepository repository, DownloadProvider downloadProvider) { this.provider = provider; this.controller = controller; - this.repository = repository; - this.downloadProvider = downloadProvider; FXUtils.loadFXML(this, "/assets/fxml/download/additional-installers.fxml"); @@ -64,55 +70,64 @@ class AdditionalInstallersPage extends StackPane implements WizardPage { btnForge.setOnMouseClicked(e -> { controller.getSettings().put(INSTALLER_TYPE, 0); - controller.onNext(new VersionsPage(controller, i18n("install.installer.choose", i18n("install.installer.forge")), provider.getGameVersion(), downloadProvider, "forge", () -> { controller.onPrev(false); })); + controller.onNext(new VersionsPage(controller, i18n("install.installer.choose", i18n("install.installer.forge")), provider.getGameVersion(), downloadProvider, "forge", () -> { + controller.onPrev(false); + })); }); btnLiteLoader.setOnMouseClicked(e -> { controller.getSettings().put(INSTALLER_TYPE, 1); - controller.onNext(new VersionsPage(controller, i18n("install.installer.choose", i18n("install.installer.liteloader")), provider.getGameVersion(), downloadProvider, "liteloader", () -> { controller.onPrev(false); })); + controller.onNext(new VersionsPage(controller, i18n("install.installer.choose", i18n("install.installer.liteloader")), provider.getGameVersion(), downloadProvider, "liteloader", () -> { + controller.onPrev(false); + })); }); btnOptiFine.setOnMouseClicked(e -> { controller.getSettings().put(INSTALLER_TYPE, 2); - controller.onNext(new VersionsPage(controller, i18n("install.installer.choose", i18n("install.installer.optifine")), provider.getGameVersion(), downloadProvider, "optifine", () -> { controller.onPrev(false); })); + controller.onNext(new VersionsPage(controller, i18n("install.installer.choose", i18n("install.installer.optifine")), provider.getGameVersion(), downloadProvider, "optifine", () -> { + controller.onPrev(false); + })); }); + + btnInstall.setOnMouseClicked(e -> onInstall()); + } + + private void onInstall() { + controller.onFinish(); } @Override public String getTitle() { - return "Choose a game version"; + return Main.i18n("settings.tabs.installers"); } @Override public void onNavigate(Map settings) { - lblGameVersion.setText("Current Game Version: " + provider.getGameVersion()); + lblGameVersion.setText(Main.i18n("install.new_game.current_game_version") + ": " + provider.getGameVersion()); btnForge.setDisable(provider.getForge() != null); if (provider.getForge() != null || controller.getSettings().containsKey("forge")) - lblForge.setText("Forge Versoin: " + Lang.nonNull(provider.getForge(), controller.getSettings().get("forge"))); + lblForge.setText(Main.i18n("install.installer.version", Main.i18n("install.installer.forge")) + ": " + Lang.nonNull(provider.getForge(), controller.getSettings().get("forge"))); else - lblForge.setText("Forge not installed"); + lblForge.setText(Main.i18n("install.installer.not_installed", Main.i18n("install.installer.forge"))); btnLiteLoader.setDisable(provider.getLiteLoader() != null); if (provider.getLiteLoader() != null || controller.getSettings().containsKey("liteloader")) - lblLiteLoader.setText("LiteLoader Versoin: " + Lang.nonNull(provider.getLiteLoader(), controller.getSettings().get("liteloader"))); + lblLiteLoader.setText(Main.i18n("install.installer.version", Main.i18n("install.installer.liteloader")) + ": " + Lang.nonNull(provider.getLiteLoader(), controller.getSettings().get("liteloader"))); else - lblLiteLoader.setText("LiteLoader not installed"); + lblLiteLoader.setText(Main.i18n("install.installer.not_installed", Main.i18n("install.installer.liteloader"))); btnOptiFine.setDisable(provider.getOptiFine() != null); if (provider.getOptiFine() != null || controller.getSettings().containsKey("optifine")) - lblOptiFine.setText("OptiFine Versoin: " + Lang.nonNull(provider.getOptiFine(), controller.getSettings().get("optifine"))); + lblOptiFine.setText(Main.i18n("install.installer.version", Main.i18n("install.installer.optifine")) + ": " + Lang.nonNull(provider.getOptiFine(), controller.getSettings().get("optifine"))); else - lblOptiFine.setText("OptiFine not installed"); + lblOptiFine.setText(Main.i18n("install.installer.not_installed", Main.i18n("install.installer.optifine"))); } - @Override public void cleanup(Map settings) { - settings.remove(INSTALLER_TYPE); - } + @Override + public void cleanup(Map settings) { + settings.remove(INSTALLER_TYPE); + } - public void onInstall() { - controller.onFinish(); - } - - public static final String INSTALLER_TYPE = "INSTALLER_TYPE"; + public static final String INSTALLER_TYPE = "INSTALLER_TYPE"; } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/DownloadWizardProvider.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/DownloadWizardProvider.java index 798f65419..bee40d140 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/DownloadWizardProvider.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/DownloadWizardProvider.java @@ -18,6 +18,7 @@ package org.jackhuang.hmcl.ui.download; import javafx.scene.Node; +import org.jackhuang.hmcl.Main; import org.jackhuang.hmcl.download.DownloadProvider; import org.jackhuang.hmcl.download.GameBuilder; import org.jackhuang.hmcl.game.HMCLModpackInstallTask; @@ -77,7 +78,7 @@ public final class DownloadWizardProvider implements WizardProvider { profile.getRepository().markVersionAsModpack(name); Task finalizeTask = Task.of(() -> { - profile.getRepository().refreshVersions(); + profile.getRepository().refreshVersionsAsync().start(); VersionSetting vs = profile.specializeVersionSetting(name); profile.getRepository().undoMark(name); if (vs != null) @@ -99,6 +100,9 @@ public final class DownloadWizardProvider implements WizardProvider { @Override public Object finish(Map settings) { + settings.put("success_message", Main.i18n("install.success")); + settings.put("failure_message", Main.i18n("install.failed")); + switch (Lang.parseInt(settings.get(InstallTypePage.INSTALL_TYPE), -1)) { case 0: return finishVersionDownloadingAsync(settings); case 1: return finishModpackInstallingAsync(settings); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallerWizardProvider.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallerWizardProvider.java index 8795b3de4..2ee89c5eb 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallerWizardProvider.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallerWizardProvider.java @@ -18,6 +18,7 @@ package org.jackhuang.hmcl.ui.download; import javafx.scene.Node; +import org.jackhuang.hmcl.Main; import org.jackhuang.hmcl.download.BMCLAPIDownloadProvider; import org.jackhuang.hmcl.game.Version; import org.jackhuang.hmcl.setting.Profile; @@ -78,18 +79,21 @@ public final class InstallerWizardProvider implements WizardProvider { @Override public Object finish(Map settings) { + settings.put("success_message", Main.i18n("install.success")); + settings.put("failure_message", Main.i18n("install.failed")); + Task ret = Task.empty(); if (settings.containsKey("forge")) - ret = ret.with(profile.getDependency().installLibraryAsync(gameVersion, version, "forge", (String) settings.get("forge"))); + ret = ret.then(profile.getDependency().installLibraryAsync(gameVersion, version, "forge", (String) settings.get("forge"))); if (settings.containsKey("liteloader")) - ret = ret.with(profile.getDependency().installLibraryAsync(gameVersion, version, "liteloader", (String) settings.get("liteloader"))); + ret = ret.then(profile.getDependency().installLibraryAsync(gameVersion, version, "liteloader", (String) settings.get("liteloader"))); if (settings.containsKey("optifine")) - ret = ret.with(profile.getDependency().installLibraryAsync(gameVersion, version, "optifine", (String) settings.get("optifine"))); + ret = ret.then(profile.getDependency().installLibraryAsync(gameVersion, version, "optifine", (String) settings.get("optifine"))); - return ret.with(Task.of(profile.getRepository()::refreshVersions)); + return ret.then(profile.getRepository().refreshVersionsAsync()); } @Override diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ModpackInfoPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ModpackInfoPage.java index b32384949..7e967fc2a 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ModpackInfoPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ModpackInfoPage.java @@ -104,7 +104,7 @@ public final class ModpackInfoPage extends StackPane implements WizardPage { public static final String MODPACK_NAME = "modpack.name"; public static final String MODPACK_VERSION = "modpack.version"; - public static final String MODPACK_AUTHOR = "modpack.author"; + public static final String MODPACK_AUTHOR = "archive.author"; public static final String MODPACK_DESCRIPTION = "modpack.description"; public static final String MODPACK_INCLUDE_LAUNCHER = "modpack.include_launcher"; public static final String MODPACK_FILE = "modpack.file"; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/AbstractWizardDisplayer.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/AbstractWizardDisplayer.java index 33c207433..0f9071a5c 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/AbstractWizardDisplayer.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/AbstractWizardDisplayer.java @@ -38,62 +38,11 @@ public interface AbstractWizardDisplayer extends WizardDisplayer { Queue getCancelQueue(); - @Override - default void handleDeferredWizardResult(Map settings, DeferredWizardResult deferredWizardResult) { - VBox vbox = new VBox(); - JFXProgressBar progressBar = new JFXProgressBar(); - Label label = new Label(); - progressBar.setMaxHeight(10); - vbox.getChildren().addAll(progressBar, label); - - StackPane root = new StackPane(); - root.getChildren().add(vbox); - navigateTo(root, Navigation.NavigationDirection.FINISH); - - getCancelQueue().add(Lang.thread(() -> { - deferredWizardResult.start(settings, new ResultProgressHandle() { - private boolean running = true; - - @Override - public void setProgress(int currentStep, int totalSteps) { - progressBar.setProgress(1.0 * currentStep / totalSteps); - } - - @Override - public void setProgress(String description, int currentStep, int totalSteps) { - label.setText(description); - progressBar.setProgress(1.0 * currentStep / totalSteps); - } - - @Override - public void setBusy(String description) { - progressBar.setProgress(JFXProgressBar.INDETERMINATE_PROGRESS); - } - - @Override - public void finished(Object result) { - running = false; - } - - @Override - public void failed(String message, boolean canNavigateBack) { - running = false; - } - - @Override - public boolean isRunning() { - return running; - } - }); - - Platform.runLater(this::navigateToSuccess); - })); - } - @Override default void handleTask(Map settings, Task task) { TaskExecutor executor = task.with(Task.of(Schedulers.javafx(), this::navigateToSuccess)).executor(); - TaskListPane pane = new TaskListPane(executor, () -> Platform.runLater(AbstractWizardDisplayer.this::navigateToSuccess)); + TaskListPane pane = new TaskListPane(); + pane.setExecutor(executor); navigateTo(pane, Navigation.NavigationDirection.FINISH); getCancelQueue().add(executor); executor.start(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/DefaultWizardDisplayer.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/DefaultWizardDisplayer.java index d19dd4146..993ebbf79 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/DefaultWizardDisplayer.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/DefaultWizardDisplayer.java @@ -28,6 +28,7 @@ import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.ui.animation.TransitionHandler; import org.jackhuang.hmcl.util.StringUtils; +import java.util.Map; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/ResultProgressHandle.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/ResultProgressHandle.java deleted file mode 100644 index a15857168..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/ResultProgressHandle.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2017 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.ui.wizard; - -/** - * A controller for the progress bar shown in the user interface. Used in - * conjunction then `DeferredWizardResult` for cases where at - * the conclusion of the wizard, the work to create the final wizard result - * will take a while and needs to happen on a background thread. - * @author Tim Boudreau - */ -public interface ResultProgressHandle { - - /** - * Set the current position and total number of steps. Note it is - * inadvisable to be holding any locks when calling this method, as it - * may immediately update the GUI using - * `EventQueue.invokeAndWait()`. - * - * @param currentStep the current step in the progress of computing the - * * result. - * * - * @param totalSteps the total number of steps. Must be greater than - * * or equal to currentStep. - */ - void setProgress(int currentStep, int totalSteps); - - /** - * Set the current position and total number of steps, and description - * of what the computation is doing. Note it is - * inadvisable to be holding any locks when calling this method, as it - * may immediately update the GUI using - * `EventQueue.invokeAndWait()`. - * @param description Text to describe what is being done, which can - * * be displayed in the UI. - * * - * @param currentStep the current step in the progress of computing the - * * result. - * * - * @param totalSteps the total number of steps. Must be greater than - * * or equal to currentStep. - */ - void setProgress(String description, int currentStep, int totalSteps); - - /** - * Set the status as "busy" - a rotating icon will be displayed instead - * of a percent complete progress bar. - - * Note it is inadvisable to be holding any locks when calling this method, as it - * may immediately update the GUI using - * `EventQueue.invokeAndWait()`. - * @param description Text to describe what is being done, which can - * * be displayed in the UI. - */ - void setBusy(String description); - - /** - * Call this method when the computation is complete, and pass in the - * final result of the computation. The method doing the computation - * (`DeferredWizardResult.start()` or something it - * called) should exit immediately after calling this method. If the - * `failed()` method is called after this method has been - * called, a runtime exception may be thrown. - * @param result the Object which was computed, if any. - */ - void finished(Object result); - - /** - * Call this method if computation fails. The message may be some text - * describing what went wrong, or null if no description. - * @param message The text to display to the user. The method - * * doing the computation (`DeferredWizardResult.start()` or something it - * * called). If the `finished()` method is called after this - * * method has been called, a runtime exception may be thrown. - * * should exit immediately after calling this method. - * * It is A description of what went wrong, or null. - * * - * @param canNavigateBack whether or not the Prev button should be - * * enabled. - */ - void failed(String message, boolean canNavigateBack); - - /** - * Returns true if the computation is still running, i.e., if neither finished or failed have been called. - * - * @return true if there is no result yet. - */ - boolean isRunning(); -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/Summary.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/Summary.java index 2421479a3..96d2eb146 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/Summary.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/Summary.java @@ -44,6 +44,11 @@ public final class Summary { this.result = result; } + public Summary(Node component, Object result) { + this.component = component; + this.result = result; + } + /** * The component that will display the summary information */ diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/WizardController.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/WizardController.java index 34a728c4a..1fb61447b 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/WizardController.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/WizardController.java @@ -100,8 +100,7 @@ public class WizardController implements Navigation { @Override public void onFinish() { Object result = provider.finish(settings); - if (result instanceof DeferredWizardResult) displayer.handleDeferredWizardResult(settings, ((DeferredWizardResult) result)); - else if (result instanceof Summary) displayer.navigateTo(((Summary) result).getComponent(), NavigationDirection.NEXT); + if (result instanceof Summary) displayer.navigateTo(((Summary) result).getComponent(), NavigationDirection.NEXT); else if (result instanceof Task) displayer.handleTask(settings, ((Task) result)); else if (result != null) throw new IllegalStateException("Unrecognized wizard result: " + result); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/WizardDisplayer.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/WizardDisplayer.java index 4f9f2ecf7..a7f508670 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/WizardDisplayer.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/WizardDisplayer.java @@ -27,6 +27,5 @@ public interface WizardDisplayer { void onEnd(); void onCancel(); void navigateTo(Node page, Navigation.NavigationDirection nav); - void handleDeferredWizardResult(Map settings, DeferredWizardResult deferredWizardResult); void handleTask(Map settings, Task task); } diff --git a/HMCL/src/main/resources/assets/fxml/account.fxml b/HMCL/src/main/resources/assets/fxml/account.fxml index 97e9db58b..cf0cafeb6 100644 --- a/HMCL/src/main/resources/assets/fxml/account.fxml +++ b/HMCL/src/main/resources/assets/fxml/account.fxml @@ -51,7 +51,7 @@ - + diff --git a/HMCL/src/main/resources/assets/fxml/download/additional-installers.fxml b/HMCL/src/main/resources/assets/fxml/download/additional-installers.fxml index e2fd0776a..e2a11972b 100644 --- a/HMCL/src/main/resources/assets/fxml/download/additional-installers.fxml +++ b/HMCL/src/main/resources/assets/fxml/download/additional-installers.fxml @@ -55,8 +55,8 @@ - + diff --git a/HMCL/src/main/resources/assets/fxml/download/installers.fxml b/HMCL/src/main/resources/assets/fxml/download/installers.fxml index 57f07cbb2..2b6d20360 100644 --- a/HMCL/src/main/resources/assets/fxml/download/installers.fxml +++ b/HMCL/src/main/resources/assets/fxml/download/installers.fxml @@ -56,7 +56,7 @@ + buttonType="RAISED" text="%button.install" styleClass="jfx-button-raised"/> diff --git a/HMCL/src/main/resources/assets/fxml/download/modpack.fxml b/HMCL/src/main/resources/assets/fxml/download/modpack.fxml index d4801aad3..88d310314 100644 --- a/HMCL/src/main/resources/assets/fxml/download/modpack.fxml +++ b/HMCL/src/main/resources/assets/fxml/download/modpack.fxml @@ -18,11 +18,11 @@ - + - + diff --git a/HMCL/src/main/resources/assets/fxml/input-dialog.fxml b/HMCL/src/main/resources/assets/fxml/input-dialog.fxml index cfbd81048..b923c54da 100644 --- a/HMCL/src/main/resources/assets/fxml/input-dialog.fxml +++ b/HMCL/src/main/resources/assets/fxml/input-dialog.fxml @@ -10,7 +10,7 @@ type="StackPane"> - diff --git a/HMCL/src/main/resources/assets/fxml/launching-steps.fxml b/HMCL/src/main/resources/assets/fxml/launching-steps.fxml index b197ba2b1..af45194ff 100644 --- a/HMCL/src/main/resources/assets/fxml/launching-steps.fxml +++ b/HMCL/src/main/resources/assets/fxml/launching-steps.fxml @@ -4,13 +4,19 @@ + + + - + - + + + diff --git a/HMCL/src/main/resources/assets/fxml/log.fxml b/HMCL/src/main/resources/assets/fxml/log.fxml index 0b8652d82..93f8ce793 100644 --- a/HMCL/src/main/resources/assets/fxml/log.fxml +++ b/HMCL/src/main/resources/assets/fxml/log.fxml @@ -52,7 +52,7 @@ - + diff --git a/HMCL/src/main/resources/assets/fxml/message-dialog.fxml b/HMCL/src/main/resources/assets/fxml/message-dialog.fxml index 2ad5380cc..f5831e21e 100644 --- a/HMCL/src/main/resources/assets/fxml/message-dialog.fxml +++ b/HMCL/src/main/resources/assets/fxml/message-dialog.fxml @@ -9,7 +9,7 @@ type="StackPane"> - - - diff --git a/HMCL/src/main/resources/assets/fxml/profile.fxml b/HMCL/src/main/resources/assets/fxml/profile.fxml index 1e82ea284..c8d758c0b 100644 --- a/HMCL/src/main/resources/assets/fxml/profile.fxml +++ b/HMCL/src/main/resources/assets/fxml/profile.fxml @@ -39,11 +39,11 @@ + buttonType="RAISED" text="%button.delete" styleClass="jfx-button-raised" /> + buttonType="RAISED" text="%button.save" styleClass="jfx-button-raised"/> diff --git a/HMCL/src/main/resources/assets/fxml/version-item.fxml b/HMCL/src/main/resources/assets/fxml/version-item.fxml index d536c14b6..4f810c4a3 100644 --- a/HMCL/src/main/resources/assets/fxml/version-item.fxml +++ b/HMCL/src/main/resources/assets/fxml/version-item.fxml @@ -29,25 +29,13 @@ - - - - - + - - - - - - - - - - + + diff --git a/HMCL/src/main/resources/assets/fxml/version/version-settings.fxml b/HMCL/src/main/resources/assets/fxml/version/version-settings.fxml index 3b63e9b85..e57b0112b 100644 --- a/HMCL/src/main/resources/assets/fxml/version/version-settings.fxml +++ b/HMCL/src/main/resources/assets/fxml/version/version-settings.fxml @@ -19,7 +19,9 @@ - diff --git a/HMCL/src/main/resources/assets/fxml/yggdrasil-account-login.fxml b/HMCL/src/main/resources/assets/fxml/yggdrasil-account-login.fxml index 212c7b8fb..e38a1c1fb 100644 --- a/HMCL/src/main/resources/assets/fxml/yggdrasil-account-login.fxml +++ b/HMCL/src/main/resources/assets/fxml/yggdrasil-account-login.fxml @@ -10,12 +10,12 @@ type="StackPane"> -