From ccc64db805e366ebfad54c88fe7a088119d14392 Mon Sep 17 00:00:00 2001 From: Glavo Date: Tue, 13 Jan 2026 21:35:34 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84=20JavaManagementPage=20?= =?UTF-8?q?=E4=BB=A5=E4=BD=BF=E7=94=A8=20ListCell=20=E5=B1=95=E7=A4=BA?= =?UTF-8?q?=E5=85=83=E7=B4=A0=20(#5223)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hmcl/ui/main/JavaManagementPage.java | 264 ++++++++++-------- 1 file changed, 144 insertions(+), 120 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/JavaManagementPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/JavaManagementPage.java index a717021a8..1465c9bab 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/JavaManagementPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/JavaManagementPage.java @@ -18,17 +18,19 @@ package org.jackhuang.hmcl.ui.main; import com.jfoenix.controls.JFXButton; +import com.jfoenix.controls.JFXListView; import javafx.beans.binding.Bindings; import javafx.beans.value.ChangeListener; import javafx.collections.FXCollections; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.Node; -import javafx.scene.control.Control; +import javafx.scene.control.ListCell; import javafx.scene.control.Skin; -import javafx.scene.control.SkinBase; +import javafx.scene.control.Tooltip; import javafx.scene.layout.BorderPane; import javafx.scene.layout.HBox; +import javafx.scene.layout.StackPane; import javafx.stage.FileChooser; import org.jackhuang.hmcl.java.JavaInfo; import org.jackhuang.hmcl.java.JavaManager; @@ -42,6 +44,7 @@ import org.jackhuang.hmcl.ui.construct.MessageDialogPane; import org.jackhuang.hmcl.ui.construct.RipplerContainer; import org.jackhuang.hmcl.ui.construct.TwoLineListItem; import org.jackhuang.hmcl.ui.wizard.SinglePageWizardProvider; +import org.jackhuang.hmcl.util.FXThread; import org.jackhuang.hmcl.util.Pair; import org.jackhuang.hmcl.util.TaskCancellationAction; import org.jackhuang.hmcl.util.io.FileUtils; @@ -62,7 +65,7 @@ import static org.jackhuang.hmcl.util.logging.Logger.LOG; /** * @author Glavo */ -public final class JavaManagementPage extends ListPageBase { +public final class JavaManagementPage extends ListPageBase { @SuppressWarnings("FieldCanBeLocal") private final ChangeListener> listener; @@ -172,130 +175,17 @@ public final class JavaManagementPage extends ListPageBase javaRuntimes) { if (javaRuntimes != null) { - List items = new ArrayList<>(); - for (JavaRuntime java : javaRuntimes) { - items.add(new JavaItem(java)); - } - this.setItems(FXCollections.observableList(items)); + this.setItems(FXCollections.observableArrayList(javaRuntimes)); this.setLoading(false); - } else + } else { this.setLoading(true); - } - - static final class JavaItem extends Control { - private final JavaRuntime java; - - public JavaItem(JavaRuntime java) { - this.java = java; - } - - public JavaRuntime getJava() { - return java; - } - - public void onReveal() { - Path target; - Path parent = java.getBinary().getParent(); - if (parent != null - && parent.getParent() != null - && parent.getFileName() != null - && parent.getFileName().toString().equals("bin") - && Files.exists(parent.getParent().resolve("release"))) { - target = parent.getParent(); - } else { - target = java.getBinary(); - } - - FXUtils.showFileInExplorer(target); - } - - public void onRemove() { - if (java.isManaged()) { - Controllers.taskDialog(JavaManager.getUninstallJavaTask(java), i18n("java.uninstall"), TaskCancellationAction.NORMAL); - } else { - String path = java.getBinary().toString(); - ConfigHolder.globalConfig().getUserJava().remove(path); - ConfigHolder.globalConfig().getDisabledJava().add(path); - try { - JavaManager.removeJava(java); - } catch (InterruptedException ignored) { - } - } - } - - @Override - protected Skin createDefaultSkin() { - return new JavaRuntimeItemSkin(this); - } - - } - - private static final class JavaRuntimeItemSkin extends SkinBase { - - JavaRuntimeItemSkin(JavaItem control) { - super(control); - JavaRuntime java = control.getJava(); - String vendor = JavaInfo.normalizeVendor(java.getVendor()); - - BorderPane root = new BorderPane(); - - HBox center = new HBox(); - center.setMouseTransparent(true); - center.setSpacing(8); - center.setAlignment(Pos.CENTER_LEFT); - - TwoLineListItem item = new TwoLineListItem(); - item.setTitle((java.isJDK() ? "JDK" : "JRE") + " " + java.getVersion()); - item.setSubtitle(java.getBinary().toString()); - item.addTag(i18n("java.info.architecture") + ": " + java.getArchitecture().getDisplayName()); - if (vendor != null) - item.addTag(i18n("java.info.vendor") + ": " + vendor); - BorderPane.setAlignment(item, Pos.CENTER); - center.getChildren().setAll(item); - root.setCenter(center); - - HBox right = new HBox(); - right.setAlignment(Pos.CENTER_RIGHT); - { - JFXButton revealButton = new JFXButton(); - revealButton.getStyleClass().add("toggle-icon4"); - revealButton.setGraphic(FXUtils.limitingSize(SVG.FOLDER_OPEN.createIcon(24), 24, 24)); - revealButton.setOnAction(e -> control.onReveal()); - FXUtils.installFastTooltip(revealButton, i18n("reveal.in_file_manager")); - - JFXButton removeButton = new JFXButton(); - removeButton.getStyleClass().add("toggle-icon4"); - removeButton.setOnAction(e -> Controllers.confirm( - java.isManaged() ? i18n("java.uninstall.confirm") : i18n("java.disable.confirm"), - i18n("message.warning"), - control::onRemove, - null - )); - if (java.isManaged()) { - removeButton.setGraphic(FXUtils.limitingSize(SVG.DELETE_FOREVER.createIcon(24), 24, 24)); - FXUtils.installFastTooltip(removeButton, i18n("java.uninstall")); - if (JavaRuntime.CURRENT_JAVA != null && java.getBinary().equals(JavaRuntime.CURRENT_JAVA.getBinary())) - removeButton.setDisable(true); - } else { - removeButton.setGraphic(FXUtils.limitingSize(SVG.DELETE.createIcon(24), 24, 24)); - FXUtils.installFastTooltip(removeButton, i18n("java.disable")); - } - - right.getChildren().setAll(revealButton, removeButton); - } - root.setRight(right); - - root.getStyleClass().add("md-list-cell"); - root.setPadding(new Insets(8)); - - getChildren().setAll(new RipplerContainer(root)); } } - private static final class JavaPageSkin extends ToolbarListPageSkin { + private static final class JavaPageSkin extends ToolbarListPageSkin { JavaPageSkin(JavaManagementPage skinnable) { super(skinnable); @@ -317,5 +207,139 @@ public final class JavaManagementPage extends ListPageBase createListCell(JFXListView listView) { + return new JavaItemCell(); + } + } + + private static final class JavaItemCell extends ListCell { + private final Node graphic; + private final TwoLineListItem content; + + private SVG removeIcon; + private final StackPane removeIconPane; + private final Tooltip removeTooltip = new Tooltip(); + + JavaItemCell() { + BorderPane root = new BorderPane(); + + HBox center = new HBox(); + center.setMouseTransparent(true); + center.setSpacing(8); + center.setAlignment(Pos.CENTER_LEFT); + + this.content = new TwoLineListItem(); + + BorderPane.setAlignment(content, Pos.CENTER); + center.getChildren().setAll(content); + root.setCenter(center); + + HBox right = new HBox(); + right.setAlignment(Pos.CENTER_RIGHT); + { + JFXButton revealButton = new JFXButton(); + revealButton.setGraphic(FXUtils.limitingSize(SVG.FOLDER_OPEN.createIcon(24), 24, 24)); + revealButton.getStyleClass().add("toggle-icon4"); + revealButton.setOnAction(e -> { + JavaRuntime java = getItem(); + if (java != null) + onReveal(java); + }); + FXUtils.installFastTooltip(revealButton, i18n("reveal.in_file_manager")); + + JFXButton removeButton = new JFXButton(); + removeButton.getStyleClass().add("toggle-icon4"); + removeButton.setOnAction(e -> { + JavaRuntime java = getItem(); + if (java != null) + onRemove(java); + }); + FXUtils.installFastTooltip(removeButton, removeTooltip); + + this.removeIconPane = new StackPane(); + removeIconPane.setAlignment(Pos.CENTER); + FXUtils.setLimitWidth(removeIconPane, 24); + FXUtils.setLimitHeight(removeIconPane, 24); + removeButton.setGraphic(removeIconPane); + + right.getChildren().setAll(revealButton, removeButton); + } + root.setRight(right); + + root.getStyleClass().add("md-list-cell"); + root.setPadding(new Insets(8)); + + this.graphic = new RipplerContainer(root); + } + + @Override + protected void updateItem(JavaRuntime item, boolean empty) { + super.updateItem(item, empty); + if (empty || item == null) { + setGraphic(null); + } else { + content.setTitle((item.isJDK() ? "JDK" : "JRE") + " " + item.getVersion()); + content.setSubtitle(item.getBinary().toString()); + + content.getTags().clear(); + content.addTag(i18n("java.info.architecture") + ": " + item.getArchitecture().getDisplayName()); + String vendor = JavaInfo.normalizeVendor(item.getVendor()); + if (vendor != null) + content.addTag(i18n("java.info.vendor") + ": " + vendor); + + SVG newRemoveIcon = item.isManaged() ? SVG.DELETE_FOREVER : SVG.DELETE; + if (removeIcon != newRemoveIcon) { + removeIcon = newRemoveIcon; + removeIconPane.getChildren().setAll(removeIcon.createIcon(24)); + removeTooltip.setText(item.isManaged() ? i18n("java.uninstall") : i18n("java.disable")); + } + + setGraphic(graphic); + } + } + + private void onReveal(JavaRuntime java) { + Path target; + Path parent = java.getBinary().getParent(); + if (parent != null + && parent.getParent() != null + && parent.getFileName() != null + && parent.getFileName().toString().equals("bin") + && Files.exists(parent.getParent().resolve("release"))) { + target = parent.getParent(); + } else { + target = java.getBinary(); + } + + FXUtils.showFileInExplorer(target); + } + + private void onRemove(JavaRuntime java) { + if (java.isManaged()) { + Controllers.confirm( + i18n("java.uninstall.confirm"), + i18n("message.warning"), + () -> Controllers.taskDialog(JavaManager.getUninstallJavaTask(java), i18n("java.uninstall"), TaskCancellationAction.NORMAL), + null + ); + } else { + Controllers.confirm( + i18n("java.disable.confirm"), + i18n("message.warning"), + () -> { + String path = java.getBinary().toString(); + ConfigHolder.globalConfig().getUserJava().remove(path); + ConfigHolder.globalConfig().getDisabledJava().add(path); + try { + JavaManager.removeJava(java); + } catch (InterruptedException ignored) { + } + }, + null + ); + } + } } }