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 927a70a32..90f9730c9 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java @@ -19,6 +19,7 @@ package org.jackhuang.hmcl.game; import com.jfoenix.concurrency.JFXUtilities; import javafx.application.Platform; +import javafx.scene.layout.Region; import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.auth.Account; import org.jackhuang.hmcl.auth.AuthInfo; @@ -46,13 +47,14 @@ import java.util.*; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Consumer; public final class LauncherHelper { public static final LauncherHelper INSTANCE = new LauncherHelper(); private LauncherHelper(){} public static final Queue PROCESSES = new ConcurrentLinkedQueue<>(); - private final TaskExecutorDialogPane launchingStepsPane = new TaskExecutorDialogPane(() -> {}); + private final TaskExecutorDialogPane launchingStepsPane = new TaskExecutorDialogPane(it -> {}); public void launch(Profile profile, Account account, String selectedVersion, File scriptFile) { if (account == null) @@ -65,7 +67,10 @@ public final class LauncherHelper { Platform.runLater(() -> { try { - checkGameState(profile, setting, version, () -> Schedulers.newThread().schedule(() -> launch0(profile, account, selectedVersion, scriptFile))); + checkGameState(profile, setting, version, () -> { + Controllers.dialog(launchingStepsPane); + Schedulers.newThread().schedule(() -> launch0(profile, account, selectedVersion, scriptFile)); + }); } catch (InterruptedException ignore) { } }); @@ -78,8 +83,7 @@ public final class LauncherHelper { VersionSetting setting = profile.getVersionSetting(selectedVersion); Optional gameVersion = GameVersion.minecraftVersion(repository.getVersionJar(version)); - TaskExecutor executor = Task.of(Schedulers.javafx(), () -> Controllers.dialog(launchingStepsPane)) - .then(Task.of(Schedulers.javafx(), () -> emitStatus(LoadingState.DEPENDENCIES))) + TaskExecutor executor = Task.of(Schedulers.javafx(), () -> emitStatus(LoadingState.DEPENDENCIES)) .then(variables -> { if (setting.isNotCheckGame()) return null; @@ -127,13 +131,13 @@ public final class LauncherHelper { if (setting.getLauncherVisibility() == LauncherVisibility.CLOSE) Launcher.stopApplication(); else - launchingStepsPane.setCancel(() -> { + launchingStepsPane.setCancel(it -> { process.stop(); - Controllers.closeDialog(); + Controllers.closeDialog(it); }); } else Platform.runLater(() -> { - Controllers.closeDialog(); + Controllers.closeDialog(launchingStepsPane); Controllers.dialog(Launcher.i18n("version.launch_script.success", scriptFile.getAbsolutePath())); }); @@ -155,11 +159,11 @@ public final class LauncherHelper { public void onStop(boolean success, TaskExecutor executor) { if (!success) { Platform.runLater(() -> { - Controllers.closeDialog(); + Controllers.closeDialog(launchingStepsPane); if (executor.getLastException() != null) Controllers.dialog(I18nException.getStackTrace(executor.getLastException()), scriptFile == null ? Launcher.i18n("launch.failed") : Launcher.i18n("version.launch_script.failed"), - MessageBox.ERROR_MESSAGE, Controllers::closeDialog); + MessageBox.ERROR_MESSAGE); }); } launchingStepsPane.setExecutor(null); @@ -170,7 +174,7 @@ public final class LauncherHelper { } private static void checkGameState(Profile profile, VersionSetting setting, Version version, Runnable onAccept) throws InterruptedException { - boolean flag = false, suggest = true; + boolean flag = false; VersionNumber gameVersion = VersionNumber.asVersion(GameVersion.minecraftVersion(profile.getRepository().getVersionJar(version)).orElse("Unknown")); JavaVersion java = setting.getJavaVersion(); @@ -188,7 +192,6 @@ public final class LauncherHelper { if (!flag && java.getParsedVersion() >= JavaVersion.JAVA_9 && gameVersion.compareTo(VersionNumber.asVersion("1.12.5")) < 0 && version.getMainClass().contains("launchwrapper")) { Controllers.dialog(Launcher.i18n("launch.advice.java9"), Launcher.i18n("message.error"), MessageBox.ERROR_MESSAGE, null); - suggest = false; flag = true; } @@ -207,10 +210,7 @@ public final class LauncherHelper { flag = true; } - if (flag) { - if (suggest && Controllers.getDialogContent() instanceof MessageDialogPane) - ((MessageDialogPane) Controllers.getDialogContent()).disableClosingDialog(); - } else + if (!flag) onAccept.run(); } @@ -221,7 +221,7 @@ public final class LauncherHelper { public void emitStatus(LoadingState state) { if (state == LoadingState.DONE) - Controllers.closeDialog(); + Controllers.closeDialog(launchingStepsPane); launchingStepsPane.setTitle(state.getLocalizedMessage()); launchingStepsPane.setSubtitle((state.ordinal() + 1) + " / " + LoadingState.values().length); @@ -359,7 +359,9 @@ public final class LauncherHelper { // Never come to here. break; case KEEP: - // No operations here + Platform.runLater(() -> { + emitStatus(LoadingState.DONE); + }); break; case HIDE: Platform.runLater(() -> { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/AccountLoginPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/AccountLoginPane.java index 4d66c6935..344099d5f 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/AccountLoginPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/AccountLoginPane.java @@ -22,12 +22,15 @@ import com.jfoenix.controls.JFXPasswordField; import com.jfoenix.controls.JFXProgressBar; import javafx.fxml.FXML; import javafx.scene.control.Label; +import javafx.scene.layout.Region; import javafx.scene.layout.StackPane; import org.jackhuang.hmcl.auth.Account; import org.jackhuang.hmcl.auth.AuthInfo; import org.jackhuang.hmcl.auth.NoSelectedCharacterException; import org.jackhuang.hmcl.task.Schedulers; import org.jackhuang.hmcl.task.Task; +import org.jackhuang.hmcl.ui.AddAccountPane; +import org.jackhuang.hmcl.ui.FXUtils; import java.util.function.Consumer; @@ -35,18 +38,19 @@ public class AccountLoginPane extends StackPane { private final Account oldAccount; private final Consumer success; private final Runnable failed; + private final Consumer closeConsumer; @FXML private Label lblUsername; @FXML private JFXPasswordField txtPassword; @FXML private Label lblCreationWarning; @FXML private JFXProgressBar progressBar; - private JFXDialog dialog; - public AccountLoginPane(Account oldAccount, Consumer success, Runnable failed) { + public AccountLoginPane(Account oldAccount, Consumer closeConsumer, Consumer success, Runnable failed) { this.oldAccount = oldAccount; this.success = success; this.failed = failed; + this.closeConsumer = closeConsumer; FXUtils.loadFXML(this, "/assets/fxml/account-login.fxml"); @@ -69,9 +73,9 @@ public class AccountLoginPane extends StackPane { Object account = variable.get("login"); if (account instanceof AuthInfo) { success.accept(((AuthInfo) account)); - dialog.close(); + closeConsumer.accept(this); } else if (account instanceof NoSelectedCharacterException) { - dialog.close(); + closeConsumer.accept(this); } else if (account instanceof Exception) { lblCreationWarning.setText(AddAccountPane.accountException((Exception) account)); } @@ -83,10 +87,6 @@ public class AccountLoginPane extends StackPane { @FXML private void onCancel() { failed.run(); - dialog.close(); - } - - public void setDialog(JFXDialog dialog) { - this.dialog = dialog; + closeConsumer.accept(this); } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/AddAccountPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/AddAccountPane.java index 643ad47da..b32868f91 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/AddAccountPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/AddAccountPane.java @@ -28,6 +28,7 @@ import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.BorderPane; import javafx.scene.layout.HBox; +import javafx.scene.layout.Region; import javafx.scene.layout.StackPane; import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.auth.*; @@ -49,6 +50,7 @@ import java.util.Collection; import java.util.List; import java.util.Optional; import java.util.concurrent.CountDownLatch; +import java.util.function.Consumer; import java.util.logging.Level; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -65,9 +67,9 @@ public class AddAccountPane extends StackPane { @FXML private Label lblAddInjectorServer; @FXML private Hyperlink linkAddInjectorServer; @FXML private JFXDialogLayout layout; - private final Runnable finalization; + private final Consumer finalization; - public AddAccountPane(Runnable finalization) { + public AddAccountPane(Consumer finalization) { this.finalization = finalization; FXUtils.loadFXML(this, "/assets/fxml/account-add.fxml"); @@ -133,10 +135,10 @@ public class AddAccountPane extends StackPane { }).finalized(Schedulers.javafx(), variables -> { Settings.INSTANCE.addAccount(variables.get("create_account")); progressBar.setVisible(false); - finalization.run(); + finalization.accept(this); }, exception -> { if (exception instanceof NoSelectedCharacterException) { - finalization.run(); + finalization.accept(this); } else { lblCreationWarning.setText(accountException(exception)); } @@ -146,12 +148,12 @@ public class AddAccountPane extends StackPane { @FXML private void onCreationCancel() { - finalization.run(); + finalization.accept(this); } @FXML private void onAddInjecterServer() { - finalization.run(); + finalization.accept(this); Controllers.navigate(Controllers.getServersPage()); } 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 52dad1769..aa55d198b 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java @@ -117,14 +117,8 @@ public final class Controllers { stage.setTitle(Launcher.TITLE); } - public static Region getDialogContent() { - return decorator.getDialog().getContent(); - } - - public static JFXDialog dialog(Region content) { - // TODO: temp fix - decorator.showDialog(Lang.apply(new Region(), region -> region.getProperties().put("controllers", true))); - return decorator.showDialog(content); + public static void dialog(Region content) { + decorator.showDialog(content); } public static void dialog(String text) { @@ -140,31 +134,33 @@ public final class Controllers { } public static void dialog(String text, String title, int type, Runnable onAccept) { - dialog(new MessageDialogPane(text, title, decorator.getDialog(), type, onAccept)); + dialog(new MessageDialogPane(text, title, Controllers::closeDialog, type, onAccept)); } public static void confirmDialog(String text, String title, Runnable onAccept, Runnable onCancel) { - dialog(new MessageDialogPane(text, title, decorator.getDialog(), onAccept, onCancel)); + dialog(new MessageDialogPane(text, title, Controllers::closeDialog, onAccept, onCancel)); } public static void inputDialog(String text, Consumer onResult) { - dialog(new InputDialogPane(text, decorator.getDialog(), onResult)); + dialog(new InputDialogPane(text, Controllers::closeDialog, onResult)); } - public static void taskDialog(TaskExecutor executor, String title, String subtitle) { - taskDialog(executor, title, subtitle, null); + public static Region taskDialog(TaskExecutor executor, String title, String subtitle) { + return taskDialog(executor, title, subtitle, null); } - public static void taskDialog(TaskExecutor executor, String title, String subtitle, Runnable onCancel) { + public static Region taskDialog(TaskExecutor executor, String title, String subtitle, Consumer onCancel) { TaskExecutorDialogPane pane = new TaskExecutorDialogPane(onCancel); pane.setTitle(title); pane.setSubtitle(subtitle); pane.setExecutor(executor); dialog(pane); + return pane; } - public static void closeDialog() { - decorator.getDialog().close(); + public static void closeDialog(Region content) { + + decorator.closeDialog(content); } public static void navigate(Node node) { 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 863fb4c3d..c5a4c11d6 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Decorator.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Decorator.java @@ -17,7 +17,6 @@ */ package org.jackhuang.hmcl.ui; -import com.jfoenix.concurrency.JFXUtilities; import com.jfoenix.controls.JFXButton; import com.jfoenix.controls.JFXDialog; import com.jfoenix.controls.JFXDrawer; @@ -167,17 +166,7 @@ public final class Decorator extends StackPane implements TaskExecutorDialogWiza btnMax.fire(); }); - dialog = new JFXDialog() { - @Override - public void close() { - dialogPane.pop(); - if (dialogPane.getChildren().isEmpty()) - Platform.runLater(() -> { - if (dialogPane.getChildren().isEmpty()) - super.close(); - }); - } - }; + dialog = new JFXDialog(); dialog.setOverlayClose(false); drawerWrapper.getChildren().add(0, dialog); dialog.setDialogContainer(drawerWrapper); @@ -525,6 +514,8 @@ public final class Decorator extends StackPane implements TaskExecutorDialogWiza } public void showPage(Node content) { + FXUtils.checkFxUserThread(); + contentPlaceHolder.getStyleClass().removeAll("gray-background", "white-background"); if (content != null) contentPlaceHolder.getStyleClass().add("gray-background"); @@ -545,11 +536,23 @@ public final class Decorator extends StackPane implements TaskExecutorDialogWiza } } - public JFXDialog showDialog(Node node) { + public void showDialog(Node node) { + FXUtils.checkFxUserThread(); + if (dialogPane.isEmpty()) dialog.show(); dialogPane.push(node); - return dialog; + } + + public void closeDialog(Node node) { + FXUtils.checkFxUserThread(); + + dialogPane.pop(node); + if (dialogPane.getChildren().isEmpty()) + Platform.runLater(() -> { + if (dialogPane.getChildren().isEmpty()) + dialog.close(); + }); } public void startWizard(WizardProvider wizardProvider) { @@ -557,6 +560,8 @@ public final class Decorator extends StackPane implements TaskExecutorDialogWiza } public void startWizard(WizardProvider wizardProvider, String category) { + FXUtils.checkFxUserThread(); + this.category = category; wizardController.setProvider(wizardProvider); wizardController.onStart(); @@ -638,10 +643,6 @@ public final class Decorator extends StackPane implements TaskExecutorDialogWiza return wizardController; } - public JFXDialog getDialog() { - return dialog; - } - public AdvancedListBox getLeftPane() { return leftPane; } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/DialogController.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/DialogController.java index f3d7c48e2..16f9476dd 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/DialogController.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/DialogController.java @@ -34,11 +34,11 @@ public final class DialogController { CountDownLatch latch = new CountDownLatch(1); AtomicReference res = new AtomicReference<>(null); JFXUtilities.runInFX(() -> { - AccountLoginPane pane = new AccountLoginPane(account, it -> { + AccountLoginPane pane = new AccountLoginPane(account, Controllers::closeDialog, it -> { res.set(it); latch.countDown(); }, latch::countDown); - pane.setDialog(Controllers.dialog(pane)); + Controllers.dialog(pane); }); latch.await(); return Optional.ofNullable(res.get()).orElseThrow(SilentException::new); 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 d62349ce6..ed8998a08 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java @@ -62,6 +62,13 @@ public final class FXUtils { private FXUtils() { } + public static void checkFxUserThread() { + if (!Platform.isFxApplicationThread()) { + throw new IllegalStateException("Not on FX application thread; currentThread = " + + Thread.currentThread().getName()); + } + } + public static void onChange(ObservableValue value, Consumer consumer) { value.addListener((a, b, c) -> consumer.accept(c)); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/LeftPaneController.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/LeftPaneController.java index 6b845f048..b10117b59 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/LeftPaneController.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/LeftPaneController.java @@ -25,6 +25,7 @@ import javafx.scene.Node; import javafx.scene.control.Tooltip; import javafx.scene.image.Image; import javafx.scene.input.MouseButton; +import javafx.scene.layout.Region; import javafx.scene.layout.VBox; import javafx.scene.paint.Color; import org.jackhuang.hmcl.Launcher; @@ -41,6 +42,7 @@ import org.jackhuang.hmcl.mod.UnsupportedModpackException; import org.jackhuang.hmcl.setting.*; import org.jackhuang.hmcl.task.Schedulers; import org.jackhuang.hmcl.task.Task; +import org.jackhuang.hmcl.task.TaskExecutor; import org.jackhuang.hmcl.ui.construct.AdvancedListBox; import org.jackhuang.hmcl.ui.construct.ClassTitle; import org.jackhuang.hmcl.ui.construct.IconedItem; @@ -50,6 +52,7 @@ import org.jackhuang.hmcl.util.Lang; import java.io.File; import java.util.LinkedList; import java.util.Objects; +import java.util.concurrent.atomic.AtomicReference; public final class LeftPaneController { private final AdvancedListBox leftPane; @@ -204,13 +207,15 @@ public final class LeftPaneController { File modpackFile = new File("modpack.zip").getAbsoluteFile(); if (modpackFile.exists()) { try { + AtomicReference region = new AtomicReference<>(); Modpack modpack = ModpackHelper.readModpackManifest(modpackFile); - Controllers.taskDialog(ModpackHelper.getInstallTask(repository.getProfile(), modpackFile, modpack.getName(), modpack) - .with(Task.of(Schedulers.javafx(), () -> { - Controllers.closeDialog(); - checkAccount(); - })).executor(true), - Launcher.i18n("modpack.installing"), "", null); + TaskExecutor executor = ModpackHelper.getInstallTask(repository.getProfile(), modpackFile, modpack.getName(), modpack) + .with(Task.of(Schedulers.javafx(), () -> { + Controllers.closeDialog(region.get()); + checkAccount(); + })).executor(); + region.set(Controllers.taskDialog(executor, Launcher.i18n("modpack.installing"), "")); + executor.start(); flag = false; } catch (UnsupportedModpackException ignore) { } 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 ded699c64..b5a1ccfd5 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPage.java @@ -25,6 +25,7 @@ import javafx.fxml.FXML; import javafx.scene.Node; import javafx.scene.image.Image; import javafx.scene.input.MouseButton; +import javafx.scene.layout.Region; import javafx.scene.layout.StackPane; import javafx.stage.FileChooser; import org.jackhuang.hmcl.Launcher; @@ -53,6 +54,7 @@ import java.io.IOException; import java.util.Collections; import java.util.LinkedList; import java.util.List; +import java.util.concurrent.atomic.AtomicReference; import static org.jackhuang.hmcl.util.StringUtils.removePrefix; import static org.jackhuang.hmcl.util.StringUtils.removeSuffix; @@ -155,18 +157,20 @@ public final class MainPage extends StackPane implements DecoratorPage { chooser.getExtensionFilters().add(new FileChooser.ExtensionFilter(Launcher.i18n("modpack"), "*.zip")); File selectedFile = chooser.showOpenDialog(Controllers.getStage()); if (selectedFile != null) { + AtomicReference region = new AtomicReference<>(); try { TaskExecutor executor = ModpackHelper.getUpdateTask(profile, selectedFile, id, ModpackHelper.readModpackConfiguration(repository.getModpackConfiguration(id))) - .then(Task.of(Schedulers.javafx(), Controllers::closeDialog)).executor(true); - Controllers.taskDialog(executor, Launcher.i18n("modpack.update"), "", null); + .then(Task.of(Schedulers.javafx(), () -> Controllers.closeDialog(region.get()))).executor(); + region.set(Controllers.taskDialog(executor, Launcher.i18n("modpack.update"), "")); + executor.start(); } catch (UnsupportedModpackException e) { - Controllers.closeDialog(); + Controllers.closeDialog(region.get()); Controllers.dialog(Launcher.i18n("modpack.unsupported"), Launcher.i18n("message.error"), MessageBox.ERROR_MESSAGE); } catch (MismatchedModpackTypeException e) { - Controllers.closeDialog(); + Controllers.closeDialog(region.get()); Controllers.dialog(Launcher.i18n("modpack.mismatched_type"), Launcher.i18n("message.error"), MessageBox.ERROR_MESSAGE); } catch (IOException e) { - Controllers.closeDialog(); + Controllers.closeDialog(region.get()); Controllers.dialog(Launcher.i18n("modpack.invalid"), Launcher.i18n("message.error"), MessageBox.ERROR_MESSAGE); } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/InputDialogPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/InputDialogPane.java index 75512829b..6488ad18c 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/InputDialogPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/InputDialogPane.java @@ -22,14 +22,13 @@ import com.jfoenix.controls.JFXDialog; import com.jfoenix.controls.JFXTextField; import javafx.fxml.FXML; import javafx.scene.control.Label; +import javafx.scene.layout.Region; import javafx.scene.layout.StackPane; import org.jackhuang.hmcl.ui.FXUtils; import java.util.function.Consumer; public class InputDialogPane extends StackPane { - private final String text; - private final JFXDialog dialog; @FXML private JFXButton acceptButton; @@ -40,16 +39,13 @@ public class InputDialogPane extends StackPane { @FXML private Label content; - public InputDialogPane(String text, JFXDialog dialog, Consumer onResult) { - this.text = text; - this.dialog = dialog; - + public InputDialogPane(String text, Consumer closeConsumer, Consumer onResult) { FXUtils.loadFXML(this, "/assets/fxml/input-dialog.fxml"); content.setText(text); - cancelButton.setOnMouseClicked(e -> dialog.close()); + cancelButton.setOnMouseClicked(e -> closeConsumer.accept(this)); acceptButton.setOnMouseClicked(e -> { onResult.accept(textField.getText()); - dialog.close(); + closeConsumer.accept(this); }); } } 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 ca9d30dec..df97902ef 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 @@ -22,6 +22,7 @@ import com.jfoenix.controls.JFXDialog; import javafx.fxml.FXML; import javafx.scene.control.Label; import javafx.scene.layout.HBox; +import javafx.scene.layout.Region; import javafx.scene.layout.StackPane; import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.setting.Theme; @@ -29,6 +30,7 @@ import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.ui.SVG; import java.util.Optional; +import java.util.function.Consumer; public final class MessageDialogPane extends StackPane { private boolean closingDialog = true; @@ -46,7 +48,7 @@ public final class MessageDialogPane extends StackPane { @FXML private HBox actions; - public MessageDialogPane(String text, String title, JFXDialog dialog, int type, Runnable onAccept) { + public MessageDialogPane(String text, String title, Consumer closeConsumer, int type, Runnable onAccept) { FXUtils.loadFXML(this, "/assets/fxml/message-dialog.fxml"); if (title != null) @@ -54,8 +56,7 @@ public final class MessageDialogPane extends StackPane { content.setText(text); acceptButton.setOnMouseClicked(e -> { - if (closingDialog) - dialog.close(); + closeConsumer.accept(MessageDialogPane.this); Optional.ofNullable(onAccept).ifPresent(Runnable::run); }); @@ -82,13 +83,12 @@ public final class MessageDialogPane extends StackPane { } } - public MessageDialogPane(String text, String title, JFXDialog dialog, Runnable onAccept, Runnable onCancel) { - this(text, title, dialog, MessageBox.QUESTION_MESSAGE, onAccept); + public MessageDialogPane(String text, String title, Consumer closeConsumer, Runnable onAccept, Runnable onCancel) { + this(text, title, closeConsumer, MessageBox.QUESTION_MESSAGE, onAccept); cancelButton.setVisible(true); cancelButton.setOnMouseClicked(e -> { - if (closingDialog) - dialog.close(); + closeConsumer.accept(MessageDialogPane.this); Optional.ofNullable(onCancel).ifPresent(Runnable::run); }); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/StackContainerPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/StackContainerPane.java index 3253453a7..9454f1cc1 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/StackContainerPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/StackContainerPane.java @@ -19,6 +19,7 @@ package org.jackhuang.hmcl.ui.construct; import javafx.scene.Node; import javafx.scene.layout.StackPane; +import org.jackhuang.hmcl.util.Logging; import java.util.Stack; @@ -26,17 +27,20 @@ public class StackContainerPane extends StackPane { private final Stack stack = new Stack<>(); public void push(Node node) { - if (!node.getProperties().containsKey("controllers")) - stack.push(node); + stack.push(node); getChildren().setAll(node); + + Logging.LOG.info(this + " " + stack); } - public void pop() { - stack.pop(); + public void pop(Node node) { + boolean flag = stack.remove(node); if (stack.isEmpty()) getChildren().setAll(); else getChildren().setAll(stack.peek()); + + Logging.LOG.info(this + " " + stack + ", removed: " + flag + ", object: " + node); } public boolean isEmpty() { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskExecutorDialogPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskExecutorDialogPane.java index 0038117a9..9b60e256a 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskExecutorDialogPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskExecutorDialogPane.java @@ -23,15 +23,17 @@ import com.jfoenix.controls.JFXProgressBar; import javafx.beans.property.StringProperty; import javafx.fxml.FXML; import javafx.scene.control.Label; +import javafx.scene.layout.Region; import javafx.scene.layout.StackPane; import org.jackhuang.hmcl.task.TaskExecutor; import org.jackhuang.hmcl.ui.FXUtils; import java.util.Optional; +import java.util.function.Consumer; public class TaskExecutorDialogPane extends StackPane { private TaskExecutor executor; - private Runnable onCancel; + private Consumer onCancel; @FXML private JFXProgressBar progressBar; @@ -44,14 +46,14 @@ public class TaskExecutorDialogPane extends StackPane { @FXML private TaskListPane taskListPane; - public TaskExecutorDialogPane(Runnable cancel) { + public TaskExecutorDialogPane(Consumer cancel) { FXUtils.loadFXML(this, "/assets/fxml/task-dialog.fxml"); setCancel(cancel); btnCancel.setOnMouseClicked(e -> { Optional.ofNullable(executor).ifPresent(TaskExecutor::cancel); - onCancel.run(); + onCancel.accept(this); }); } @@ -93,7 +95,7 @@ public class TaskExecutorDialogPane extends StackPane { progressBar.setProgress(progress); } - public void setCancel(Runnable onCancel) { + public void setCancel(Consumer onCancel) { this.onCancel = onCancel; JFXUtilities.runInFX(() -> btnCancel.setDisable(onCancel == null)); 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 index 28f88e87a..0b69e4f95 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskExecutorDialogWizardDisplayer.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskExecutorDialogWizardDisplayer.java @@ -33,8 +33,8 @@ public interface TaskExecutorDialogWizardDisplayer extends AbstractWizardDisplay @Override default void handleTask(Map settings, Task task) { - TaskExecutorDialogPane pane = new TaskExecutorDialogPane(() -> { - Controllers.closeDialog(); + TaskExecutorDialogPane pane = new TaskExecutorDialogPane(it -> { + Controllers.closeDialog(it); Controllers.navigate(null); }); @@ -61,7 +61,7 @@ public interface TaskExecutorDialogWizardDisplayer extends AbstractWizardDisplay @Override public void onStop(boolean success, TaskExecutor executor) { JFXUtilities.runInFX(() -> { - Controllers.closeDialog(); + Controllers.closeDialog(pane); if (success) { if (settings.containsKey("success_message") && settings.get("success_message") instanceof String) Controllers.dialog((String) settings.get("success_message"), null, MessageBox.FINE_MESSAGE, () -> Controllers.navigate(null)); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/AppDataUpgrader.java b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/AppDataUpgrader.java index 5ac4d50d1..3bf965e34 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/AppDataUpgrader.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/AppDataUpgrader.java @@ -20,6 +20,7 @@ package org.jackhuang.hmcl.upgrade; import com.google.gson.JsonParseException; import com.google.gson.reflect.TypeToken; import com.jfoenix.concurrency.JFXUtilities; +import javafx.scene.layout.Region; import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.task.FileDownloadTask; import org.jackhuang.hmcl.task.Schedulers; @@ -38,6 +39,7 @@ import java.security.AccessController; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; import java.util.*; +import java.util.concurrent.atomic.AtomicReference; import java.util.jar.JarFile; import java.util.jar.JarOutputStream; import java.util.jar.Pack200; @@ -116,13 +118,16 @@ public class AppDataUpgrader extends IUpgrader { String hash = null; if (map.containsKey("jarsha1")) hash = map.get("jarsha1"); - Controllers.dialog(Launcher.i18n("message.downloading")); - if (new AppDataUpgraderJarTask(NetworkUtils.toURL(map.get("jar")), version.toString(), hash).test()) { + Task task = new AppDataUpgraderJarTask(NetworkUtils.toURL(map.get("jar")), version.toString(), hash); + TaskExecutor executor = task.executor(); + AtomicReference region = new AtomicReference<>(); + JFXUtilities.runInFX(() -> region.set(Controllers.taskDialog(executor, Launcher.i18n("message.downloading"), "", null))); + if (executor.test()) { new ProcessBuilder(JavaVersion.fromCurrentEnvironment().getBinary().getAbsolutePath(), "-jar", AppDataUpgraderJarTask.getSelf(version.toString()).getAbsolutePath()) .directory(new File("").getAbsoluteFile()).start(); System.exit(0); } - Controllers.closeDialog(); + JFXUtilities.runInFX(() -> Controllers.closeDialog(region.get())); } catch (IOException ex) { Logging.LOG.log(Level.SEVERE, "Failed to create upgrader", ex); } @@ -133,13 +138,14 @@ public class AppDataUpgrader extends IUpgrader { hash = map.get("packsha1"); Task task = new AppDataUpgraderPackGzTask(NetworkUtils.toURL(map.get("pack")), version.toString(), hash); TaskExecutor executor = task.executor(); - JFXUtilities.runInFX(() -> Controllers.taskDialog(executor, Launcher.i18n("message.downloading"), "", null)); + AtomicReference region = new AtomicReference<>(); + JFXUtilities.runInFX(() -> region.set(Controllers.taskDialog(executor, Launcher.i18n("message.downloading"), "", null))); if (executor.test()) { new ProcessBuilder(JavaVersion.fromCurrentEnvironment().getBinary().getAbsolutePath(), "-jar", AppDataUpgraderPackGzTask.getSelf(version.toString()).getAbsolutePath()) .directory(new File("").getAbsoluteFile()).start(); System.exit(0); } - JFXUtilities.runInFX(Controllers::closeDialog); + JFXUtilities.runInFX(() -> Controllers.closeDialog(region.get())); } catch (IOException ex) { Logging.LOG.log(Level.SEVERE, "Failed to create upgrader", ex); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/NewFileUpgrader.java b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/NewFileUpgrader.java index 5437a0c01..ebc6b78da 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/NewFileUpgrader.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/NewFileUpgrader.java @@ -17,8 +17,12 @@ */ package org.jackhuang.hmcl.upgrade; +import com.jfoenix.concurrency.JFXUtilities; +import javafx.scene.layout.Region; import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.task.FileDownloadTask; +import org.jackhuang.hmcl.task.Task; +import org.jackhuang.hmcl.task.TaskExecutor; import org.jackhuang.hmcl.ui.Controllers; import org.jackhuang.hmcl.util.Charsets; import org.jackhuang.hmcl.util.Logging; @@ -28,6 +32,7 @@ import java.io.File; import java.io.IOException; import java.net.URL; import java.util.List; +import java.util.concurrent.atomic.AtomicReference; import java.util.logging.Level; /** @@ -52,7 +57,11 @@ public class NewFileUpgrader extends IUpgrader { if (url == null) return; File newf = new File(url.getFile()); Controllers.dialog(Launcher.i18n("message.downloading")); - if (new FileDownloadTask(url, newf).test()) { + Task task = new FileDownloadTask(url, newf); + TaskExecutor executor = task.executor(); + AtomicReference region = new AtomicReference<>(); + JFXUtilities.runInFX(() -> region.set(Controllers.taskDialog(executor, Launcher.i18n("message.downloading"), "", null))); + if (executor.test()) { try { new ProcessBuilder(newf.getCanonicalPath(), "--removeOldLauncher", getRealPath()) .directory(new File("").getAbsoluteFile()) @@ -62,7 +71,7 @@ public class NewFileUpgrader extends IUpgrader { } System.exit(0); } - Controllers.closeDialog(); + JFXUtilities.runInFX(() -> Controllers.closeDialog(region.get())); } private static String getRealPath() {