diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ComponentList.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ComponentList.java index 0306acc10..03dd49b87 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ComponentList.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ComponentList.java @@ -38,7 +38,8 @@ import javafx.scene.layout.Priority; import javafx.scene.layout.VBox; import org.jackhuang.hmcl.util.javafx.MappedObservableList; -import java.util.function.Consumer; +import java.util.List; +import java.util.function.Supplier; @DefaultProperty("content") public class ComponentList extends Control { @@ -47,13 +48,17 @@ public class ComponentList extends Control { private final IntegerProperty depth = new SimpleIntegerProperty(this, "depth", 0); private boolean hasSubtitle = false; public final ObservableList content = FXCollections.observableArrayList(); - private boolean expanded = false; - private Consumer lazyInitializer; + private Supplier> lazyInitializer; public ComponentList() { getStyleClass().add("options-list"); } + public ComponentList(Supplier> lazyInitializer) { + this(); + this.lazyInitializer = lazyInitializer; + } + public String getTitle() { return title.get(); } @@ -102,17 +107,12 @@ public class ComponentList extends Control { return content; } - public void setLazyInitializer(Consumer lazyInitializer) { - this.lazyInitializer = lazyInitializer; - } - - public void onExpand() { - if (!expanded && lazyInitializer != null) { - lazyInitializer.accept(this); + void doLazyInit() { + if (lazyInitializer != null) { + this.getContent().setAll(lazyInitializer.get()); setNeedsLayout(true); + lazyInitializer = null; } - - expanded = true; } @Override @@ -125,7 +125,7 @@ public class ComponentList extends Control { return new Skin(this); } - protected static class Skin extends ControlSkinBase { + private static final class Skin extends ControlSkinBase { private static final PseudoClass PSEUDO_CLASS_FIRST = PseudoClass.getPseudoClass("first"); private static final PseudoClass PSEUDO_CLASS_LAST = PseudoClass.getPseudoClass("last"); @@ -133,7 +133,7 @@ public class ComponentList extends Control { private final ObjectBinding firstItem; private final ObjectBinding lastItem; - protected Skin(ComponentList control) { + Skin(ComponentList control) { super(control); list = MappedObservableList.create(control.getContent(), node -> { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ComponentListCell.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ComponentListCell.java index 6ae405b5e..ed9dc7314 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ComponentListCell.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/ComponentListCell.java @@ -43,7 +43,7 @@ import org.jackhuang.hmcl.ui.animation.AnimationUtils; /** * @author huangyuhui */ -class ComponentListCell extends StackPane { +final class ComponentListCell extends StackPane { private final Node content; private Animation expandAnimation; private Rectangle clipRect; @@ -139,69 +139,53 @@ class ComponentListCell extends StackPane { container.getChildren().setAll(content); groupNode.getChildren().add(container); - EventHandler onExpand; - if (AnimationUtils.isAnimationEnabled()) { - onExpand = e -> { - if (expandAnimation != null && expandAnimation.getStatus() == Animation.Status.RUNNING) { - expandAnimation.stop(); + EventHandler onExpand = e -> { + if (expandAnimation != null && expandAnimation.getStatus() == Animation.Status.RUNNING) { + expandAnimation.stop(); + } + + boolean expanded = !isExpanded(); + setExpanded(expanded); + if (expanded) { + list.doLazyInit(); + list.layout(); + } + + Platform.runLater(() -> { + double newAnimatedHeight = (list.prefHeight(-1) + 8 + 10) * (expanded ? 1 : -1); + double newHeight = expanded ? getHeight() + newAnimatedHeight : prefHeight(-1); + double contentHeight = expanded ? newAnimatedHeight : 0; + + if (expanded) { + updateClip(newHeight); } - setExpanded(!isExpanded()); - - if (isExpanded()) { - list.onExpand(); - list.layout(); - } - - Platform.runLater(() -> { - double newAnimatedHeight = (content.prefHeight(-1) + 8 + 10) * (isExpanded() ? 1 : -1); - double newHeight = isExpanded() ? getHeight() + newAnimatedHeight : prefHeight(-1); - double contentHeight = isExpanded() ? newAnimatedHeight : 0; - - if (isExpanded()) { - updateClip(newHeight); - } - + if (AnimationUtils.isAnimationEnabled()) { expandAnimation = new Timeline(new KeyFrame(new Duration(320.0), new KeyValue(container.minHeightProperty(), contentHeight, FXUtils.SINE), new KeyValue(container.maxHeightProperty(), contentHeight, FXUtils.SINE) )); - if (!isExpanded()) { + if (!expanded) { expandAnimation.setOnFinished(e2 -> updateClip(newHeight)); } expandAnimation.play(); - }); - }; - } else { - onExpand = e -> { - setExpanded(!isExpanded()); + } else { + container.setMinHeight(contentHeight); + container.setMaxHeight(contentHeight); - double newAnimatedHeight = (content.prefHeight(-1) + 8 + 10) * (isExpanded() ? 1 : -1); - double newHeight = isExpanded() ? getHeight() + newAnimatedHeight : prefHeight(-1); - double contentHeight = isExpanded() ? newAnimatedHeight : 0; - - if (isExpanded()) { - list.onExpand(); - list.layout(); - updateClip(newHeight); + if (!expanded) { + updateClip(newHeight); + } } - - container.setMinHeight(contentHeight); - container.setMaxHeight(contentHeight); - - if (!isExpanded()) { - updateClip(newHeight); - } - }; - } + }); + }; headerRippler.setOnMouseClicked(onExpand); expandButton.setOnAction((EventHandler) (Object) onExpand); - expandedProperty().addListener((a, b, newValue) -> - expandIcon.setRotate(newValue ? 180 : 0)); + expandedProperty().addListener((a, b, newValue) -> expandIcon.setRotate(newValue ? 180 : 0)); getChildren().setAll(groupNode); } else { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadPage.java index 6c466c64c..aaee3229e 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadPage.java @@ -322,12 +322,10 @@ public class DownloadPage extends Control implements DecoratorPage { for (String gameVersion : control.versions.keys().stream() .sorted(VersionNumber.VERSION_COMPARATOR.reversed()) .collect(Collectors.toList())) { - ComponentList sublist = new ComponentList(); - sublist.setLazyInitializer(self -> { - self.getContent().setAll(control.versions.get(gameVersion).stream() - .map(version -> new ModItem(version, control)) - .collect(Collectors.toList())); - }); + ComponentList sublist = new ComponentList(() -> + control.versions.get(gameVersion).stream() + .map(version -> new ModItem(version, control)) + .collect(Collectors.toList())); sublist.getStyleClass().add("no-padding"); sublist.setTitle(gameVersion); @@ -369,6 +367,7 @@ public class DownloadPage extends Control implements DecoratorPage { } private static final class ModItem extends StackPane { + ModItem(RemoteMod.Version dataItem, DownloadPage selfPage) { HBox pane = new HBox(8); pane.setPadding(new Insets(8)); @@ -378,9 +377,7 @@ public class DownloadPage extends Control implements DecoratorPage { JFXButton saveAsButton = new JFXButton(); RipplerContainer container = new RipplerContainer(pane); - container.setOnMouseClicked(e -> { - selfPage.download(dataItem); - }); + container.setOnMouseClicked(e -> selfPage.download(dataItem)); getChildren().setAll(container); saveAsButton.getStyleClass().add("toggle-icon4"); @@ -391,7 +388,7 @@ public class DownloadPage extends Control implements DecoratorPage { content.setTitle(dataItem.getName()); content.setSubtitle(FORMATTER.format(dataItem.getDatePublished().toInstant())); - saveAsButton.setOnMouseClicked(e -> selfPage.saveAs(dataItem)); + saveAsButton.setOnAction(e -> selfPage.saveAs(dataItem)); switch (dataItem.getVersionType()) { case Release: @@ -407,6 +404,9 @@ public class DownloadPage extends Control implements DecoratorPage { content.getTags().add(i18n("version.game.snapshot")); break; } + + // Workaround for https://github.com/huanghongxun/HMCL/issues/2129 + this.setMinHeight(50); } }