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 3776fd71f..5a07574e1 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java @@ -52,6 +52,7 @@ import javafx.stage.Stage; import javafx.util.Callback; import javafx.util.Duration; import javafx.util.StringConverter; +import org.jackhuang.hmcl.setting.Theme; import org.jackhuang.hmcl.task.CacheFileTask; import org.jackhuang.hmcl.task.Schedulers; import org.jackhuang.hmcl.task.Task; @@ -1159,6 +1160,13 @@ public final class FXUtils { return button; } + public static JFXButton newToggleButton4(SVG icon) { + JFXButton button = new JFXButton(); + button.getStyleClass().add("toggle-icon4"); + button.setGraphic(icon.createIcon(Theme.blackFill(), -1)); + return button; + } + public static Label truncatedLabel(String text, int limit) { Label label = new Label(); if (text.length() <= limit) { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java index 030d66c4d..9d1660570 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java @@ -19,12 +19,13 @@ package org.jackhuang.hmcl.ui.download; import com.jfoenix.controls.*; import javafx.beans.InvalidationListener; -import javafx.beans.property.ObjectProperty; -import javafx.beans.property.SimpleObjectProperty; +import javafx.beans.property.*; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.geometry.Insets; +import javafx.geometry.Pos; import javafx.scene.control.*; +import javafx.scene.image.ImageView; import javafx.scene.input.KeyCode; import javafx.scene.input.KeyEvent; import javafx.scene.layout.*; @@ -41,7 +42,6 @@ import org.jackhuang.hmcl.download.neoforge.NeoForgeRemoteVersion; import org.jackhuang.hmcl.download.optifine.OptiFineRemoteVersion; import org.jackhuang.hmcl.download.quilt.QuiltAPIRemoteVersion; import org.jackhuang.hmcl.download.quilt.QuiltRemoteVersion; -import org.jackhuang.hmcl.setting.Theme; import org.jackhuang.hmcl.setting.VersionIconType; import org.jackhuang.hmcl.task.Schedulers; import org.jackhuang.hmcl.task.Task; @@ -73,17 +73,23 @@ public final class VersionsPage extends Control implements WizardPage, Refreshab private final String libraryId; private final String title; private final Navigation navigation; + private final DownloadProvider downloadProvider; private final VersionList versionList; private final Runnable callback; private final ObservableList versions = FXCollections.observableArrayList(); private final ObjectProperty status = new SimpleObjectProperty<>(Status.LOADING); - public VersionsPage(Navigation navigation, String title, String gameVersion, DownloadProvider downloadProvider, String libraryId, Runnable callback) { + public VersionsPage(Navigation navigation, + String title, String gameVersion, + DownloadProvider downloadProvider, + String libraryId, + Runnable callback) { this.title = title; this.gameVersion = gameVersion; this.libraryId = libraryId; this.navigation = navigation; + this.downloadProvider = downloadProvider; this.versionList = downloadProvider.getVersionListById(libraryId); this.callback = callback; @@ -130,10 +136,6 @@ public final class VersionsPage extends Control implements WizardPage, Refreshab navigation.onPrev(true); } - private void onSponsor() { - FXUtils.openLink("https://bmclapidoc.bangbang93.com"); - } - private enum Status { LOADING, FAILED, @@ -149,22 +151,61 @@ public final class VersionsPage extends Control implements WizardPage, Refreshab } private static class RemoteVersionListCell extends ListCell { - private final IconedTwoLineListItem content = new IconedTwoLineListItem(); - private final RipplerContainer ripplerContainer = new RipplerContainer(content); + private final VersionsPage control; + + private final TwoLineListItem twoLineListItem = new TwoLineListItem(); + private final ImageView imageView = new ImageView(); private final StackPane pane = new StackPane(); private final Holder lastCell; - RemoteVersionListCell(Holder lastCell, String libraryId) { + RemoteVersionListCell(Holder lastCell, VersionsPage control) { this.lastCell = lastCell; - if ("game".equals(libraryId)) { - content.getExternalLinkButton().setGraphic(SVG.GLOBE_BOOK.createIcon(Theme.blackFill(), -1)); - FXUtils.installFastTooltip(content.getExternalLinkButton(), i18n("wiki.tooltip")); + this.control = control; + + HBox hbox = new HBox(16); + HBox.setHgrow(twoLineListItem, Priority.ALWAYS); + hbox.setAlignment(Pos.CENTER); + + HBox actions = new HBox(8); + actions.setAlignment(Pos.CENTER); + { + if ("game".equals(control.libraryId)) { + JFXButton wikiButton = newToggleButton4(SVG.GLOBE_BOOK); + wikiButton.setOnAction(event -> onOpenWiki()); + FXUtils.installFastTooltip(wikiButton, i18n("wiki.tooltip")); + actions.getChildren().add(wikiButton); + } + + JFXButton actionButton = newToggleButton4(SVG.ARROW_FORWARD); + actionButton.setOnAction(e -> onAction()); + actions.getChildren().add(actionButton); } + hbox.getChildren().setAll(imageView, twoLineListItem, actions); + pane.getStyleClass().add("md-list-cell"); - StackPane.setMargin(content, new Insets(10, 16, 10, 16)); - pane.getChildren().setAll(ripplerContainer); + StackPane.setMargin(hbox, new Insets(10, 16, 10, 16)); + pane.getChildren().setAll(new RipplerContainer(hbox)); + + FXUtils.onClicked(this, this::onAction); + } + + private void onAction() { + RemoteVersion item = getItem(); + if (item == null) + return; + + control.navigation.getSettings().put(control.libraryId, item); + control.callback.run(); + } + + private void onOpenWiki() { + RemoteVersion item = getItem(); + if (!(item instanceof GameRemoteVersion)) + return; + + FXUtils.openLink(I18n.getWikiLink((GameRemoteVersion) item)); } @Override @@ -182,37 +223,36 @@ public final class VersionsPage extends Control implements WizardPage, Refreshab } setGraphic(pane); - content.setTitle(I18n.getDisplaySelfVersion(remoteVersion)); + twoLineListItem.setTitle(I18n.getDisplaySelfVersion(remoteVersion)); if (remoteVersion.getReleaseDate() != null) { - content.setSubtitle(I18n.formatDateTime(remoteVersion.getReleaseDate())); + twoLineListItem.setSubtitle(I18n.formatDateTime(remoteVersion.getReleaseDate())); } else { - content.setSubtitle(null); + twoLineListItem.setSubtitle(null); } if (remoteVersion instanceof GameRemoteVersion) { RemoteVersion.Type versionType = remoteVersion.getVersionType(); switch (versionType) { case RELEASE: - content.getTags().setAll(i18n("version.game.release")); - content.setImage(VersionIconType.GRASS.getIcon()); + twoLineListItem.getTags().setAll(i18n("version.game.release")); + imageView.setImage(VersionIconType.GRASS.getIcon()); break; case PENDING: case SNAPSHOT: if (versionType == RemoteVersion.Type.SNAPSHOT && GameVersionNumber.asGameVersion(remoteVersion.getGameVersion()).isAprilFools()) { - content.getTags().setAll(i18n("version.game.april_fools")); - content.setImage(VersionIconType.APRIL_FOOLS.getIcon()); + twoLineListItem.getTags().setAll(i18n("version.game.april_fools")); + imageView.setImage(VersionIconType.APRIL_FOOLS.getIcon()); } else { - content.getTags().setAll(i18n("version.game.snapshot")); - content.setImage(VersionIconType.COMMAND.getIcon()); + twoLineListItem.getTags().setAll(i18n("version.game.snapshot")); + imageView.setImage(VersionIconType.COMMAND.getIcon()); } break; default: - content.getTags().setAll(i18n("version.game.old")); - content.setImage(VersionIconType.CRAFT_TABLE.getIcon()); + twoLineListItem.getTags().setAll(i18n("version.game.old")); + imageView.setImage(VersionIconType.CRAFT_TABLE.getIcon()); break; } - content.setExternalLink(I18n.getWikiLink((GameRemoteVersion) remoteVersion)); } else { VersionIconType iconType; if (remoteVersion instanceof LiteLoaderRemoteVersion) @@ -230,14 +270,13 @@ public final class VersionsPage extends Control implements WizardPage, Refreshab else if (remoteVersion instanceof QuiltRemoteVersion || remoteVersion instanceof QuiltAPIRemoteVersion) iconType = VersionIconType.QUILT; else - iconType = null; + iconType = VersionIconType.COMMAND; - content.setImage(iconType != null ? iconType.getIcon() : null); - if (content.getSubtitle() == null) - content.setSubtitle(remoteVersion.getGameVersion()); + imageView.setImage(iconType.getIcon()); + if (twoLineListItem.getSubtitle() == null) + twoLineListItem.setSubtitle(remoteVersion.getGameVersion()); else - content.getTags().setAll(remoteVersion.getGameVersion()); - content.setExternalLink(null); + twoLineListItem.getTags().setAll(remoteVersion.getGameVersion()); } } } @@ -355,14 +394,7 @@ public final class VersionsPage extends Control implements WizardPage, Refreshab control.versions.addListener((InvalidationListener) o -> updateList()); Holder lastCell = new Holder<>(); - list.setCellFactory(listView -> new RemoteVersionListCell(lastCell, control.libraryId)); - - FXUtils.onClicked(list, () -> { - if (list.getSelectionModel().getSelectedIndex() < 0) - return; - control.navigation.getSettings().put(control.libraryId, list.getSelectionModel().getSelectedItem()); - control.callback.run(); - }); + list.setCellFactory(listView -> new RemoteVersionListCell(lastCell, control)); ComponentList.setVgrow(list, Priority.ALWAYS);