diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/AbstractInstallersPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/AbstractInstallersPage.java new file mode 100644 index 000000000..79183b9c0 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/AbstractInstallersPage.java @@ -0,0 +1,152 @@ +/* + * Hello Minecraft! Launcher + * Copyright (C) 2025 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 com.jfoenix.controls.JFXButton; +import com.jfoenix.controls.JFXTextField; +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.SimpleBooleanProperty; +import javafx.geometry.Insets; +import javafx.geometry.Pos; +import javafx.scene.control.*; +import javafx.scene.layout.FlowPane; +import javafx.scene.layout.HBox; +import org.jackhuang.hmcl.download.DownloadProvider; +import org.jackhuang.hmcl.download.LibraryAnalyzer; +import org.jackhuang.hmcl.ui.Controllers; +import javafx.scene.layout.BorderPane; +import org.jackhuang.hmcl.ui.FXUtils; +import org.jackhuang.hmcl.ui.InstallerItem; +import org.jackhuang.hmcl.ui.construct.MessageDialogPane; +import org.jackhuang.hmcl.ui.wizard.WizardController; +import org.jackhuang.hmcl.ui.wizard.WizardPage; + +import java.util.Map; + +import static org.jackhuang.hmcl.util.i18n.I18n.i18n; + +public abstract class AbstractInstallersPage extends Control implements WizardPage { + protected final WizardController controller; + + protected InstallerItem.InstallerItemGroup group; + protected JFXTextField txtName = new JFXTextField(); + + protected BooleanProperty installable = new SimpleBooleanProperty(); + + public AbstractInstallersPage(WizardController controller, String gameVersion, DownloadProvider downloadProvider) { + this.controller = controller; + this.group = new InstallerItem.InstallerItemGroup(gameVersion, getInstallerItemStyle()); + + for (InstallerItem library : group.getLibraries()) { + String libraryId = library.getLibraryId(); + if (libraryId.equals(LibraryAnalyzer.LibraryType.MINECRAFT.getPatchId())) continue; + library.setOnInstall(() -> { + if (LibraryAnalyzer.LibraryType.FABRIC_API.getPatchId().equals(libraryId)) { + Controllers.dialog(i18n("install.installer.fabric-api.warning"), i18n("message.warning"), MessageDialogPane.MessageType.WARNING); + } + + if (!(library.resolvedStateProperty().get() instanceof InstallerItem.IncompatibleState)) + controller.onNext(new VersionsPage(controller, i18n("install.installer.choose", i18n("install.installer." + libraryId)), gameVersion, downloadProvider, libraryId, () -> controller.onPrev(false))); + }); + library.setOnRemove(() -> { + controller.getSettings().remove(libraryId); + reload(); + }); + } + } + + protected InstallerItem.Style getInstallerItemStyle() { + return InstallerItem.Style.CARD; + } + + @Override + public abstract String getTitle(); + + protected abstract void reload(); + + @Override + public void onNavigate(Map settings) { + reload(); + } + + @Override + public abstract void cleanup(Map settings); + + protected abstract void onInstall(); + + @Override + protected Skin createDefaultSkin() { + return new InstallersPageSkin(this); + } + + protected static class InstallersPageSkin extends SkinBase { + /** + * Constructor for all SkinBase instances. + * + * @param control The control for which this Skin should attach to. + */ + protected InstallersPageSkin(AbstractInstallersPage control) { + super(control); + + BorderPane root = new BorderPane(); + root.setPadding(new Insets(16)); + + { + HBox versionNamePane = new HBox(8); + versionNamePane.getStyleClass().add("card-non-transparent"); + versionNamePane.setStyle("-fx-padding: 20 8 20 16"); + versionNamePane.setAlignment(Pos.CENTER_LEFT); + + control.txtName.setMaxWidth(300); + versionNamePane.getChildren().setAll(new Label(i18n("version.name")), control.txtName); + root.setTop(versionNamePane); + } + + { + InstallerItem[] libraries = control.group.getLibraries(); + + FlowPane libraryPane = new FlowPane(libraries); + libraryPane.setVgap(16); + libraryPane.setHgap(16); + + if (libraries.length <= 8) { + BorderPane.setMargin(libraryPane, new Insets(16, 0, 16, 0)); + root.setCenter(libraryPane); + } else { + ScrollPane scrollPane = new ScrollPane(libraryPane); + scrollPane.setFitToWidth(true); + scrollPane.setFitToHeight(true); + BorderPane.setMargin(scrollPane, new Insets(16, 0, 16, 0)); + root.setCenter(scrollPane); + } + } + + { + JFXButton installButton = FXUtils.newRaisedButton(i18n("button.install")); + installButton.disableProperty().bind(control.installable.not()); + installButton.setPrefWidth(100); + installButton.setPrefHeight(40); + installButton.setOnAction(e -> control.onInstall()); + BorderPane.setAlignment(installButton, Pos.CENTER_RIGHT); + root.setBottom(installButton); + } + + getChildren().setAll(root); + } + } +} 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 0e7d1ce64..dce9a2801 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 @@ -17,7 +17,6 @@ */ package org.jackhuang.hmcl.ui.download; -import javafx.beans.binding.Bindings; import javafx.beans.property.BooleanProperty; import javafx.beans.property.SimpleBooleanProperty; import org.jackhuang.hmcl.download.DownloadProvider; @@ -36,26 +35,21 @@ import java.util.Optional; import static org.jackhuang.hmcl.download.LibraryAnalyzer.LibraryType.MINECRAFT; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; -class AdditionalInstallersPage extends InstallersPage { +class AdditionalInstallersPage extends AbstractInstallersPage { protected final BooleanProperty compatible = new SimpleBooleanProperty(); protected final GameRepository repository; protected final String gameVersion; protected final Version version; public AdditionalInstallersPage(String gameVersion, Version version, WizardController controller, HMCLGameRepository repository, DownloadProvider downloadProvider) { - super(controller, repository, gameVersion, downloadProvider); + super(controller, gameVersion, downloadProvider); this.gameVersion = gameVersion; this.version = version; this.repository = repository; - txtName.getValidators().clear(); txtName.setText(version.getId()); txtName.setEditable(false); - installable.bind(Bindings.createBooleanBinding( - () -> compatible.get() && txtName.validate(), - txtName.textProperty(), compatible)); - for (InstallerItem library : group.getLibraries()) { String libraryId = library.getLibraryId(); if (libraryId.equals("game")) continue; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallersPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallersPage.java index 8a80a0ba1..6f07812ab 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallersPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallersPage.java @@ -17,28 +17,16 @@ */ package org.jackhuang.hmcl.ui.download; -import com.jfoenix.controls.JFXButton; -import com.jfoenix.controls.JFXTextField; -import javafx.beans.property.BooleanProperty; -import javafx.beans.property.SimpleBooleanProperty; -import javafx.geometry.Insets; -import javafx.geometry.Pos; -import javafx.scene.control.*; -import javafx.scene.layout.BorderPane; -import javafx.scene.layout.FlowPane; -import javafx.scene.layout.HBox; import org.jackhuang.hmcl.download.DownloadProvider; import org.jackhuang.hmcl.download.LibraryAnalyzer; import org.jackhuang.hmcl.download.RemoteVersion; import org.jackhuang.hmcl.game.HMCLGameRepository; import org.jackhuang.hmcl.ui.Controllers; -import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.ui.InstallerItem; import org.jackhuang.hmcl.ui.construct.MessageDialogPane; import org.jackhuang.hmcl.ui.construct.RequiredValidator; import org.jackhuang.hmcl.ui.construct.Validator; import org.jackhuang.hmcl.ui.wizard.WizardController; -import org.jackhuang.hmcl.ui.wizard.WizardPage; import java.nio.charset.StandardCharsets; import java.util.Map; @@ -46,18 +34,12 @@ import java.util.Map; import static javafx.beans.binding.Bindings.createBooleanBinding; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; -public class InstallersPage extends Control implements WizardPage { - protected final WizardController controller; - - protected InstallerItem.InstallerItemGroup group; - protected JFXTextField txtName = new JFXTextField(); - protected BooleanProperty installable = new SimpleBooleanProperty(); +public class InstallersPage extends AbstractInstallersPage { private boolean isNameModifiedByUser = false; public InstallersPage(WizardController controller, HMCLGameRepository repository, String gameVersion, DownloadProvider downloadProvider) { - this.controller = controller; - this.group = new InstallerItem.InstallerItemGroup(gameVersion, getInstallerItemStyle()); + super(controller, gameVersion, downloadProvider); txtName.getValidators().addAll( new RequiredValidator(), @@ -66,27 +48,6 @@ public class InstallersPage extends Control implements WizardPage { installable.bind(createBooleanBinding(txtName::validate, txtName.textProperty())); txtName.textProperty().addListener((obs, oldText, newText) -> isNameModifiedByUser = true); - - for (InstallerItem library : group.getLibraries()) { - String libraryId = library.getLibraryId(); - if (libraryId.equals(LibraryAnalyzer.LibraryType.MINECRAFT.getPatchId())) continue; - library.setOnInstall(() -> { - if (LibraryAnalyzer.LibraryType.FABRIC_API.getPatchId().equals(libraryId)) { - Controllers.dialog(i18n("install.installer.fabric-api.warning"), i18n("message.warning"), MessageDialogPane.MessageType.WARNING); - } - - if (!(library.resolvedStateProperty().get() instanceof InstallerItem.IncompatibleState)) - controller.onNext(new VersionsPage(controller, i18n("install.installer.choose", i18n("install.installer." + libraryId)), gameVersion, downloadProvider, libraryId, () -> controller.onPrev(false))); - }); - library.setOnRemove(() -> { - controller.getSettings().remove(libraryId); - reload(); - }); - } - } - - protected InstallerItem.Style getInstallerItemStyle() { - return InstallerItem.Style.CARD; } @Override @@ -112,11 +73,6 @@ public class InstallersPage extends Control implements WizardPage { } } - @Override - public void onNavigate(Map settings) { - reload(); - } - @Override public void cleanup(Map settings) { } @@ -143,11 +99,6 @@ public class InstallersPage extends Control implements WizardPage { } } - @Override - protected Skin createDefaultSkin() { - return new InstallersPageSkin(this); - } - private void setTxtNameWithLoaders() { StringBuilder nameBuilder = new StringBuilder(group.getGame().versionProperty().get().getVersion()); @@ -190,62 +141,4 @@ public class InstallersPage extends Control implements WizardPage { txtName.setText(nameBuilder.toString()); isNameModifiedByUser = false; } - - protected static class InstallersPageSkin extends SkinBase { - - /** - * Constructor for all SkinBase instances. - * - * @param control The control for which this Skin should attach to. - */ - protected InstallersPageSkin(InstallersPage control) { - super(control); - - BorderPane root = new BorderPane(); - root.setPadding(new Insets(16)); - - { - HBox versionNamePane = new HBox(8); - versionNamePane.getStyleClass().add("card-non-transparent"); - versionNamePane.setStyle("-fx-padding: 20 8 20 16"); - versionNamePane.setAlignment(Pos.CENTER_LEFT); - - control.txtName.setMaxWidth(300); - versionNamePane.getChildren().setAll(new Label(i18n("version.name")), control.txtName); - root.setTop(versionNamePane); - } - - { - InstallerItem[] libraries = control.group.getLibraries(); - - FlowPane libraryPane = new FlowPane(libraries); - libraryPane.setVgap(16); - libraryPane.setHgap(16); - - if (libraries.length <= 8) { - BorderPane.setMargin(libraryPane, new Insets(16, 0, 16, 0)); - root.setCenter(libraryPane); - } else { - ScrollPane scrollPane = new ScrollPane(libraryPane); - scrollPane.setFitToWidth(true); - scrollPane.setFitToHeight(true); - BorderPane.setMargin(scrollPane, new Insets(16, 0, 16, 0)); - root.setCenter(scrollPane); - } - } - - - { - JFXButton installButton = FXUtils.newRaisedButton(i18n("button.install")); - installButton.disableProperty().bind(control.installable.not()); - installButton.setPrefWidth(100); - installButton.setPrefHeight(40); - installButton.setOnAction(e -> control.onInstall()); - BorderPane.setAlignment(installButton, Pos.CENTER_RIGHT); - root.setBottom(installButton); - } - - getChildren().setAll(root); - } - } }