fix #2129: Fix computePerfHeight of ComponentList (#2139)

* update

* update style

* update

* update

* update

* update
This commit is contained in:
Glavo
2023-02-19 19:22:01 +08:00
committed by GitHub
parent 6f70da51f9
commit 090b83bf9c
3 changed files with 55 additions and 71 deletions

View File

@@ -38,7 +38,8 @@ import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox; import javafx.scene.layout.VBox;
import org.jackhuang.hmcl.util.javafx.MappedObservableList; import org.jackhuang.hmcl.util.javafx.MappedObservableList;
import java.util.function.Consumer; import java.util.List;
import java.util.function.Supplier;
@DefaultProperty("content") @DefaultProperty("content")
public class ComponentList extends Control { public class ComponentList extends Control {
@@ -47,13 +48,17 @@ public class ComponentList extends Control {
private final IntegerProperty depth = new SimpleIntegerProperty(this, "depth", 0); private final IntegerProperty depth = new SimpleIntegerProperty(this, "depth", 0);
private boolean hasSubtitle = false; private boolean hasSubtitle = false;
public final ObservableList<Node> content = FXCollections.observableArrayList(); public final ObservableList<Node> content = FXCollections.observableArrayList();
private boolean expanded = false; private Supplier<List<? extends Node>> lazyInitializer;
private Consumer<ComponentList> lazyInitializer;
public ComponentList() { public ComponentList() {
getStyleClass().add("options-list"); getStyleClass().add("options-list");
} }
public ComponentList(Supplier<List<? extends Node>> lazyInitializer) {
this();
this.lazyInitializer = lazyInitializer;
}
public String getTitle() { public String getTitle() {
return title.get(); return title.get();
} }
@@ -102,17 +107,12 @@ public class ComponentList extends Control {
return content; return content;
} }
public void setLazyInitializer(Consumer<ComponentList> lazyInitializer) { void doLazyInit() {
this.lazyInitializer = lazyInitializer; if (lazyInitializer != null) {
} this.getContent().setAll(lazyInitializer.get());
public void onExpand() {
if (!expanded && lazyInitializer != null) {
lazyInitializer.accept(this);
setNeedsLayout(true); setNeedsLayout(true);
lazyInitializer = null;
} }
expanded = true;
} }
@Override @Override
@@ -125,7 +125,7 @@ public class ComponentList extends Control {
return new Skin(this); return new Skin(this);
} }
protected static class Skin extends ControlSkinBase<ComponentList> { private static final class Skin extends ControlSkinBase<ComponentList> {
private static final PseudoClass PSEUDO_CLASS_FIRST = PseudoClass.getPseudoClass("first"); private static final PseudoClass PSEUDO_CLASS_FIRST = PseudoClass.getPseudoClass("first");
private static final PseudoClass PSEUDO_CLASS_LAST = PseudoClass.getPseudoClass("last"); private static final PseudoClass PSEUDO_CLASS_LAST = PseudoClass.getPseudoClass("last");
@@ -133,7 +133,7 @@ public class ComponentList extends Control {
private final ObjectBinding<Node> firstItem; private final ObjectBinding<Node> firstItem;
private final ObjectBinding<Node> lastItem; private final ObjectBinding<Node> lastItem;
protected Skin(ComponentList control) { Skin(ComponentList control) {
super(control); super(control);
list = MappedObservableList.create(control.getContent(), node -> { list = MappedObservableList.create(control.getContent(), node -> {

View File

@@ -43,7 +43,7 @@ import org.jackhuang.hmcl.ui.animation.AnimationUtils;
/** /**
* @author huangyuhui * @author huangyuhui
*/ */
class ComponentListCell extends StackPane { final class ComponentListCell extends StackPane {
private final Node content; private final Node content;
private Animation expandAnimation; private Animation expandAnimation;
private Rectangle clipRect; private Rectangle clipRect;
@@ -139,69 +139,53 @@ class ComponentListCell extends StackPane {
container.getChildren().setAll(content); container.getChildren().setAll(content);
groupNode.getChildren().add(container); groupNode.getChildren().add(container);
EventHandler<Event> onExpand; EventHandler<Event> onExpand = e -> {
if (AnimationUtils.isAnimationEnabled()) {
onExpand = e -> {
if (expandAnimation != null && expandAnimation.getStatus() == Animation.Status.RUNNING) { if (expandAnimation != null && expandAnimation.getStatus() == Animation.Status.RUNNING) {
expandAnimation.stop(); expandAnimation.stop();
} }
setExpanded(!isExpanded()); boolean expanded = !isExpanded();
setExpanded(expanded);
if (isExpanded()) { if (expanded) {
list.onExpand(); list.doLazyInit();
list.layout(); list.layout();
} }
Platform.runLater(() -> { Platform.runLater(() -> {
double newAnimatedHeight = (content.prefHeight(-1) + 8 + 10) * (isExpanded() ? 1 : -1); double newAnimatedHeight = (list.prefHeight(-1) + 8 + 10) * (expanded ? 1 : -1);
double newHeight = isExpanded() ? getHeight() + newAnimatedHeight : prefHeight(-1); double newHeight = expanded ? getHeight() + newAnimatedHeight : prefHeight(-1);
double contentHeight = isExpanded() ? newAnimatedHeight : 0; double contentHeight = expanded ? newAnimatedHeight : 0;
if (isExpanded()) { if (expanded) {
updateClip(newHeight); updateClip(newHeight);
} }
if (AnimationUtils.isAnimationEnabled()) {
expandAnimation = new Timeline(new KeyFrame(new Duration(320.0), expandAnimation = new Timeline(new KeyFrame(new Duration(320.0),
new KeyValue(container.minHeightProperty(), contentHeight, FXUtils.SINE), new KeyValue(container.minHeightProperty(), contentHeight, FXUtils.SINE),
new KeyValue(container.maxHeightProperty(), contentHeight, FXUtils.SINE) new KeyValue(container.maxHeightProperty(), contentHeight, FXUtils.SINE)
)); ));
if (!isExpanded()) { if (!expanded) {
expandAnimation.setOnFinished(e2 -> updateClip(newHeight)); expandAnimation.setOnFinished(e2 -> updateClip(newHeight));
} }
expandAnimation.play(); expandAnimation.play();
});
};
} else { } else {
onExpand = e -> {
setExpanded(!isExpanded());
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);
}
container.setMinHeight(contentHeight); container.setMinHeight(contentHeight);
container.setMaxHeight(contentHeight); container.setMaxHeight(contentHeight);
if (!isExpanded()) { if (!expanded) {
updateClip(newHeight); updateClip(newHeight);
} }
};
} }
});
};
headerRippler.setOnMouseClicked(onExpand); headerRippler.setOnMouseClicked(onExpand);
expandButton.setOnAction((EventHandler<ActionEvent>) (Object) onExpand); expandButton.setOnAction((EventHandler<ActionEvent>) (Object) onExpand);
expandedProperty().addListener((a, b, newValue) -> expandedProperty().addListener((a, b, newValue) -> expandIcon.setRotate(newValue ? 180 : 0));
expandIcon.setRotate(newValue ? 180 : 0));
getChildren().setAll(groupNode); getChildren().setAll(groupNode);
} else { } else {

View File

@@ -322,12 +322,10 @@ public class DownloadPage extends Control implements DecoratorPage {
for (String gameVersion : control.versions.keys().stream() for (String gameVersion : control.versions.keys().stream()
.sorted(VersionNumber.VERSION_COMPARATOR.reversed()) .sorted(VersionNumber.VERSION_COMPARATOR.reversed())
.collect(Collectors.toList())) { .collect(Collectors.toList())) {
ComponentList sublist = new ComponentList(); ComponentList sublist = new ComponentList(() ->
sublist.setLazyInitializer(self -> { control.versions.get(gameVersion).stream()
self.getContent().setAll(control.versions.get(gameVersion).stream()
.map(version -> new ModItem(version, control)) .map(version -> new ModItem(version, control))
.collect(Collectors.toList())); .collect(Collectors.toList()));
});
sublist.getStyleClass().add("no-padding"); sublist.getStyleClass().add("no-padding");
sublist.setTitle(gameVersion); sublist.setTitle(gameVersion);
@@ -369,6 +367,7 @@ public class DownloadPage extends Control implements DecoratorPage {
} }
private static final class ModItem extends StackPane { private static final class ModItem extends StackPane {
ModItem(RemoteMod.Version dataItem, DownloadPage selfPage) { ModItem(RemoteMod.Version dataItem, DownloadPage selfPage) {
HBox pane = new HBox(8); HBox pane = new HBox(8);
pane.setPadding(new Insets(8)); pane.setPadding(new Insets(8));
@@ -378,9 +377,7 @@ public class DownloadPage extends Control implements DecoratorPage {
JFXButton saveAsButton = new JFXButton(); JFXButton saveAsButton = new JFXButton();
RipplerContainer container = new RipplerContainer(pane); RipplerContainer container = new RipplerContainer(pane);
container.setOnMouseClicked(e -> { container.setOnMouseClicked(e -> selfPage.download(dataItem));
selfPage.download(dataItem);
});
getChildren().setAll(container); getChildren().setAll(container);
saveAsButton.getStyleClass().add("toggle-icon4"); saveAsButton.getStyleClass().add("toggle-icon4");
@@ -391,7 +388,7 @@ public class DownloadPage extends Control implements DecoratorPage {
content.setTitle(dataItem.getName()); content.setTitle(dataItem.getName());
content.setSubtitle(FORMATTER.format(dataItem.getDatePublished().toInstant())); content.setSubtitle(FORMATTER.format(dataItem.getDatePublished().toInstant()));
saveAsButton.setOnMouseClicked(e -> selfPage.saveAs(dataItem)); saveAsButton.setOnAction(e -> selfPage.saveAs(dataItem));
switch (dataItem.getVersionType()) { switch (dataItem.getVersionType()) {
case Release: case Release:
@@ -407,6 +404,9 @@ public class DownloadPage extends Control implements DecoratorPage {
content.getTags().add(i18n("version.game.snapshot")); content.getTags().add(i18n("version.game.snapshot"));
break; break;
} }
// Workaround for https://github.com/huanghongxun/HMCL/issues/2129
this.setMinHeight(50);
} }
} }