From aa013a86ddede95d031c1789cdbc0253ecd3ff9c Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Mon, 18 Mar 2019 23:17:53 +0800 Subject: [PATCH] Add upgrade button on Forge, LiteLoader, OptiFine --- .../org/jackhuang/hmcl/ui/InstallerItem.java | 52 +++++++---- .../UpdateInstallerWizardProvider.java | 88 +++++++++++++++++++ .../hmcl/ui/versions/InstallerListPage.java | 51 +++++++---- HMCL/src/main/resources/assets/css/root.css | 3 +- .../resources/assets/lang/I18N.properties | 2 + .../resources/assets/lang/I18N_zh.properties | 2 + .../assets/lang/I18N_zh_CN.properties | 2 + 7 files changed, 161 insertions(+), 39 deletions(-) create mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/ui/download/UpdateInstallerWizardProvider.java 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 d584789c1..53c4b54db 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerItem.java @@ -17,10 +17,13 @@ */ package org.jackhuang.hmcl.ui; +import com.jfoenix.controls.JFXButton; import com.jfoenix.effects.JFXDepthManager; -import javafx.fxml.FXML; -import javafx.scene.control.Label; +import javafx.geometry.Pos; import javafx.scene.layout.BorderPane; +import javafx.scene.layout.HBox; +import org.jackhuang.hmcl.setting.Theme; +import org.jackhuang.hmcl.ui.construct.TwoLineListItem; import java.util.function.Consumer; @@ -30,26 +33,37 @@ import static org.jackhuang.hmcl.util.i18n.I18n.i18n; * @author huangyuhui */ public class InstallerItem extends BorderPane { - private final Consumer deleteCallback; - - @FXML - private Label lblInstallerArtifact; - - @FXML - private Label lblInstallerVersion; - - public InstallerItem(String artifact, String version, Consumer deleteCallback) { - this.deleteCallback = deleteCallback; - FXUtils.loadFXML(this, "/assets/fxml/version/installer-item.fxml"); + public InstallerItem(String artifact, String version, Runnable upgrade, Consumer deleteCallback) { + getStyleClass().add("two-line-list-item"); setStyle("-fx-background-radius: 2; -fx-background-color: white; -fx-padding: 8;"); JFXDepthManager.setDepth(this, 1); - lblInstallerArtifact.setText(artifact); - lblInstallerVersion.setText(i18n("archive.version") + ": " + version); + + { + TwoLineListItem item = new TwoLineListItem(); + item.setTitle(artifact); + item.setSubtitle(i18n("archive.version") + ": " + version); + setCenter(item); + } + + { + HBox hBox = new HBox(); + + JFXButton upgradeButton = new JFXButton(); + upgradeButton.setGraphic(SVG.update(Theme.blackFillBinding(), -1, -1)); + upgradeButton.getStyleClass().add("toggle-icon4"); + FXUtils.installFastTooltip(upgradeButton, i18n("install.change_version")); + upgradeButton.setOnMouseClicked(e -> upgrade.run()); + + JFXButton deleteButton = new JFXButton(); + deleteButton.setGraphic(SVG.close(Theme.blackFillBinding(), -1, -1)); + deleteButton.getStyleClass().add("toggle-icon4"); + deleteButton.setOnMouseClicked(e -> deleteCallback.accept(this)); + + hBox.setAlignment(Pos.CENTER_RIGHT); + hBox.getChildren().setAll(upgradeButton, deleteButton); + setRight(hBox); + } } - @FXML - private void onDelete() { - deleteCallback.accept(this); - } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/UpdateInstallerWizardProvider.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/UpdateInstallerWizardProvider.java new file mode 100644 index 000000000..655ec03d4 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/UpdateInstallerWizardProvider.java @@ -0,0 +1,88 @@ +/* + * Hello Minecraft! Launcher + * Copyright (C) 2019 huangyuhui and contributors + * + * 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 . + */ +package org.jackhuang.hmcl.ui.download; + +import javafx.scene.Node; +import org.jackhuang.hmcl.download.DownloadProvider; +import org.jackhuang.hmcl.download.MaintainTask; +import org.jackhuang.hmcl.download.RemoteVersion; +import org.jackhuang.hmcl.game.Library; +import org.jackhuang.hmcl.game.Version; +import org.jackhuang.hmcl.setting.Profile; +import org.jackhuang.hmcl.ui.Controllers; +import org.jackhuang.hmcl.ui.wizard.WizardController; +import org.jackhuang.hmcl.ui.wizard.WizardProvider; + +import java.util.LinkedList; +import java.util.Map; + +import static org.jackhuang.hmcl.ui.download.InstallerWizardProvider.alertFailureMessage; +import static org.jackhuang.hmcl.util.i18n.I18n.i18n; + +public final class UpdateInstallerWizardProvider implements WizardProvider { + private final Profile profile; + private final String gameVersion; + private final Version version; + private final String libraryId; + private final Library oldLibrary; + + public UpdateInstallerWizardProvider(Profile profile, String gameVersion, Version version, String libraryId, Library oldLibrary) { + this.profile = profile; + this.gameVersion = gameVersion; + this.version = version; + this.libraryId = libraryId; + this.oldLibrary = oldLibrary; + } + + @Override + public void start(Map settings) { + } + + @Override + public Object finish(Map settings) { + settings.put("success_message", i18n("install.success")); + settings.put("failure_callback", (FailureCallback) (settings1, exception, next) -> alertFailureMessage(exception, next)); + + // We remove library but not save it, + // so if installation failed will not break down current version. + LinkedList newList = new LinkedList<>(version.getLibraries()); + newList.remove(oldLibrary); + return new MaintainTask(version.setLibraries(newList)) + .thenCompose(profile.getDependency().installLibraryAsync((RemoteVersion) settings.get(libraryId))) + .then(profile.getRepository().refreshVersionsAsync()); + } + + @Override + public Node createPage(WizardController controller, int step, Map settings) { + DownloadProvider provider = profile.getDependency().getDownloadProvider(); + switch (step) { + case 0: + return new VersionsPage(controller, i18n("install.installer.choose", i18n("install.installer." + libraryId)), gameVersion, provider, libraryId, () -> { + Controllers.confirmDialog(i18n("install.change_version.confirm", i18n("install.installer." + libraryId), oldLibrary.getVersion(), ((RemoteVersion) settings.get(libraryId)).getSelfVersion()), + i18n("install.change_version"), controller::onFinish, controller::onCancel); + }); + default: + throw new IllegalStateException(); + } + } + + @Override + public boolean cancel() { + return true; + } +} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/InstallerListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/InstallerListPage.java index 020ff62de..072ec6915 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/InstallerListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/InstallerListPage.java @@ -30,9 +30,9 @@ import org.jackhuang.hmcl.ui.Controllers; import org.jackhuang.hmcl.ui.InstallerItem; import org.jackhuang.hmcl.ui.ListPage; import org.jackhuang.hmcl.ui.download.InstallerWizardProvider; +import org.jackhuang.hmcl.ui.download.UpdateInstallerWizardProvider; import java.util.LinkedList; -import java.util.Optional; import java.util.function.Consumer; import java.util.function.Function; @@ -42,37 +42,50 @@ public class InstallerListPage extends ListPage { private Profile profile; private String versionId; private Version version; + private String gameVersion; public void loadVersion(Profile profile, String versionId) { this.profile = profile; this.versionId = versionId; this.version = profile.getRepository().getResolvedVersion(versionId); + this.gameVersion = null; - LibraryAnalyzer analyzer = LibraryAnalyzer.analyze(version); + Task.ofResult(() -> { + gameVersion = GameVersion.minecraftVersion(profile.getRepository().getVersionJar(version)).orElse(null); - Function> removeAction = library -> x -> { - LinkedList newList = new LinkedList<>(version.getLibraries()); - newList.remove(library); - new MaintainTask(version.setLibraries(newList)) - .then(maintainedVersion -> new VersionJsonSaveTask(profile.getRepository(), maintainedVersion)) - .with(profile.getRepository().refreshVersionsAsync()) - .with(Task.of(Schedulers.javafx(), () -> loadVersion(this.profile, this.versionId))) - .start(); - }; + return LibraryAnalyzer.analyze(version); + }).thenAccept(Schedulers.javafx(), analyzer -> { + Function> removeAction = library -> x -> { + LinkedList newList = new LinkedList<>(version.getLibraries()); + newList.remove(library); + new MaintainTask(version.setLibraries(newList)) + .then(maintainedVersion -> new VersionJsonSaveTask(profile.getRepository(), maintainedVersion)) + .with(profile.getRepository().refreshVersionsAsync()) + .with(Task.of(Schedulers.javafx(), () -> loadVersion(this.profile, this.versionId))) + .start(); + }; - itemsProperty().clear(); - analyzer.getForge().ifPresent(library -> itemsProperty().add(new InstallerItem("Forge", library.getVersion(), removeAction.apply(library)))); - analyzer.getLiteLoader().ifPresent(library -> itemsProperty().add(new InstallerItem("LiteLoader", library.getVersion(), removeAction.apply(library)))); - analyzer.getOptiFine().ifPresent(library -> itemsProperty().add(new InstallerItem("OptiFine", library.getVersion(), removeAction.apply(library)))); + itemsProperty().clear(); + analyzer.getForge().ifPresent(library -> itemsProperty().add( + new InstallerItem("Forge", library.getVersion(), () -> { + Controllers.getDecorator().startWizard(new UpdateInstallerWizardProvider(profile, gameVersion, version, "forge", library)); + }, removeAction.apply(library)))); + analyzer.getLiteLoader().ifPresent(library -> itemsProperty().add( + new InstallerItem("LiteLoader", library.getVersion(), () -> { + Controllers.getDecorator().startWizard(new UpdateInstallerWizardProvider(profile, gameVersion, version, "liteloader", library)); + }, removeAction.apply(library)))); + analyzer.getOptiFine().ifPresent(library -> itemsProperty().add( + new InstallerItem("OptiFine", library.getVersion(), () -> { + Controllers.getDecorator().startWizard(new UpdateInstallerWizardProvider(profile, gameVersion, version, "optifine", library)); + }, removeAction.apply(library)))); + }).start(); } @Override public void add() { - Optional gameVersion = GameVersion.minecraftVersion(profile.getRepository().getVersionJar(version)); - - if (!gameVersion.isPresent()) + if (gameVersion == null) Controllers.dialog(i18n("version.cannot_read")); else - Controllers.getDecorator().startWizard(new InstallerWizardProvider(profile, gameVersion.get(), version)); + Controllers.getDecorator().startWizard(new InstallerWizardProvider(profile, gameVersion, version)); } } diff --git a/HMCL/src/main/resources/assets/css/root.css b/HMCL/src/main/resources/assets/css/root.css index 6f36ecd0e..d3ac305c8 100644 --- a/HMCL/src/main/resources/assets/css/root.css +++ b/HMCL/src/main/resources/assets/css/root.css @@ -995,7 +995,8 @@ } .jfx-decorator-title { - -fx-text-fill: -fx-base-text-fill; -fx-font-size: 15; + -fx-text-fill: -fx-base-text-fill; + -fx-font-size: 15; } .resize-border { diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 0e995c956..0589d09d6 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -124,6 +124,8 @@ input.not_empty=Required field input.url=Must be a valid URL. install=Install New Game +install.change_version=Change version +install.change_version.confirm=Sure to update %s from verison %s to %s? install.failed=Failed to install install.failed.downloading=Failed to install due to some files not downloaded successfully install.failed.downloading.detail=Failed to download file: %s diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 4c974003d..08f064d89 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -123,6 +123,8 @@ input.not_empty=必填 input.url=必須為有效連結 install=新增遊戲 +install.change_version=更換版本 +install.change_version.confirm=你確定要將 %s 從 %s 更新到 %s 嗎? install.failed=安裝失敗 install.failed.downloading=安裝失敗,部分文件未能完成下載 install.failed.downloading.detail=未能下載檔案:%s diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties index b120ddda0..5fcbfe4e6 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -123,6 +123,8 @@ input.not_empty=必填项 input.url=必须是合法的链接 install=添加游戏 +install.change_version=更换版本 +install.change_version.confirm=你确定要将 %s 从 %s 更新到 %s 吗? install.failed=安装失败 install.failed.downloading=安装失败,部分文件未能完成下载 install.failed.downloading.detail=未能下载文件:%s