diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/SchematicsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/SchematicsPage.java index a96e47f7f..2d5673f9b 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/SchematicsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/SchematicsPage.java @@ -19,8 +19,10 @@ package org.jackhuang.hmcl.ui.versions; import com.jfoenix.controls.JFXButton; import com.jfoenix.controls.JFXDialogLayout; +import com.jfoenix.controls.JFXListView; import javafx.geometry.Insets; import javafx.geometry.Pos; +import javafx.scene.Group; import javafx.scene.Node; import javafx.scene.control.*; import javafx.scene.image.Image; @@ -30,6 +32,7 @@ import javafx.scene.image.WritableImage; import javafx.scene.layout.BorderPane; import javafx.scene.layout.HBox; import javafx.scene.layout.StackPane; +import javafx.scene.shape.SVGPath; import javafx.stage.FileChooser; import org.jackhuang.hmcl.schematic.LitematicFile; import org.jackhuang.hmcl.setting.Profile; @@ -221,7 +224,7 @@ public final class SchematicsPage extends ListPageBase impl getItems().addAll(item.children); } - abstract class Item extends Control implements Comparable { + abstract sealed class Item implements Comparable { boolean isDirectory() { return this instanceof DirItem; @@ -258,11 +261,6 @@ public final class SchematicsPage extends ListPageBase impl return this.getName().compareTo(o.getName()); } - - @Override - protected Skin createDefaultSkin() { - return new ItemSkin(this); - } } private final class BackItem extends Item { @@ -438,6 +436,10 @@ public final class SchematicsPage extends ListPageBase impl return SVG.SCHEMA; } + public @Nullable Image getImage() { + return image; + } + Node getIcon(int size) { if (image == null) { return super.getIcon(size); @@ -540,62 +542,122 @@ public final class SchematicsPage extends ListPageBase impl } } - private static final class ItemSkin extends SkinBase { - public ItemSkin(Item item) { - super(item); + private static final class Cell extends ListCell { - BorderPane root = new BorderPane(); + private final RipplerContainer graphics; + private final BorderPane root; + private final StackPane left; + private final TwoLineListItem center; + private final HBox right; + + private final ImageView iconImageView; + private final SVGPath iconSVG; + private final StackPane iconSVGWrapper; + + private final Tooltip tooltip = new Tooltip(); + + public Cell() { + this.root = new BorderPane(); root.getStyleClass().add("md-list-cell"); root.setPadding(new Insets(8)); { - StackPane left = new StackPane(); - left.setMaxSize(32, 32); - left.setPrefSize(32, 32); - left.getChildren().add(item.getIcon(24)); + this.left = new StackPane(); left.setPadding(new Insets(0, 8, 0, 0)); - Path path = item.getPath(); - if (path != null) { - FXUtils.installSlowTooltip(left, path.toAbsolutePath().normalize().toString()); - } + this.iconImageView = new ImageView(); + FXUtils.limitSize(iconImageView, 32, 32); + + this.iconSVG = new SVGPath(); + iconSVG.getStyleClass().add("svg"); + iconSVG.setScaleX(32.0 / SVG.DEFAULT_SIZE); + iconSVG.setScaleY(32.0 / SVG.DEFAULT_SIZE); + + this.iconSVGWrapper = new StackPane(new Group(iconSVG)); + iconSVGWrapper.setAlignment(Pos.CENTER); + FXUtils.setLimitWidth(iconSVGWrapper, 32); + FXUtils.setLimitHeight(iconSVGWrapper, 32); BorderPane.setAlignment(left, Pos.CENTER); root.setLeft(left); } { - TwoLineListItem center = new TwoLineListItem(); - center.setTitle(item.getName()); - center.setSubtitle(item.getDescription()); - + this.center = new TwoLineListItem(); root.setCenter(center); } - if (!(item instanceof BackItem)) { - HBox right = new HBox(8); + { + this.right = new HBox(8); right.setAlignment(Pos.CENTER_RIGHT); JFXButton btnReveal = new JFXButton(); FXUtils.installFastTooltip(btnReveal, i18n("reveal.in_file_manager")); btnReveal.getStyleClass().add("toggle-icon4"); btnReveal.setGraphic(SVG.FOLDER_OPEN.createIcon()); - btnReveal.setOnAction(event -> item.onReveal()); + btnReveal.setOnAction(event -> { + Item item = getItem(); + if (item != null && !(item instanceof BackItem)) + item.onReveal(); + }); JFXButton btnDelete = new JFXButton(); btnDelete.getStyleClass().add("toggle-icon4"); btnDelete.setGraphic(SVG.DELETE_FOREVER.createIcon()); - btnDelete.setOnAction(event -> + btnDelete.setOnAction(event -> { + Item item = getItem(); + if (item != null && !(item instanceof BackItem)) { Controllers.confirm(i18n("button.remove.confirm"), i18n("button.remove"), - item::onDelete, null)); + item::onDelete, null); + } + }); right.getChildren().setAll(btnReveal, btnDelete); - root.setRight(right); } - RipplerContainer container = new RipplerContainer(root); - FXUtils.onClicked(container, item::onClick); - this.getChildren().add(container); + this.graphics = new RipplerContainer(root); + FXUtils.onClicked(graphics, () -> { + Item item = getItem(); + if (item != null) + item.onClick(); + }); + } + + @Override + protected void updateItem(Item item, boolean empty) { + super.updateItem(item, empty); + + iconImageView.setImage(null); + + if (empty || item == null) { + setGraphic(null); + center.setTitle(""); + center.setSubtitle(""); + } else { + if (item instanceof LitematicFileItem fileItem && fileItem.getImage() != null) { + iconImageView.setImage(fileItem.getImage()); + left.getChildren().setAll(iconImageView); + } else { + iconSVG.setContent(item.getIcon().getPath()); + left.getChildren().setAll(iconSVGWrapper); + } + + center.setTitle(item.getName()); + center.setSubtitle(item.getDescription()); + + Path path = item.getPath(); + if (path != null) { + tooltip.setText(FileUtils.getAbsolutePath(path)); + FXUtils.installSlowTooltip(left, tooltip); + } else { + tooltip.setText(""); + Tooltip.uninstall(left, tooltip); + } + + root.setRight(item instanceof BackItem ? null : right); + + setGraphic(graphics); + } } } @@ -612,5 +674,10 @@ public final class SchematicsPage extends ListPageBase impl createToolbarButton2(i18n("schematics.create_directory"), SVG.CREATE_NEW_FOLDER, skinnable::onCreateDirectory) ); } + + @Override + protected ListCell createListCell(JFXListView listView) { + return new Cell(); + } } }