Skip to content

Commit 20249ec

Browse files
authored
重构 SchematicsPage 以使用 ListCell 展示元素 (#5276)
1 parent db38b4d commit 20249ec

1 file changed

Lines changed: 98 additions & 31 deletions

File tree

HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/SchematicsPage.java

Lines changed: 98 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@
1919

2020
import com.jfoenix.controls.JFXButton;
2121
import com.jfoenix.controls.JFXDialogLayout;
22+
import com.jfoenix.controls.JFXListView;
2223
import javafx.geometry.Insets;
2324
import javafx.geometry.Pos;
25+
import javafx.scene.Group;
2426
import javafx.scene.Node;
2527
import javafx.scene.control.*;
2628
import javafx.scene.image.Image;
@@ -30,6 +32,7 @@
3032
import javafx.scene.layout.BorderPane;
3133
import javafx.scene.layout.HBox;
3234
import javafx.scene.layout.StackPane;
35+
import javafx.scene.shape.SVGPath;
3336
import javafx.stage.FileChooser;
3437
import org.jackhuang.hmcl.schematic.LitematicFile;
3538
import org.jackhuang.hmcl.setting.Profile;
@@ -221,7 +224,7 @@ private void navigateTo(DirItem item) {
221224
getItems().addAll(item.children);
222225
}
223226

224-
abstract class Item extends Control implements Comparable<Item> {
227+
abstract sealed class Item implements Comparable<Item> {
225228

226229
boolean isDirectory() {
227230
return this instanceof DirItem;
@@ -258,11 +261,6 @@ public int compareTo(@NotNull SchematicsPage.Item o) {
258261

259262
return this.getName().compareTo(o.getName());
260263
}
261-
262-
@Override
263-
protected Skin<?> createDefaultSkin() {
264-
return new ItemSkin(this);
265-
}
266264
}
267265

268266
private final class BackItem extends Item {
@@ -438,6 +436,10 @@ SVG getIcon() {
438436
return SVG.SCHEMA;
439437
}
440438

439+
public @Nullable Image getImage() {
440+
return image;
441+
}
442+
441443
Node getIcon(int size) {
442444
if (image == null) {
443445
return super.getIcon(size);
@@ -540,62 +542,122 @@ private void updateContent(LitematicFile file) {
540542
}
541543
}
542544

543-
private static final class ItemSkin extends SkinBase<Item> {
544-
public ItemSkin(Item item) {
545-
super(item);
545+
private static final class Cell extends ListCell<Item> {
546546

547-
BorderPane root = new BorderPane();
547+
private final RipplerContainer graphics;
548+
private final BorderPane root;
549+
private final StackPane left;
550+
private final TwoLineListItem center;
551+
private final HBox right;
552+
553+
private final ImageView iconImageView;
554+
private final SVGPath iconSVG;
555+
private final StackPane iconSVGWrapper;
556+
557+
private final Tooltip tooltip = new Tooltip();
558+
559+
public Cell() {
560+
this.root = new BorderPane();
548561
root.getStyleClass().add("md-list-cell");
549562
root.setPadding(new Insets(8));
550563

551564
{
552-
StackPane left = new StackPane();
553-
left.setMaxSize(32, 32);
554-
left.setPrefSize(32, 32);
555-
left.getChildren().add(item.getIcon(24));
565+
this.left = new StackPane();
556566
left.setPadding(new Insets(0, 8, 0, 0));
557567

558-
Path path = item.getPath();
559-
if (path != null) {
560-
FXUtils.installSlowTooltip(left, path.toAbsolutePath().normalize().toString());
561-
}
568+
this.iconImageView = new ImageView();
569+
FXUtils.limitSize(iconImageView, 32, 32);
570+
571+
this.iconSVG = new SVGPath();
572+
iconSVG.getStyleClass().add("svg");
573+
iconSVG.setScaleX(32.0 / SVG.DEFAULT_SIZE);
574+
iconSVG.setScaleY(32.0 / SVG.DEFAULT_SIZE);
575+
576+
this.iconSVGWrapper = new StackPane(new Group(iconSVG));
577+
iconSVGWrapper.setAlignment(Pos.CENTER);
578+
FXUtils.setLimitWidth(iconSVGWrapper, 32);
579+
FXUtils.setLimitHeight(iconSVGWrapper, 32);
562580

563581
BorderPane.setAlignment(left, Pos.CENTER);
564582
root.setLeft(left);
565583
}
566584

567585
{
568-
TwoLineListItem center = new TwoLineListItem();
569-
center.setTitle(item.getName());
570-
center.setSubtitle(item.getDescription());
571-
586+
this.center = new TwoLineListItem();
572587
root.setCenter(center);
573588
}
574589

575-
if (!(item instanceof BackItem)) {
576-
HBox right = new HBox(8);
590+
{
591+
this.right = new HBox(8);
577592
right.setAlignment(Pos.CENTER_RIGHT);
578593

579594
JFXButton btnReveal = new JFXButton();
580595
FXUtils.installFastTooltip(btnReveal, i18n("reveal.in_file_manager"));
581596
btnReveal.getStyleClass().add("toggle-icon4");
582597
btnReveal.setGraphic(SVG.FOLDER_OPEN.createIcon());
583-
btnReveal.setOnAction(event -> item.onReveal());
598+
btnReveal.setOnAction(event -> {
599+
Item item = getItem();
600+
if (item != null && !(item instanceof BackItem))
601+
item.onReveal();
602+
});
584603

585604
JFXButton btnDelete = new JFXButton();
586605
btnDelete.getStyleClass().add("toggle-icon4");
587606
btnDelete.setGraphic(SVG.DELETE_FOREVER.createIcon());
588-
btnDelete.setOnAction(event ->
607+
btnDelete.setOnAction(event -> {
608+
Item item = getItem();
609+
if (item != null && !(item instanceof BackItem)) {
589610
Controllers.confirm(i18n("button.remove.confirm"), i18n("button.remove"),
590-
item::onDelete, null));
611+
item::onDelete, null);
612+
}
613+
});
591614

592615
right.getChildren().setAll(btnReveal, btnDelete);
593-
root.setRight(right);
594616
}
595617

596-
RipplerContainer container = new RipplerContainer(root);
597-
FXUtils.onClicked(container, item::onClick);
598-
this.getChildren().add(container);
618+
this.graphics = new RipplerContainer(root);
619+
FXUtils.onClicked(graphics, () -> {
620+
Item item = getItem();
621+
if (item != null)
622+
item.onClick();
623+
});
624+
}
625+
626+
@Override
627+
protected void updateItem(Item item, boolean empty) {
628+
super.updateItem(item, empty);
629+
630+
iconImageView.setImage(null);
631+
632+
if (empty || item == null) {
633+
setGraphic(null);
634+
center.setTitle("");
635+
center.setSubtitle("");
636+
} else {
637+
if (item instanceof LitematicFileItem fileItem && fileItem.getImage() != null) {
638+
iconImageView.setImage(fileItem.getImage());
639+
left.getChildren().setAll(iconImageView);
640+
} else {
641+
iconSVG.setContent(item.getIcon().getPath());
642+
left.getChildren().setAll(iconSVGWrapper);
643+
}
644+
645+
center.setTitle(item.getName());
646+
center.setSubtitle(item.getDescription());
647+
648+
Path path = item.getPath();
649+
if (path != null) {
650+
tooltip.setText(FileUtils.getAbsolutePath(path));
651+
FXUtils.installSlowTooltip(left, tooltip);
652+
} else {
653+
tooltip.setText("");
654+
Tooltip.uninstall(left, tooltip);
655+
}
656+
657+
root.setRight(item instanceof BackItem ? null : right);
658+
659+
setGraphic(graphics);
660+
}
599661
}
600662
}
601663

@@ -612,5 +674,10 @@ protected List<Node> initializeToolbar(SchematicsPage skinnable) {
612674
createToolbarButton2(i18n("schematics.create_directory"), SVG.CREATE_NEW_FOLDER, skinnable::onCreateDirectory)
613675
);
614676
}
677+
678+
@Override
679+
protected ListCell<Item> createListCell(JFXListView<Item> listView) {
680+
return new Cell();
681+
}
615682
}
616683
}

0 commit comments

Comments
 (0)