Try to fix empty stack of StackContainerPane

This commit is contained in:
huangyuhui 2018-03-09 16:24:02 +08:00
parent 44aff94937
commit dbfcf1facc
16 changed files with 146 additions and 112 deletions

View File

@ -19,6 +19,7 @@ package org.jackhuang.hmcl.game;
import com.jfoenix.concurrency.JFXUtilities; import com.jfoenix.concurrency.JFXUtilities;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.scene.layout.Region;
import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.Launcher;
import org.jackhuang.hmcl.auth.Account; import org.jackhuang.hmcl.auth.Account;
import org.jackhuang.hmcl.auth.AuthInfo; import org.jackhuang.hmcl.auth.AuthInfo;
@ -46,13 +47,14 @@ import java.util.*;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
public final class LauncherHelper { public final class LauncherHelper {
public static final LauncherHelper INSTANCE = new LauncherHelper(); public static final LauncherHelper INSTANCE = new LauncherHelper();
private LauncherHelper(){} private LauncherHelper(){}
public static final Queue<ManagedProcess> PROCESSES = new ConcurrentLinkedQueue<>(); public static final Queue<ManagedProcess> 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) { public void launch(Profile profile, Account account, String selectedVersion, File scriptFile) {
if (account == null) if (account == null)
@ -65,7 +67,10 @@ public final class LauncherHelper {
Platform.runLater(() -> { Platform.runLater(() -> {
try { 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) { } catch (InterruptedException ignore) {
} }
}); });
@ -78,8 +83,7 @@ public final class LauncherHelper {
VersionSetting setting = profile.getVersionSetting(selectedVersion); VersionSetting setting = profile.getVersionSetting(selectedVersion);
Optional<String> gameVersion = GameVersion.minecraftVersion(repository.getVersionJar(version)); Optional<String> gameVersion = GameVersion.minecraftVersion(repository.getVersionJar(version));
TaskExecutor executor = Task.of(Schedulers.javafx(), () -> Controllers.dialog(launchingStepsPane)) TaskExecutor executor = Task.of(Schedulers.javafx(), () -> emitStatus(LoadingState.DEPENDENCIES))
.then(Task.of(Schedulers.javafx(), () -> emitStatus(LoadingState.DEPENDENCIES)))
.then(variables -> { .then(variables -> {
if (setting.isNotCheckGame()) if (setting.isNotCheckGame())
return null; return null;
@ -127,13 +131,13 @@ public final class LauncherHelper {
if (setting.getLauncherVisibility() == LauncherVisibility.CLOSE) if (setting.getLauncherVisibility() == LauncherVisibility.CLOSE)
Launcher.stopApplication(); Launcher.stopApplication();
else else
launchingStepsPane.setCancel(() -> { launchingStepsPane.setCancel(it -> {
process.stop(); process.stop();
Controllers.closeDialog(); Controllers.closeDialog(it);
}); });
} else } else
Platform.runLater(() -> { Platform.runLater(() -> {
Controllers.closeDialog(); Controllers.closeDialog(launchingStepsPane);
Controllers.dialog(Launcher.i18n("version.launch_script.success", scriptFile.getAbsolutePath())); 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) { public void onStop(boolean success, TaskExecutor executor) {
if (!success) { if (!success) {
Platform.runLater(() -> { Platform.runLater(() -> {
Controllers.closeDialog(); Controllers.closeDialog(launchingStepsPane);
if (executor.getLastException() != null) if (executor.getLastException() != null)
Controllers.dialog(I18nException.getStackTrace(executor.getLastException()), Controllers.dialog(I18nException.getStackTrace(executor.getLastException()),
scriptFile == null ? Launcher.i18n("launch.failed") : Launcher.i18n("version.launch_script.failed"), scriptFile == null ? Launcher.i18n("launch.failed") : Launcher.i18n("version.launch_script.failed"),
MessageBox.ERROR_MESSAGE, Controllers::closeDialog); MessageBox.ERROR_MESSAGE);
}); });
} }
launchingStepsPane.setExecutor(null); 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 { 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")); VersionNumber gameVersion = VersionNumber.asVersion(GameVersion.minecraftVersion(profile.getRepository().getVersionJar(version)).orElse("Unknown"));
JavaVersion java = setting.getJavaVersion(); 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")) { 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); Controllers.dialog(Launcher.i18n("launch.advice.java9"), Launcher.i18n("message.error"), MessageBox.ERROR_MESSAGE, null);
suggest = false;
flag = true; flag = true;
} }
@ -207,10 +210,7 @@ public final class LauncherHelper {
flag = true; flag = true;
} }
if (flag) { if (!flag)
if (suggest && Controllers.getDialogContent() instanceof MessageDialogPane)
((MessageDialogPane) Controllers.getDialogContent()).disableClosingDialog();
} else
onAccept.run(); onAccept.run();
} }
@ -221,7 +221,7 @@ public final class LauncherHelper {
public void emitStatus(LoadingState state) { public void emitStatus(LoadingState state) {
if (state == LoadingState.DONE) if (state == LoadingState.DONE)
Controllers.closeDialog(); Controllers.closeDialog(launchingStepsPane);
launchingStepsPane.setTitle(state.getLocalizedMessage()); launchingStepsPane.setTitle(state.getLocalizedMessage());
launchingStepsPane.setSubtitle((state.ordinal() + 1) + " / " + LoadingState.values().length); launchingStepsPane.setSubtitle((state.ordinal() + 1) + " / " + LoadingState.values().length);
@ -359,7 +359,9 @@ public final class LauncherHelper {
// Never come to here. // Never come to here.
break; break;
case KEEP: case KEEP:
// No operations here Platform.runLater(() -> {
emitStatus(LoadingState.DONE);
});
break; break;
case HIDE: case HIDE:
Platform.runLater(() -> { Platform.runLater(() -> {

View File

@ -22,12 +22,15 @@ import com.jfoenix.controls.JFXPasswordField;
import com.jfoenix.controls.JFXProgressBar; import com.jfoenix.controls.JFXProgressBar;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.scene.control.Label; import javafx.scene.control.Label;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane; import javafx.scene.layout.StackPane;
import org.jackhuang.hmcl.auth.Account; import org.jackhuang.hmcl.auth.Account;
import org.jackhuang.hmcl.auth.AuthInfo; import org.jackhuang.hmcl.auth.AuthInfo;
import org.jackhuang.hmcl.auth.NoSelectedCharacterException; import org.jackhuang.hmcl.auth.NoSelectedCharacterException;
import org.jackhuang.hmcl.task.Schedulers; import org.jackhuang.hmcl.task.Schedulers;
import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.task.Task;
import org.jackhuang.hmcl.ui.AddAccountPane;
import org.jackhuang.hmcl.ui.FXUtils;
import java.util.function.Consumer; import java.util.function.Consumer;
@ -35,18 +38,19 @@ public class AccountLoginPane extends StackPane {
private final Account oldAccount; private final Account oldAccount;
private final Consumer<AuthInfo> success; private final Consumer<AuthInfo> success;
private final Runnable failed; private final Runnable failed;
private final Consumer<Region> closeConsumer;
@FXML @FXML
private Label lblUsername; private Label lblUsername;
@FXML private JFXPasswordField txtPassword; @FXML private JFXPasswordField txtPassword;
@FXML private Label lblCreationWarning; @FXML private Label lblCreationWarning;
@FXML private JFXProgressBar progressBar; @FXML private JFXProgressBar progressBar;
private JFXDialog dialog;
public AccountLoginPane(Account oldAccount, Consumer<AuthInfo> success, Runnable failed) { public AccountLoginPane(Account oldAccount, Consumer<Region> closeConsumer, Consumer<AuthInfo> success, Runnable failed) {
this.oldAccount = oldAccount; this.oldAccount = oldAccount;
this.success = success; this.success = success;
this.failed = failed; this.failed = failed;
this.closeConsumer = closeConsumer;
FXUtils.loadFXML(this, "/assets/fxml/account-login.fxml"); FXUtils.loadFXML(this, "/assets/fxml/account-login.fxml");
@ -69,9 +73,9 @@ public class AccountLoginPane extends StackPane {
Object account = variable.get("login"); Object account = variable.get("login");
if (account instanceof AuthInfo) { if (account instanceof AuthInfo) {
success.accept(((AuthInfo) account)); success.accept(((AuthInfo) account));
dialog.close(); closeConsumer.accept(this);
} else if (account instanceof NoSelectedCharacterException) { } else if (account instanceof NoSelectedCharacterException) {
dialog.close(); closeConsumer.accept(this);
} else if (account instanceof Exception) { } else if (account instanceof Exception) {
lblCreationWarning.setText(AddAccountPane.accountException((Exception) account)); lblCreationWarning.setText(AddAccountPane.accountException((Exception) account));
} }
@ -83,10 +87,6 @@ public class AccountLoginPane extends StackPane {
@FXML @FXML
private void onCancel() { private void onCancel() {
failed.run(); failed.run();
dialog.close(); closeConsumer.accept(this);
}
public void setDialog(JFXDialog dialog) {
this.dialog = dialog;
} }
} }

View File

@ -28,6 +28,7 @@ import javafx.scene.image.Image;
import javafx.scene.image.ImageView; import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane; import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox; import javafx.scene.layout.HBox;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane; import javafx.scene.layout.StackPane;
import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.Launcher;
import org.jackhuang.hmcl.auth.*; import org.jackhuang.hmcl.auth.*;
@ -49,6 +50,7 @@ import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.function.Consumer;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
@ -65,9 +67,9 @@ public class AddAccountPane extends StackPane {
@FXML private Label lblAddInjectorServer; @FXML private Label lblAddInjectorServer;
@FXML private Hyperlink linkAddInjectorServer; @FXML private Hyperlink linkAddInjectorServer;
@FXML private JFXDialogLayout layout; @FXML private JFXDialogLayout layout;
private final Runnable finalization; private final Consumer<Region> finalization;
public AddAccountPane(Runnable finalization) { public AddAccountPane(Consumer<Region> finalization) {
this.finalization = finalization; this.finalization = finalization;
FXUtils.loadFXML(this, "/assets/fxml/account-add.fxml"); FXUtils.loadFXML(this, "/assets/fxml/account-add.fxml");
@ -133,10 +135,10 @@ public class AddAccountPane extends StackPane {
}).finalized(Schedulers.javafx(), variables -> { }).finalized(Schedulers.javafx(), variables -> {
Settings.INSTANCE.addAccount(variables.get("create_account")); Settings.INSTANCE.addAccount(variables.get("create_account"));
progressBar.setVisible(false); progressBar.setVisible(false);
finalization.run(); finalization.accept(this);
}, exception -> { }, exception -> {
if (exception instanceof NoSelectedCharacterException) { if (exception instanceof NoSelectedCharacterException) {
finalization.run(); finalization.accept(this);
} else { } else {
lblCreationWarning.setText(accountException(exception)); lblCreationWarning.setText(accountException(exception));
} }
@ -146,12 +148,12 @@ public class AddAccountPane extends StackPane {
@FXML @FXML
private void onCreationCancel() { private void onCreationCancel() {
finalization.run(); finalization.accept(this);
} }
@FXML @FXML
private void onAddInjecterServer() { private void onAddInjecterServer() {
finalization.run(); finalization.accept(this);
Controllers.navigate(Controllers.getServersPage()); Controllers.navigate(Controllers.getServersPage());
} }

View File

@ -117,14 +117,8 @@ public final class Controllers {
stage.setTitle(Launcher.TITLE); stage.setTitle(Launcher.TITLE);
} }
public static Region getDialogContent() { public static void dialog(Region content) {
return decorator.getDialog().getContent(); decorator.showDialog(content);
}
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(String text) { 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) { 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) { 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<String> onResult) { public static void inputDialog(String text, Consumer<String> 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) { public static Region taskDialog(TaskExecutor executor, String title, String subtitle) {
taskDialog(executor, title, subtitle, null); 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<Region> onCancel) {
TaskExecutorDialogPane pane = new TaskExecutorDialogPane(onCancel); TaskExecutorDialogPane pane = new TaskExecutorDialogPane(onCancel);
pane.setTitle(title); pane.setTitle(title);
pane.setSubtitle(subtitle); pane.setSubtitle(subtitle);
pane.setExecutor(executor); pane.setExecutor(executor);
dialog(pane); dialog(pane);
return pane;
} }
public static void closeDialog() { public static void closeDialog(Region content) {
decorator.getDialog().close();
decorator.closeDialog(content);
} }
public static void navigate(Node node) { public static void navigate(Node node) {

View File

@ -17,7 +17,6 @@
*/ */
package org.jackhuang.hmcl.ui; package org.jackhuang.hmcl.ui;
import com.jfoenix.concurrency.JFXUtilities;
import com.jfoenix.controls.JFXButton; import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXDialog; import com.jfoenix.controls.JFXDialog;
import com.jfoenix.controls.JFXDrawer; import com.jfoenix.controls.JFXDrawer;
@ -167,17 +166,7 @@ public final class Decorator extends StackPane implements TaskExecutorDialogWiza
btnMax.fire(); btnMax.fire();
}); });
dialog = new JFXDialog() { dialog = new JFXDialog();
@Override
public void close() {
dialogPane.pop();
if (dialogPane.getChildren().isEmpty())
Platform.runLater(() -> {
if (dialogPane.getChildren().isEmpty())
super.close();
});
}
};
dialog.setOverlayClose(false); dialog.setOverlayClose(false);
drawerWrapper.getChildren().add(0, dialog); drawerWrapper.getChildren().add(0, dialog);
dialog.setDialogContainer(drawerWrapper); dialog.setDialogContainer(drawerWrapper);
@ -525,6 +514,8 @@ public final class Decorator extends StackPane implements TaskExecutorDialogWiza
} }
public void showPage(Node content) { public void showPage(Node content) {
FXUtils.checkFxUserThread();
contentPlaceHolder.getStyleClass().removeAll("gray-background", "white-background"); contentPlaceHolder.getStyleClass().removeAll("gray-background", "white-background");
if (content != null) if (content != null)
contentPlaceHolder.getStyleClass().add("gray-background"); 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()) if (dialogPane.isEmpty())
dialog.show(); dialog.show();
dialogPane.push(node); 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) { public void startWizard(WizardProvider wizardProvider) {
@ -557,6 +560,8 @@ public final class Decorator extends StackPane implements TaskExecutorDialogWiza
} }
public void startWizard(WizardProvider wizardProvider, String category) { public void startWizard(WizardProvider wizardProvider, String category) {
FXUtils.checkFxUserThread();
this.category = category; this.category = category;
wizardController.setProvider(wizardProvider); wizardController.setProvider(wizardProvider);
wizardController.onStart(); wizardController.onStart();
@ -638,10 +643,6 @@ public final class Decorator extends StackPane implements TaskExecutorDialogWiza
return wizardController; return wizardController;
} }
public JFXDialog getDialog() {
return dialog;
}
public AdvancedListBox getLeftPane() { public AdvancedListBox getLeftPane() {
return leftPane; return leftPane;
} }

View File

@ -34,11 +34,11 @@ public final class DialogController {
CountDownLatch latch = new CountDownLatch(1); CountDownLatch latch = new CountDownLatch(1);
AtomicReference<AuthInfo> res = new AtomicReference<>(null); AtomicReference<AuthInfo> res = new AtomicReference<>(null);
JFXUtilities.runInFX(() -> { JFXUtilities.runInFX(() -> {
AccountLoginPane pane = new AccountLoginPane(account, it -> { AccountLoginPane pane = new AccountLoginPane(account, Controllers::closeDialog, it -> {
res.set(it); res.set(it);
latch.countDown(); latch.countDown();
}, latch::countDown); }, latch::countDown);
pane.setDialog(Controllers.dialog(pane)); Controllers.dialog(pane);
}); });
latch.await(); latch.await();
return Optional.ofNullable(res.get()).orElseThrow(SilentException::new); return Optional.ofNullable(res.get()).orElseThrow(SilentException::new);

View File

@ -62,6 +62,13 @@ public final class FXUtils {
private FXUtils() { private FXUtils() {
} }
public static void checkFxUserThread() {
if (!Platform.isFxApplicationThread()) {
throw new IllegalStateException("Not on FX application thread; currentThread = "
+ Thread.currentThread().getName());
}
}
public static <T> void onChange(ObservableValue<T> value, Consumer<T> consumer) { public static <T> void onChange(ObservableValue<T> value, Consumer<T> consumer) {
value.addListener((a, b, c) -> consumer.accept(c)); value.addListener((a, b, c) -> consumer.accept(c));
} }

View File

@ -25,6 +25,7 @@ import javafx.scene.Node;
import javafx.scene.control.Tooltip; import javafx.scene.control.Tooltip;
import javafx.scene.image.Image; import javafx.scene.image.Image;
import javafx.scene.input.MouseButton; import javafx.scene.input.MouseButton;
import javafx.scene.layout.Region;
import javafx.scene.layout.VBox; import javafx.scene.layout.VBox;
import javafx.scene.paint.Color; import javafx.scene.paint.Color;
import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.Launcher;
@ -41,6 +42,7 @@ import org.jackhuang.hmcl.mod.UnsupportedModpackException;
import org.jackhuang.hmcl.setting.*; import org.jackhuang.hmcl.setting.*;
import org.jackhuang.hmcl.task.Schedulers; import org.jackhuang.hmcl.task.Schedulers;
import org.jackhuang.hmcl.task.Task; 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.AdvancedListBox;
import org.jackhuang.hmcl.ui.construct.ClassTitle; import org.jackhuang.hmcl.ui.construct.ClassTitle;
import org.jackhuang.hmcl.ui.construct.IconedItem; import org.jackhuang.hmcl.ui.construct.IconedItem;
@ -50,6 +52,7 @@ import org.jackhuang.hmcl.util.Lang;
import java.io.File; import java.io.File;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.Objects; import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;
public final class LeftPaneController { public final class LeftPaneController {
private final AdvancedListBox leftPane; private final AdvancedListBox leftPane;
@ -204,13 +207,15 @@ public final class LeftPaneController {
File modpackFile = new File("modpack.zip").getAbsoluteFile(); File modpackFile = new File("modpack.zip").getAbsoluteFile();
if (modpackFile.exists()) { if (modpackFile.exists()) {
try { try {
AtomicReference<Region> region = new AtomicReference<>();
Modpack modpack = ModpackHelper.readModpackManifest(modpackFile); Modpack modpack = ModpackHelper.readModpackManifest(modpackFile);
Controllers.taskDialog(ModpackHelper.getInstallTask(repository.getProfile(), modpackFile, modpack.getName(), modpack) TaskExecutor executor = ModpackHelper.getInstallTask(repository.getProfile(), modpackFile, modpack.getName(), modpack)
.with(Task.of(Schedulers.javafx(), () -> { .with(Task.of(Schedulers.javafx(), () -> {
Controllers.closeDialog(); Controllers.closeDialog(region.get());
checkAccount(); checkAccount();
})).executor(true), })).executor();
Launcher.i18n("modpack.installing"), "", null); region.set(Controllers.taskDialog(executor, Launcher.i18n("modpack.installing"), ""));
executor.start();
flag = false; flag = false;
} catch (UnsupportedModpackException ignore) { } catch (UnsupportedModpackException ignore) {
} }

View File

@ -25,6 +25,7 @@ import javafx.fxml.FXML;
import javafx.scene.Node; import javafx.scene.Node;
import javafx.scene.image.Image; import javafx.scene.image.Image;
import javafx.scene.input.MouseButton; import javafx.scene.input.MouseButton;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane; import javafx.scene.layout.StackPane;
import javafx.stage.FileChooser; import javafx.stage.FileChooser;
import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.Launcher;
@ -53,6 +54,7 @@ import java.io.IOException;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; 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.removePrefix;
import static org.jackhuang.hmcl.util.StringUtils.removeSuffix; 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")); chooser.getExtensionFilters().add(new FileChooser.ExtensionFilter(Launcher.i18n("modpack"), "*.zip"));
File selectedFile = chooser.showOpenDialog(Controllers.getStage()); File selectedFile = chooser.showOpenDialog(Controllers.getStage());
if (selectedFile != null) { if (selectedFile != null) {
AtomicReference<Region> region = new AtomicReference<>();
try { try {
TaskExecutor executor = ModpackHelper.getUpdateTask(profile, selectedFile, id, ModpackHelper.readModpackConfiguration(repository.getModpackConfiguration(id))) TaskExecutor executor = ModpackHelper.getUpdateTask(profile, selectedFile, id, ModpackHelper.readModpackConfiguration(repository.getModpackConfiguration(id)))
.then(Task.of(Schedulers.javafx(), Controllers::closeDialog)).executor(true); .then(Task.of(Schedulers.javafx(), () -> Controllers.closeDialog(region.get()))).executor();
Controllers.taskDialog(executor, Launcher.i18n("modpack.update"), "", null); region.set(Controllers.taskDialog(executor, Launcher.i18n("modpack.update"), ""));
executor.start();
} catch (UnsupportedModpackException e) { } catch (UnsupportedModpackException e) {
Controllers.closeDialog(); Controllers.closeDialog(region.get());
Controllers.dialog(Launcher.i18n("modpack.unsupported"), Launcher.i18n("message.error"), MessageBox.ERROR_MESSAGE); Controllers.dialog(Launcher.i18n("modpack.unsupported"), Launcher.i18n("message.error"), MessageBox.ERROR_MESSAGE);
} catch (MismatchedModpackTypeException e) { } catch (MismatchedModpackTypeException e) {
Controllers.closeDialog(); Controllers.closeDialog(region.get());
Controllers.dialog(Launcher.i18n("modpack.mismatched_type"), Launcher.i18n("message.error"), MessageBox.ERROR_MESSAGE); Controllers.dialog(Launcher.i18n("modpack.mismatched_type"), Launcher.i18n("message.error"), MessageBox.ERROR_MESSAGE);
} catch (IOException e) { } catch (IOException e) {
Controllers.closeDialog(); Controllers.closeDialog(region.get());
Controllers.dialog(Launcher.i18n("modpack.invalid"), Launcher.i18n("message.error"), MessageBox.ERROR_MESSAGE); Controllers.dialog(Launcher.i18n("modpack.invalid"), Launcher.i18n("message.error"), MessageBox.ERROR_MESSAGE);
} }
} }

View File

@ -22,14 +22,13 @@ import com.jfoenix.controls.JFXDialog;
import com.jfoenix.controls.JFXTextField; import com.jfoenix.controls.JFXTextField;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.scene.control.Label; import javafx.scene.control.Label;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane; import javafx.scene.layout.StackPane;
import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.ui.FXUtils;
import java.util.function.Consumer; import java.util.function.Consumer;
public class InputDialogPane extends StackPane { public class InputDialogPane extends StackPane {
private final String text;
private final JFXDialog dialog;
@FXML @FXML
private JFXButton acceptButton; private JFXButton acceptButton;
@ -40,16 +39,13 @@ public class InputDialogPane extends StackPane {
@FXML @FXML
private Label content; private Label content;
public InputDialogPane(String text, JFXDialog dialog, Consumer<String> onResult) { public InputDialogPane(String text, Consumer<Region> closeConsumer, Consumer<String> onResult) {
this.text = text;
this.dialog = dialog;
FXUtils.loadFXML(this, "/assets/fxml/input-dialog.fxml"); FXUtils.loadFXML(this, "/assets/fxml/input-dialog.fxml");
content.setText(text); content.setText(text);
cancelButton.setOnMouseClicked(e -> dialog.close()); cancelButton.setOnMouseClicked(e -> closeConsumer.accept(this));
acceptButton.setOnMouseClicked(e -> { acceptButton.setOnMouseClicked(e -> {
onResult.accept(textField.getText()); onResult.accept(textField.getText());
dialog.close(); closeConsumer.accept(this);
}); });
} }
} }

View File

@ -22,6 +22,7 @@ import com.jfoenix.controls.JFXDialog;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.scene.control.Label; import javafx.scene.control.Label;
import javafx.scene.layout.HBox; import javafx.scene.layout.HBox;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane; import javafx.scene.layout.StackPane;
import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.Launcher;
import org.jackhuang.hmcl.setting.Theme; import org.jackhuang.hmcl.setting.Theme;
@ -29,6 +30,7 @@ import org.jackhuang.hmcl.ui.FXUtils;
import org.jackhuang.hmcl.ui.SVG; import org.jackhuang.hmcl.ui.SVG;
import java.util.Optional; import java.util.Optional;
import java.util.function.Consumer;
public final class MessageDialogPane extends StackPane { public final class MessageDialogPane extends StackPane {
private boolean closingDialog = true; private boolean closingDialog = true;
@ -46,7 +48,7 @@ public final class MessageDialogPane extends StackPane {
@FXML @FXML
private HBox actions; private HBox actions;
public MessageDialogPane(String text, String title, JFXDialog dialog, int type, Runnable onAccept) { public MessageDialogPane(String text, String title, Consumer<Region> closeConsumer, int type, Runnable onAccept) {
FXUtils.loadFXML(this, "/assets/fxml/message-dialog.fxml"); FXUtils.loadFXML(this, "/assets/fxml/message-dialog.fxml");
if (title != null) if (title != null)
@ -54,8 +56,7 @@ public final class MessageDialogPane extends StackPane {
content.setText(text); content.setText(text);
acceptButton.setOnMouseClicked(e -> { acceptButton.setOnMouseClicked(e -> {
if (closingDialog) closeConsumer.accept(MessageDialogPane.this);
dialog.close();
Optional.ofNullable(onAccept).ifPresent(Runnable::run); 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) { public MessageDialogPane(String text, String title, Consumer<Region> closeConsumer, Runnable onAccept, Runnable onCancel) {
this(text, title, dialog, MessageBox.QUESTION_MESSAGE, onAccept); this(text, title, closeConsumer, MessageBox.QUESTION_MESSAGE, onAccept);
cancelButton.setVisible(true); cancelButton.setVisible(true);
cancelButton.setOnMouseClicked(e -> { cancelButton.setOnMouseClicked(e -> {
if (closingDialog) closeConsumer.accept(MessageDialogPane.this);
dialog.close();
Optional.ofNullable(onCancel).ifPresent(Runnable::run); Optional.ofNullable(onCancel).ifPresent(Runnable::run);
}); });

View File

@ -19,6 +19,7 @@ package org.jackhuang.hmcl.ui.construct;
import javafx.scene.Node; import javafx.scene.Node;
import javafx.scene.layout.StackPane; import javafx.scene.layout.StackPane;
import org.jackhuang.hmcl.util.Logging;
import java.util.Stack; import java.util.Stack;
@ -26,17 +27,20 @@ public class StackContainerPane extends StackPane {
private final Stack<Node> stack = new Stack<>(); private final Stack<Node> stack = new Stack<>();
public void push(Node node) { public void push(Node node) {
if (!node.getProperties().containsKey("controllers")) stack.push(node);
stack.push(node);
getChildren().setAll(node); getChildren().setAll(node);
Logging.LOG.info(this + " " + stack);
} }
public void pop() { public void pop(Node node) {
stack.pop(); boolean flag = stack.remove(node);
if (stack.isEmpty()) if (stack.isEmpty())
getChildren().setAll(); getChildren().setAll();
else else
getChildren().setAll(stack.peek()); getChildren().setAll(stack.peek());
Logging.LOG.info(this + " " + stack + ", removed: " + flag + ", object: " + node);
} }
public boolean isEmpty() { public boolean isEmpty() {

View File

@ -23,15 +23,17 @@ import com.jfoenix.controls.JFXProgressBar;
import javafx.beans.property.StringProperty; import javafx.beans.property.StringProperty;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.scene.control.Label; import javafx.scene.control.Label;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane; import javafx.scene.layout.StackPane;
import org.jackhuang.hmcl.task.TaskExecutor; import org.jackhuang.hmcl.task.TaskExecutor;
import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.ui.FXUtils;
import java.util.Optional; import java.util.Optional;
import java.util.function.Consumer;
public class TaskExecutorDialogPane extends StackPane { public class TaskExecutorDialogPane extends StackPane {
private TaskExecutor executor; private TaskExecutor executor;
private Runnable onCancel; private Consumer<Region> onCancel;
@FXML @FXML
private JFXProgressBar progressBar; private JFXProgressBar progressBar;
@ -44,14 +46,14 @@ public class TaskExecutorDialogPane extends StackPane {
@FXML @FXML
private TaskListPane taskListPane; private TaskListPane taskListPane;
public TaskExecutorDialogPane(Runnable cancel) { public TaskExecutorDialogPane(Consumer<Region> cancel) {
FXUtils.loadFXML(this, "/assets/fxml/task-dialog.fxml"); FXUtils.loadFXML(this, "/assets/fxml/task-dialog.fxml");
setCancel(cancel); setCancel(cancel);
btnCancel.setOnMouseClicked(e -> { btnCancel.setOnMouseClicked(e -> {
Optional.ofNullable(executor).ifPresent(TaskExecutor::cancel); Optional.ofNullable(executor).ifPresent(TaskExecutor::cancel);
onCancel.run(); onCancel.accept(this);
}); });
} }
@ -93,7 +95,7 @@ public class TaskExecutorDialogPane extends StackPane {
progressBar.setProgress(progress); progressBar.setProgress(progress);
} }
public void setCancel(Runnable onCancel) { public void setCancel(Consumer<Region> onCancel) {
this.onCancel = onCancel; this.onCancel = onCancel;
JFXUtilities.runInFX(() -> btnCancel.setDisable(onCancel == null)); JFXUtilities.runInFX(() -> btnCancel.setDisable(onCancel == null));

View File

@ -33,8 +33,8 @@ public interface TaskExecutorDialogWizardDisplayer extends AbstractWizardDisplay
@Override @Override
default void handleTask(Map<String, Object> settings, Task task) { default void handleTask(Map<String, Object> settings, Task task) {
TaskExecutorDialogPane pane = new TaskExecutorDialogPane(() -> { TaskExecutorDialogPane pane = new TaskExecutorDialogPane(it -> {
Controllers.closeDialog(); Controllers.closeDialog(it);
Controllers.navigate(null); Controllers.navigate(null);
}); });
@ -61,7 +61,7 @@ public interface TaskExecutorDialogWizardDisplayer extends AbstractWizardDisplay
@Override @Override
public void onStop(boolean success, TaskExecutor executor) { public void onStop(boolean success, TaskExecutor executor) {
JFXUtilities.runInFX(() -> { JFXUtilities.runInFX(() -> {
Controllers.closeDialog(); Controllers.closeDialog(pane);
if (success) { if (success) {
if (settings.containsKey("success_message") && settings.get("success_message") instanceof String) 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)); Controllers.dialog((String) settings.get("success_message"), null, MessageBox.FINE_MESSAGE, () -> Controllers.navigate(null));

View File

@ -20,6 +20,7 @@ package org.jackhuang.hmcl.upgrade;
import com.google.gson.JsonParseException; import com.google.gson.JsonParseException;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import com.jfoenix.concurrency.JFXUtilities; import com.jfoenix.concurrency.JFXUtilities;
import javafx.scene.layout.Region;
import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.Launcher;
import org.jackhuang.hmcl.task.FileDownloadTask; import org.jackhuang.hmcl.task.FileDownloadTask;
import org.jackhuang.hmcl.task.Schedulers; import org.jackhuang.hmcl.task.Schedulers;
@ -38,6 +39,7 @@ import java.security.AccessController;
import java.security.PrivilegedActionException; import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction; import java.security.PrivilegedExceptionAction;
import java.util.*; import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.jar.JarFile; import java.util.jar.JarFile;
import java.util.jar.JarOutputStream; import java.util.jar.JarOutputStream;
import java.util.jar.Pack200; import java.util.jar.Pack200;
@ -116,13 +118,16 @@ public class AppDataUpgrader extends IUpgrader {
String hash = null; String hash = null;
if (map.containsKey("jarsha1")) if (map.containsKey("jarsha1"))
hash = map.get("jarsha1"); hash = map.get("jarsha1");
Controllers.dialog(Launcher.i18n("message.downloading")); Task task = new AppDataUpgraderJarTask(NetworkUtils.toURL(map.get("jar")), version.toString(), hash);
if (new AppDataUpgraderJarTask(NetworkUtils.toURL(map.get("jar")), version.toString(), hash).test()) { TaskExecutor executor = task.executor();
AtomicReference<Region> 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()) new ProcessBuilder(JavaVersion.fromCurrentEnvironment().getBinary().getAbsolutePath(), "-jar", AppDataUpgraderJarTask.getSelf(version.toString()).getAbsolutePath())
.directory(new File("").getAbsoluteFile()).start(); .directory(new File("").getAbsoluteFile()).start();
System.exit(0); System.exit(0);
} }
Controllers.closeDialog(); JFXUtilities.runInFX(() -> Controllers.closeDialog(region.get()));
} catch (IOException ex) { } catch (IOException ex) {
Logging.LOG.log(Level.SEVERE, "Failed to create upgrader", ex); Logging.LOG.log(Level.SEVERE, "Failed to create upgrader", ex);
} }
@ -133,13 +138,14 @@ public class AppDataUpgrader extends IUpgrader {
hash = map.get("packsha1"); hash = map.get("packsha1");
Task task = new AppDataUpgraderPackGzTask(NetworkUtils.toURL(map.get("pack")), version.toString(), hash); Task task = new AppDataUpgraderPackGzTask(NetworkUtils.toURL(map.get("pack")), version.toString(), hash);
TaskExecutor executor = task.executor(); TaskExecutor executor = task.executor();
JFXUtilities.runInFX(() -> Controllers.taskDialog(executor, Launcher.i18n("message.downloading"), "", null)); AtomicReference<Region> region = new AtomicReference<>();
JFXUtilities.runInFX(() -> region.set(Controllers.taskDialog(executor, Launcher.i18n("message.downloading"), "", null)));
if (executor.test()) { if (executor.test()) {
new ProcessBuilder(JavaVersion.fromCurrentEnvironment().getBinary().getAbsolutePath(), "-jar", AppDataUpgraderPackGzTask.getSelf(version.toString()).getAbsolutePath()) new ProcessBuilder(JavaVersion.fromCurrentEnvironment().getBinary().getAbsolutePath(), "-jar", AppDataUpgraderPackGzTask.getSelf(version.toString()).getAbsolutePath())
.directory(new File("").getAbsoluteFile()).start(); .directory(new File("").getAbsoluteFile()).start();
System.exit(0); System.exit(0);
} }
JFXUtilities.runInFX(Controllers::closeDialog); JFXUtilities.runInFX(() -> Controllers.closeDialog(region.get()));
} catch (IOException ex) { } catch (IOException ex) {
Logging.LOG.log(Level.SEVERE, "Failed to create upgrader", ex); Logging.LOG.log(Level.SEVERE, "Failed to create upgrader", ex);
} }

View File

@ -17,8 +17,12 @@
*/ */
package org.jackhuang.hmcl.upgrade; package org.jackhuang.hmcl.upgrade;
import com.jfoenix.concurrency.JFXUtilities;
import javafx.scene.layout.Region;
import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.Launcher;
import org.jackhuang.hmcl.task.FileDownloadTask; 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.ui.Controllers;
import org.jackhuang.hmcl.util.Charsets; import org.jackhuang.hmcl.util.Charsets;
import org.jackhuang.hmcl.util.Logging; import org.jackhuang.hmcl.util.Logging;
@ -28,6 +32,7 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.net.URL; import java.net.URL;
import java.util.List; import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level; import java.util.logging.Level;
/** /**
@ -52,7 +57,11 @@ public class NewFileUpgrader extends IUpgrader {
if (url == null) return; if (url == null) return;
File newf = new File(url.getFile()); File newf = new File(url.getFile());
Controllers.dialog(Launcher.i18n("message.downloading")); Controllers.dialog(Launcher.i18n("message.downloading"));
if (new FileDownloadTask(url, newf).test()) { Task task = new FileDownloadTask(url, newf);
TaskExecutor executor = task.executor();
AtomicReference<Region> region = new AtomicReference<>();
JFXUtilities.runInFX(() -> region.set(Controllers.taskDialog(executor, Launcher.i18n("message.downloading"), "", null)));
if (executor.test()) {
try { try {
new ProcessBuilder(newf.getCanonicalPath(), "--removeOldLauncher", getRealPath()) new ProcessBuilder(newf.getCanonicalPath(), "--removeOldLauncher", getRealPath())
.directory(new File("").getAbsoluteFile()) .directory(new File("").getAbsoluteFile())
@ -62,7 +71,7 @@ public class NewFileUpgrader extends IUpgrader {
} }
System.exit(0); System.exit(0);
} }
Controllers.closeDialog(); JFXUtilities.runInFX(() -> Controllers.closeDialog(region.get()));
} }
private static String getRealPath() { private static String getRealPath() {