Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,11 @@

import com.jfoenix.controls.JFXButton;
import javafx.beans.InvalidationListener;
import javafx.beans.binding.Bindings;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Pos;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
Expand All @@ -22,7 +18,6 @@

public class IconedTwoLineListItem extends HBox {
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 StringProperty externalLink = new SimpleStringProperty(this, "externalLink");
private final ObjectProperty<Image> image = new SimpleObjectProperty<>(this, "image");
Expand All @@ -41,7 +36,6 @@ public IconedTwoLineListItem() {
twoLineListItem.titleProperty().bind(title);
twoLineListItem.subtitleProperty().bind(subtitle);
HBox.setHgrow(twoLineListItem, Priority.ALWAYS);
Bindings.bindContent(twoLineListItem.getTags(), tags);

observer = FXUtils.observeWeak(() -> {
getChildren().clear();
Expand All @@ -63,8 +57,8 @@ public void setTitle(String title) {
this.title.set(title);
}

public ObservableList<Label> getTags() {
return tags;
public void addTags(String tag) {
twoLineListItem.addTag(tag);
}

public String getSubtitle() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,33 +18,34 @@
package org.jackhuang.hmcl.ui.construct;

import javafx.beans.binding.Bindings;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.property.*;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import org.jackhuang.hmcl.ui.FXUtils;
import org.jackhuang.hmcl.util.AggregatedObservableList;

import java.util.stream.Collectors;

import static org.jackhuang.hmcl.util.i18n.I18n.i18n;

public class TwoLineListItem extends VBox {
private static final String DEFAULT_STYLE_CLASS = "two-line-list-item";

private static Label createTagLabel(String tag) {
Label tagLabel = new Label();
tagLabel.setText(tag);
HBox.setMargin(tagLabel, new Insets(0, 8, 0, 0));
return tagLabel;
}
private static final int UNLIMITED_TAGS = -1;

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 ReadOnlyListWrapper<Tag> sourceTags = new ReadOnlyListWrapper<>(this, "sourceTags", FXCollections.observableArrayList());
private final ObservableList<Label> visibleTagLabels = FXCollections.observableArrayList();

private final AggregatedObservableList<Node> firstLineChildren;
private final IntegerProperty visibleTagLimit = new SimpleIntegerProperty(UNLIMITED_TAGS);
private final Label overflowLabel = createTagLabel("", "tag-overflow", false);

public TwoLineListItem(String titleString, String subtitleString) {
this();
Expand All @@ -54,23 +55,28 @@ public TwoLineListItem(String titleString, String subtitleString) {
}

public TwoLineListItem() {
setMouseTransparent(true);

HBox firstLine = new HBox();
firstLine.getStyleClass().add("first-line");
firstLine.setAlignment(Pos.CENTER_LEFT);

Label lblTitle = new Label();
lblTitle.getStyleClass().add("title");
lblTitle.textProperty().bind(title);
FXUtils.showTooltipWhenTruncated(lblTitle);

firstLineChildren = new AggregatedObservableList<>();
AggregatedObservableList<Node> firstLineChildren = new AggregatedObservableList<>();
firstLineChildren.appendList(FXCollections.singletonObservableList(lblTitle));
firstLineChildren.appendList(tags);
firstLineChildren.appendList(visibleTagLabels);
sourceTags.addListener((ListChangeListener<? super Tag>) this::updateVisibleTagLabels);
visibleTagLimit.addListener(observable -> rebuildVisibleTagLabels());

Bindings.bindContent(firstLine.getChildren(), firstLineChildren.getAggregatedList());

Label lblSubtitle = new Label();
lblSubtitle.getStyleClass().add("subtitle");
lblSubtitle.textProperty().bind(subtitle);
FXUtils.showTooltipWhenTruncated(lblSubtitle);

HBox secondLine = new HBox();
secondLine.getChildren().setAll(lblSubtitle);
Expand All @@ -85,6 +91,54 @@ public TwoLineListItem() {
getStyleClass().add(DEFAULT_STYLE_CLASS);
}

private void updateVisibleTagLabels(ListChangeListener.Change<? extends Tag> c) {
if (visibleTagLimit.get() == UNLIMITED_TAGS || visibleTagLabels.size() < visibleTagLimit.get()) {
while (c.next()) {
if (c.wasAdded()) {
for (Tag tag : c.getAddedSubList()) {
if (visibleTagLimit.get() != UNLIMITED_TAGS && visibleTagLabels.size() > visibleTagLimit.get()) {
break;
}
visibleTagLabels.add(createTagLabel(tag.text, tag.styleClass, true));
}
}
}
}
updateOverflowTag();
}

private void rebuildVisibleTagLabels() {
visibleTagLabels.clear();
for (Tag allTag : sourceTags) {
if (visibleTagLimit.get() != UNLIMITED_TAGS && visibleTagLabels.size() > visibleTagLimit.get()) {
break;
}
visibleTagLabels.add(createTagLabel(allTag.text, allTag.styleClass, true));
}
updateOverflowTag();
}

private void updateOverflowTag() {
if (visibleTagLimit.get() != UNLIMITED_TAGS && sourceTags.size() > visibleTagLimit.get()) {
FXUtils.installFastTooltip(overflowLabel, sourceTags.stream().skip(visibleTagLimit.get())
.map(Tag::text).collect(Collectors.joining("\n")));
overflowLabel.setText(i18n("tag.overflow", (sourceTags.size() - visibleTagLimit.get())));
if (!visibleTagLabels.contains(overflowLabel)) {
visibleTagLabels.add(overflowLabel);
}
}
}

private static Label createTagLabel(String tag, String StyleClass, Boolean showToolTipIfTruncated) {
Label tagLabel = new Label(tag);
if (showToolTipIfTruncated) {
FXUtils.showTooltipWhenTruncated(tagLabel);
}
HBox.setMargin(tagLabel, new Insets(0, 4, 0, 0));
tagLabel.getStyleClass().add(StyleClass);
return tagLabel;
}

public String getTitle() {
return title.get();
}
Expand All @@ -110,23 +164,37 @@ public void setSubtitle(String subtitle) {
}

public void addTag(String tag) {
Label tagLabel = createTagLabel(tag);
tagLabel.getStyleClass().add("tag");
getTags().add(tagLabel);
sourceTags.add(new Tag(tag, "tag"));
}

public void addTagWarning(String tag) {
Label tagLabel = createTagLabel(tag);
tagLabel.getStyleClass().add("tag-warning");
getTags().add(tagLabel);
sourceTags.add(new Tag(tag, "tag-warning"));
}

public ObservableList<Label> getTags() {
return tags;
public ReadOnlyListProperty<Tag> getTags() {
return sourceTags.getReadOnlyProperty();
}

public void setVisibleTagLimit(int visibleTagLimit) {
if (visibleTagLimit >= -1) {
this.visibleTagLimit.set(visibleTagLimit);
}
}

public IntegerProperty getVisibleTagLimit() {
return visibleTagLimit;
}

public void clearTags() {
sourceTags.clear();
visibleTagLabels.clear();
}

@Override
public String toString() {
return getTitle();
}

public record Tag(String text, String styleClass) {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ public void updateItem(RemoteVersion remoteVersion, boolean empty) {
} else {
twoLineListItem.setSubtitle(null);
}
twoLineListItem.getTags().clear();
twoLineListItem.clearTags();

if (remoteVersion instanceof GameRemoteVersion) {
RemoteVersion.Type versionType = remoteVersion.getVersionType();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,8 @@ protected void updateControl(RemoteMod dataItem, boolean empty) {
ModTranslations.Mod mod = ModTranslations.getTranslationsByRepositoryType(getSkinnable().repository.getType()).getModByCurseForgeId(dataItem.getSlug());
content.setTitle(mod != null && I18n.isUseChinese() ? mod.getDisplayName() : dataItem.getTitle());
content.setSubtitle(dataItem.getDescription());
content.getTags().clear();
content.setVisibleTagLimit(4);
content.clearTags();
dataItem.getCategories().stream()
.map(category -> getSkinnable().getLocalizedCategory(category))
.forEach(content::addTag);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ protected ModDownloadPageSkin(DownloadPage control) {
ModTranslations.Mod mod = getSkinnable().translations.getModByCurseForgeId(getSkinnable().addon.getSlug());
content.setTitle(mod != null && I18n.isUseChinese() ? mod.getDisplayName() : getSkinnable().addon.getTitle());
content.setSubtitle(getSkinnable().addon.getDescription());
content.setVisibleTagLimit(7);
getSkinnable().addon.getCategories().stream()
.map(category -> getSkinnable().page.getLocalizedCategory(category))
.forEach(content::addTag);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public GameItemSkin(GameItem skinnable) {
TwoLineListItem item = new TwoLineListItem();
item.titleProperty().bind(skinnable.titleProperty());
FXUtils.onChangeAndOperate(skinnable.tagProperty(), tag -> {
item.getTags().clear();
item.clearTags();
if (StringUtils.isNotBlank(tag))
item.addTag(tag);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,7 @@ final class ModInfoDialog extends JFXDialogLayout {
}
if (title.getTags()
.stream()
.noneMatch(it -> it.getText().equals(loaderName))) {
.noneMatch(it -> it.text().equals(loaderName))) {
title.addTag(loaderName);
}
}
Expand Down Expand Up @@ -619,7 +619,7 @@ protected void updateControl(ModInfoObject dataItem, boolean empty) {

List<String> warning = new ArrayList<>();

content.getTags().clear();
content.clearTags();

LocalModFile modInfo = dataItem.getModInfo();
ModTranslations.Mod modTranslations = dataItem.getModTranslations();
Expand Down
21 changes: 16 additions & 5 deletions HMCL/src/main/resources/assets/css/root.css
Original file line number Diff line number Diff line change
Expand Up @@ -288,17 +288,28 @@
.two-line-list-item > .first-line > .tag {
-fx-text-fill: -fx-base-color;
-fx-background-color: -fx-base-rippler-color;
-fx-padding: 2;
-fx-padding: 1 2 1 2;
-fx-font-weight: normal;
-fx-font-size: 12px;
-fx-font-size: 11px;
-fx-background-radius: 2;
}

.two-line-list-item > .first-line > .tag-warning {
-fx-text-fill: #d34336;;
-fx-text-fill: #d34336;
-fx-background-color: #f1aeb5;
-fx-padding: 2;
-fx-padding: 1 2 1 2;
-fx-font-weight: normal;
-fx-font-size: 12px;
-fx-font-size: 11px;
-fx-background-radius: 2;
}

.two-line-list-item > .first-line > .tag-overflow {
-fx-text-fill: -fx-base-color;
-fx-background-color: derive(-fx-base-rippler-color, -10%);
-fx-padding: 1 2 1 2;
-fx-font-weight: normal;
-fx-font-size: 11px;
-fx-background-radius: 2;
}

.two-line-item-second-large {
Expand Down
2 changes: 2 additions & 0 deletions HMCL/src/main/resources/assets/lang/I18N.properties
Original file line number Diff line number Diff line change
Expand Up @@ -1110,6 +1110,8 @@ datapack.choose_datapack=Choose datapack to import
datapack.extension=Datapack
datapack.title=World [%s] - Datapacks

tag.overflow=+%d more

web.failed=Failed to load page
web.open_in_browser=Do you want to open this address in a browser:\n%s
web.view_in_browser=View all in browser
Expand Down
2 changes: 2 additions & 0 deletions HMCL/src/main/resources/assets/lang/I18N_zh.properties
Original file line number Diff line number Diff line change
Expand Up @@ -907,6 +907,8 @@ datapack.choose_datapack=選取要匯入的資料包壓縮檔
datapack.extension=資料包
datapack.title=世界 [%s] - 資料包

tag.overflow=+%d 更多

web.failed=載入頁面失敗
web.open_in_browser=是否要在瀏覽器中開啟此連結:\n%s
web.view_in_browser=在瀏覽器中查看完整日誌
Expand Down
2 changes: 2 additions & 0 deletions HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties
Original file line number Diff line number Diff line change
Expand Up @@ -917,6 +917,8 @@ datapack.choose_datapack=选择要导入的数据包压缩包
datapack.extension=数据包
datapack.title=世界 [%s] - 数据包

tag.overflow=+%d 更多

web.failed=加载页面失败
web.open_in_browser=是否要在浏览器中打开此链接:\n%s
web.view_in_browser=在浏览器中查看完整日志
Expand Down