优化 TwoLineListItem (#5447)
This commit is contained in:
@@ -18,126 +18,166 @@
|
|||||||
package org.jackhuang.hmcl.ui.construct;
|
package org.jackhuang.hmcl.ui.construct;
|
||||||
|
|
||||||
import javafx.beans.binding.Bindings;
|
import javafx.beans.binding.Bindings;
|
||||||
import javafx.beans.property.SimpleStringProperty;
|
|
||||||
import javafx.beans.property.StringProperty;
|
import javafx.beans.property.StringProperty;
|
||||||
|
import javafx.beans.property.StringPropertyBase;
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
import javafx.geometry.Insets;
|
|
||||||
import javafx.scene.Node;
|
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
import javafx.scene.layout.HBox;
|
import javafx.scene.layout.HBox;
|
||||||
import javafx.scene.layout.VBox;
|
import javafx.scene.layout.VBox;
|
||||||
import org.jackhuang.hmcl.ui.FXUtils;
|
|
||||||
import org.jackhuang.hmcl.util.AggregatedObservableList;
|
|
||||||
|
|
||||||
public class TwoLineListItem extends VBox {
|
public class TwoLineListItem extends VBox {
|
||||||
private static final String DEFAULT_STYLE_CLASS = "two-line-list-item";
|
private static final String DEFAULT_STYLE_CLASS = "two-line-list-item";
|
||||||
|
|
||||||
private static Label createTagLabel(String tag) {
|
private final HBox firstLine;
|
||||||
Label tagLabel = new Label();
|
private HBox secondLine;
|
||||||
tagLabel.setText(tag);
|
|
||||||
HBox.setMargin(tagLabel, new Insets(0, 8, 0, 0));
|
|
||||||
return tagLabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final StringProperty title = new SimpleStringProperty(this, "title");
|
|
||||||
private final ObservableList<Label> tags = FXCollections.observableArrayList();
|
|
||||||
private final StringProperty subtitle = new SimpleStringProperty(this, "subtitle");
|
|
||||||
|
|
||||||
private final Label lblSubtitle;
|
|
||||||
private final Label lblTitle;
|
private final Label lblTitle;
|
||||||
|
private Label lblSubtitle;
|
||||||
|
|
||||||
private final AggregatedObservableList<Node> firstLineChildren;
|
public TwoLineListItem() {
|
||||||
|
getStyleClass().add(DEFAULT_STYLE_CLASS);
|
||||||
|
setMouseTransparent(true);
|
||||||
|
|
||||||
|
lblTitle = new Label();
|
||||||
|
lblTitle.getStyleClass().add("title");
|
||||||
|
|
||||||
|
this.firstLine = new HBox(lblTitle);
|
||||||
|
firstLine.getStyleClass().add("first-line");
|
||||||
|
|
||||||
|
this.getChildren().setAll(firstLine);
|
||||||
|
}
|
||||||
|
|
||||||
public TwoLineListItem(String titleString, String subtitleString) {
|
public TwoLineListItem(String titleString, String subtitleString) {
|
||||||
this();
|
this();
|
||||||
|
|
||||||
title.set(titleString);
|
setTitle(titleString);
|
||||||
subtitle.set(subtitleString);
|
setSubtitle(subtitleString);
|
||||||
}
|
}
|
||||||
|
|
||||||
public TwoLineListItem() {
|
private void initSecondLine() {
|
||||||
setMouseTransparent(true);
|
if (secondLine == null) {
|
||||||
|
|
||||||
HBox firstLine = new HBox();
|
|
||||||
firstLine.getStyleClass().add("first-line");
|
|
||||||
|
|
||||||
lblTitle = new Label();
|
|
||||||
lblTitle.getStyleClass().add("title");
|
|
||||||
lblTitle.textProperty().bind(title);
|
|
||||||
|
|
||||||
firstLineChildren = new AggregatedObservableList<>();
|
|
||||||
firstLineChildren.appendList(FXCollections.singletonObservableList(lblTitle));
|
|
||||||
firstLineChildren.appendList(tags);
|
|
||||||
Bindings.bindContent(firstLine.getChildren(), firstLineChildren.getAggregatedList());
|
|
||||||
|
|
||||||
lblSubtitle = new Label();
|
lblSubtitle = new Label();
|
||||||
lblSubtitle.getStyleClass().add("subtitle");
|
lblSubtitle.getStyleClass().add("subtitle");
|
||||||
lblSubtitle.textProperty().bind(subtitle);
|
|
||||||
|
|
||||||
HBox secondLine = new HBox();
|
secondLine = new HBox(lblSubtitle);
|
||||||
secondLine.getChildren().setAll(lblSubtitle);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
getChildren().setAll(firstLine, secondLine);
|
private final StringProperty title = new StringPropertyBase() {
|
||||||
|
@Override
|
||||||
|
public Object getBean() {
|
||||||
|
return TwoLineListItem.this;
|
||||||
|
}
|
||||||
|
|
||||||
FXUtils.onChangeAndOperate(subtitle, subtitleString -> {
|
@Override
|
||||||
if (subtitleString == null) getChildren().setAll(firstLine);
|
public String getName() {
|
||||||
else getChildren().setAll(firstLine, secondLine);
|
return "title";
|
||||||
});
|
}
|
||||||
|
|
||||||
getStyleClass().add(DEFAULT_STYLE_CLASS);
|
@Override
|
||||||
|
protected void invalidated() {
|
||||||
|
lblTitle.setText(get());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public StringProperty titleProperty() {
|
||||||
|
return title;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getTitle() {
|
public String getTitle() {
|
||||||
return title.get();
|
return title.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public StringProperty titleProperty() {
|
|
||||||
return title;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTitle(String title) {
|
public void setTitle(String title) {
|
||||||
this.title.set(title);
|
this.title.set(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSubtitle() {
|
private StringProperty subtitle;
|
||||||
return subtitle.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
public StringProperty subtitleProperty() {
|
public StringProperty subtitleProperty() {
|
||||||
|
if (subtitle == null) {
|
||||||
|
subtitle = new StringPropertyBase() {
|
||||||
|
@Override
|
||||||
|
public Object getBean() {
|
||||||
|
return TwoLineListItem.this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "subtitle";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void invalidated() {
|
||||||
|
String subtitle = get();
|
||||||
|
|
||||||
|
if (subtitle != null) {
|
||||||
|
initSecondLine();
|
||||||
|
lblSubtitle.setText(subtitle);
|
||||||
|
|
||||||
|
if (getChildren().size() == 1)
|
||||||
|
getChildren().add(secondLine);
|
||||||
|
} else if (secondLine != null) {
|
||||||
|
lblSubtitle.setText(null);
|
||||||
|
if (getChildren().size() > 1)
|
||||||
|
getChildren().setAll(firstLine);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
return subtitle;
|
return subtitle;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSubtitle(String subtitle) {
|
public String getSubtitle() {
|
||||||
this.subtitle.set(subtitle);
|
return subtitle != null ? subtitleProperty().get() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Label getSubtitleLabel() {
|
public void setSubtitle(String subtitle) {
|
||||||
return lblSubtitle;
|
if (this.subtitle == null && subtitle == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
subtitleProperty().set(subtitle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Label getTitleLabel() {
|
public Label getTitleLabel() {
|
||||||
return lblTitle;
|
return lblTitle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Label getSubtitleLabel() {
|
||||||
|
initSecondLine();
|
||||||
|
return lblSubtitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ObservableList<Label> tags;
|
||||||
|
|
||||||
|
public ObservableList<Label> getTags() {
|
||||||
|
if (tags == null) {
|
||||||
|
tags = FXCollections.observableArrayList();
|
||||||
|
|
||||||
|
var tagsBox = new HBox(8);
|
||||||
|
tagsBox.getStyleClass().add("tags");
|
||||||
|
Bindings.bindContent(tagsBox.getChildren(), tags);
|
||||||
|
|
||||||
|
firstLine.getChildren().setAll(lblTitle, tagsBox);
|
||||||
|
}
|
||||||
|
return tags;
|
||||||
|
}
|
||||||
|
|
||||||
public void addTag(String tag) {
|
public void addTag(String tag) {
|
||||||
Label tagLabel = createTagLabel(tag);
|
var tagLabel = new Label(tag);
|
||||||
tagLabel.getStyleClass().add("tag");
|
tagLabel.getStyleClass().add("tag");
|
||||||
getTags().add(tagLabel);
|
getTags().add(tagLabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addTagWarning(String tag) {
|
public void addTagWarning(String tag) {
|
||||||
Label tagLabel = createTagLabel(tag);
|
var tagLabel = new Label(tag);
|
||||||
tagLabel.getStyleClass().add("tag-warning");
|
tagLabel.getStyleClass().add("tag-warning");
|
||||||
getTags().add(tagLabel);
|
getTags().add(tagLabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ObservableList<Label> getTags() {
|
|
||||||
return tags;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return getTitle();
|
return "TwoLineListItem[title=%s, subtitle=%s, tags=%s]".formatted(getTitle(), getSubtitle(), tags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -324,7 +324,7 @@
|
|||||||
-fx-fill: -monet-on-surface-variant;
|
-fx-fill: -monet-on-surface-variant;
|
||||||
}
|
}
|
||||||
|
|
||||||
.two-line-list-item > .first-line > .tag {
|
.two-line-list-item > .first-line > .tags > .tag {
|
||||||
-fx-text-fill: -monet-on-secondary-container;
|
-fx-text-fill: -monet-on-secondary-container;
|
||||||
-fx-background-color: -monet-secondary-container;
|
-fx-background-color: -monet-secondary-container;
|
||||||
-fx-padding: 2;
|
-fx-padding: 2;
|
||||||
@@ -332,7 +332,7 @@
|
|||||||
-fx-font-size: 12px;
|
-fx-font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.two-line-list-item > .first-line > .tag-warning {
|
.two-line-list-item > .first-line > .tags > .tag-warning {
|
||||||
-fx-text-fill: -monet-on-error-container;
|
-fx-text-fill: -monet-on-error-container;
|
||||||
-fx-background-color: -fixed-warning-tag-background;
|
-fx-background-color: -fixed-warning-tag-background;
|
||||||
-fx-padding: 2;
|
-fx-padding: 2;
|
||||||
|
|||||||
Reference in New Issue
Block a user