Skip to content
Merged
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 @@ -25,6 +25,7 @@
import javafx.animation.PauseTransition;
import javafx.application.Platform;
import javafx.beans.InvalidationListener;
import javafx.beans.binding.Bindings;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
Expand All @@ -33,6 +34,7 @@
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.SkinBase;
import javafx.scene.image.Image;
Expand All @@ -51,7 +53,9 @@
import org.jackhuang.hmcl.ui.animation.ContainerAnimations;
import org.jackhuang.hmcl.ui.animation.TransitionPane;
import org.jackhuang.hmcl.ui.construct.*;
import org.jackhuang.hmcl.util.StringUtils;
import org.jackhuang.hmcl.util.io.CompressingUtils;
import org.jetbrains.annotations.NotNullByDefault;
import org.jetbrains.annotations.Nullable;

import java.lang.ref.SoftReference;
Expand All @@ -68,6 +72,7 @@
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
import static org.jackhuang.hmcl.util.logging.Logger.LOG;

@NotNullByDefault
final class DataPackListPageSkin extends SkinBase<DataPackListPage> {

private final TransitionPane toolbarPane;
Expand All @@ -79,10 +84,15 @@ final class DataPackListPageSkin extends SkinBase<DataPackListPage> {
private final JFXListView<DataPackInfoObject> listView;
private final FilteredList<DataPackInfoObject> filteredList;

/// Whether the search mechanism is currently active.
private final BooleanProperty isSearching = new SimpleBooleanProperty(false);
Comment thread
KSSJW marked this conversation as resolved.

private final BooleanProperty isSelecting = new SimpleBooleanProperty(false);
private final JFXTextField searchField;

/// Timer for debouncing search input to avoid executing search on every keystroke.
private final PauseTransition searchPause = new PauseTransition(Duration.millis(100));

private static final AtomicInteger lastShiftClickIndex = new AtomicInteger(-1);
final Consumer<Integer> toggleSelect;

Expand Down Expand Up @@ -148,16 +158,21 @@ final class DataPackListPageSkin extends SkinBase<DataPackListPage> {
searchField = new JFXTextField();
searchField.setPromptText(i18n("search"));
HBox.setHgrow(searchField, Priority.ALWAYS);
PauseTransition pause = new PauseTransition(Duration.millis(100));
pause.setOnFinished(e -> filteredList.setPredicate(skinnable.updateSearchPredicate(searchField.getText())));
searchPause.setOnFinished(e -> filteredList.setPredicate(skinnable.updateSearchPredicate(searchField.getText())));
searchField.textProperty().addListener((observable, oldValue, newValue) -> {
pause.setRate(1);
pause.playFromStart();
if (isSearching.get() || !StringUtils.isBlank(newValue)) {
Comment thread
KSSJW marked this conversation as resolved.
searchPause.setRate(1);
searchPause.playFromStart();
}
});
JFXButton closeSearchBar = createToolbarButton2(null, SVG.CLOSE,
() -> {
isSearching.set(false);
searchField.clear();
searchPause.stop();
Comment thread
KSSJW marked this conversation as resolved.

filteredList.setPredicate(null);

isSearching.set(false);
});
FXUtils.onEscPressed(searchField, closeSearchBar::fire);
searchBar.getChildren().addAll(searchField, closeSearchBar);
Expand Down Expand Up @@ -193,6 +208,23 @@ final class DataPackListPageSkin extends SkinBase<DataPackListPage> {

listView.setCellFactory(x -> new DataPackInfoListCell(listView, getSkinnable().readOnly));
listView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);

StackPane placeholderContainer = new StackPane();
placeholderContainer.getStyleClass().add("notice-pane");
Label placeholderLabel = new Label(i18n("datapack.empty"));
placeholderLabel.textProperty().bind(
Bindings.createStringBinding(() -> {
if (isSearching.get()) {
return i18n("search.no_results_found");
} else {
return i18n("datapack.empty");
}
},
isSearching)
);
placeholderContainer.getChildren().add(placeholderLabel);
listView.setPlaceholder(placeholderContainer);

this.listView.setItems(filteredList);
listView.getItems().addListener(listener);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import javafx.beans.binding.Bindings;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.collections.ListChangeListener;
import javafx.css.PseudoClass;
import javafx.geometry.Insets;
Expand Down Expand Up @@ -61,6 +62,7 @@
import org.jackhuang.hmcl.util.io.CompressingUtils;
import org.jackhuang.hmcl.util.io.FileUtils;
import org.jackhuang.hmcl.util.io.NetworkUtils;
import org.jetbrains.annotations.NotNullByDefault;
import org.jetbrains.annotations.Nullable;

import java.lang.ref.SoftReference;
Expand All @@ -80,6 +82,7 @@
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
import static org.jackhuang.hmcl.util.logging.Logger.LOG;

@NotNullByDefault
final class ModListPageSkin extends SkinBase<ModListPage> {

private final TransitionPane toolbarPane;
Expand All @@ -88,10 +91,14 @@ final class ModListPageSkin extends SkinBase<ModListPage> {
private final HBox toolbarSelecting;

private final JFXListView<ModInfoObject> listView;

/// Whether the search mechanism is currently active.
private final BooleanProperty isSearching = new SimpleBooleanProperty(false);

private final JFXTextField searchField;

@FXThread
private boolean isSearching = false;
/// Timer for debouncing search input to avoid executing search on every keystroke.
private final PauseTransition searchPause = new PauseTransition(Duration.millis(100));
Comment thread
KSSJW marked this conversation as resolved.

ModListPageSkin(ModListPage skinnable) {
super(skinnable);
Expand All @@ -118,19 +125,22 @@ final class ModListPageSkin extends SkinBase<ModListPage> {
searchField = new JFXTextField();
searchField.setPromptText(i18n("search"));
HBox.setHgrow(searchField, Priority.ALWAYS);
PauseTransition pause = new PauseTransition(Duration.millis(100));
pause.setOnFinished(e -> search());
searchPause.setOnFinished(e -> search());
searchField.textProperty().addListener((observable, oldValue, newValue) -> {
pause.setRate(1);
pause.playFromStart();
if (isSearching.get() || !StringUtils.isBlank(newValue)) {
searchPause.setRate(1);
searchPause.playFromStart();
}
});

JFXButton closeSearchBar = createToolbarButton2(null, SVG.CLOSE,
() -> {
changeToolbar(toolbarNormal);

isSearching = false;
searchField.clear();
searchPause.stop();

isSearching.set(false);
Bindings.bindContent(listView.getItems(), getSkinnable().getItems());
});

Expand Down Expand Up @@ -192,7 +202,7 @@ final class ModListPageSkin extends SkinBase<ModListPage> {
FXUtils.onChangeAndOperate(listView.getSelectionModel().selectedItemProperty(),
selectedItem -> {
if (selectedItem == null)
changeToolbar(isSearching ? searchBar : toolbarNormal);
changeToolbar(isSearching.get() ? searchBar : toolbarNormal);
else
changeToolbar(toolbarSelecting);
});
Expand All @@ -219,9 +229,26 @@ final class ModListPageSkin extends SkinBase<ModListPage> {

listView.setCellFactory(x -> new ModInfoListCell(listView));
listView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);

StackPane placeholderContainer = new StackPane();
placeholderContainer.getStyleClass().add("notice-pane");
Label placeholderLabel = new Label(i18n("mods.empty"));
Comment thread
KSSJW marked this conversation as resolved.
placeholderLabel.textProperty().bind(
Bindings.createStringBinding(() -> {
if (isSearching.get()) {
return i18n("search.no_results_found");
} else {
return i18n("mods.empty");
}
},
isSearching)
);
placeholderContainer.getChildren().add(placeholderLabel);
listView.setPlaceholder(placeholderContainer);

Bindings.bindContent(listView.getItems(), skinnable.getItems());
skinnable.getItems().addListener((ListChangeListener<? super ModInfoObject>) c -> {
if (isSearching) {
if (isSearching.get()) {
search();
}
});
Expand Down Expand Up @@ -264,7 +291,7 @@ private void changeToolbar(HBox newToolbar) {
}

private void search() {
isSearching = true;
isSearching.set(true);

Bindings.unbindContent(listView.getItems(), getSkinnable().getItems());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
import org.jackhuang.hmcl.util.StringUtils;
import org.jackhuang.hmcl.util.TaskCancellationAction;
import org.jackhuang.hmcl.util.io.FileUtils;
import org.jetbrains.annotations.NotNullByDefault;
import org.jetbrains.annotations.Nullable;

import java.io.IOException;
Expand Down Expand Up @@ -257,6 +258,7 @@ public void checkUpdates(Collection<ResourcePackFile> resourcePacks) {
}
}

@NotNullByDefault
private static final class ResourcePackListPageSkin extends SkinBase<ResourcePackListPage> {
private final JFXListView<ResourcePackInfoObject> listView;
private final JFXTextField searchField = new JFXTextField();
Expand All @@ -266,7 +268,11 @@ private static final class ResourcePackListPageSkin extends SkinBase<ResourcePac
private final HBox toolbarNormal = new HBox();
private final HBox toolbarSelecting = new HBox();

private boolean isSearching;
/// Whether the search mechanism is currently active.
private final BooleanProperty isSearching = new SimpleBooleanProperty(false);

/// Timer for debouncing search input to avoid executing search on every keystroke.
private final PauseTransition searchPause = new PauseTransition(Duration.millis(100));

private ResourcePackListPageSkin(ResourcePackListPage control) {
super(control);
Expand Down Expand Up @@ -309,19 +315,22 @@ private ResourcePackListPageSkin(ResourcePackListPage control) {
searchBar.setPadding(new Insets(0, 5, 0, 5));
searchField.setPromptText(i18n("search"));
HBox.setHgrow(searchField, Priority.ALWAYS);
PauseTransition pause = new PauseTransition(Duration.millis(100));
pause.setOnFinished(e -> search());
searchPause.setOnFinished(e -> search());
FXUtils.onChange(searchField.textProperty(), newValue -> {
pause.setRate(1);
pause.playFromStart();
if (isSearching.get() || !StringUtils.isBlank(newValue)) {
searchPause.setRate(1);
searchPause.playFromStart();
}
});

JFXButton closeSearchBar = createToolbarButton2(null, SVG.CLOSE,
() -> {
changeToolbar(toolbarNormal);

isSearching = false;
searchField.clear();
searchPause.stop();

isSearching.set(false);
Bindings.bindContent(listView.getItems(), getSkinnable().getItems());
});

Expand All @@ -346,7 +355,7 @@ private ResourcePackListPageSkin(ResourcePackListPage control) {
FXUtils.onChangeAndOperate(listView.getSelectionModel().selectedItemProperty(),
selectedItem -> {
if (selectedItem == null)
changeToolbar(isSearching ? searchBar : toolbarNormal);
changeToolbar(isSearching.get() ? searchBar : toolbarNormal);
else
changeToolbar(toolbarSelecting);
});
Expand All @@ -371,6 +380,23 @@ private ResourcePackListPageSkin(ResourcePackListPage control) {

listView.setCellFactory(x -> new ResourcePackListCell(listView, control));
listView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);

StackPane placeholderContainer = new StackPane();
placeholderContainer.getStyleClass().add("notice-pane");
Label placeholderLabel = new Label(i18n("resourcepack.empty"));
placeholderLabel.textProperty().bind(
Bindings.createStringBinding(() -> {
if (isSearching.get()) {
return i18n("search.no_results_found");
} else {
return i18n("resourcepack.empty");
}
},
isSearching)
);
placeholderContainer.getChildren().add(placeholderLabel);
listView.setPlaceholder(placeholderContainer);

Bindings.bindContent(listView.getItems(), control.getItems());

listView.setOnContextMenuRequested(event -> {
Expand Down Expand Up @@ -403,7 +429,7 @@ private void changeToolbar(HBox newToolbar) {
}

private void search() {
isSearching = true;
isSearching.set(true);

Bindings.unbindContent(listView.getItems(), getSkinnable().getItems());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -636,6 +636,12 @@ protected void updateItem(Item item, boolean empty) {
private final class SchematicsPageSkin extends ToolbarListPageSkin<Item, SchematicsPage> {
SchematicsPageSkin() {
super(SchematicsPage.this);

StackPane placeholderContainer = new StackPane();
placeholderContainer.getStyleClass().add("notice-pane");
Label placeholderLabel = new Label(i18n("schematics.empty"));
placeholderContainer.getChildren().add(placeholderLabel);
listView.setPlaceholder(placeholderContainer);
Comment on lines +640 to +644

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Add the required nullability default to this modified skin

AGENTS.md requires every class whose Java code is modified to be annotated with JetBrains @NotNullByDefault. SchematicsPageSkin has been modified by this placeholder setup but has no such annotation (and the same omission remains in the modified world backup/world list skins), leaving nullability implicit contrary to the repository requirement.

Useful? React with 👍 / 👎.

}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.Control;
import javafx.scene.control.Label;
import javafx.scene.control.Skin;
import javafx.scene.control.SkinBase;
import javafx.scene.layout.BorderPane;
Expand Down Expand Up @@ -162,6 +163,12 @@ private final class WorldBackupsPageSkin extends ToolbarListPageSkin<BackupInfo,

WorldBackupsPageSkin() {
super(WorldBackupsPage.this);

StackPane placeholderContainer = new StackPane();
placeholderContainer.getStyleClass().add("notice-pane");
Label placeholderLabel = new Label(i18n("world.backup.empty"));
placeholderContainer.getChildren().add(placeholderLabel);
listView.setPlaceholder(placeholderContainer);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.Skin;
import javafx.scene.control.Tooltip;
Expand Down Expand Up @@ -216,6 +217,12 @@ private final class WorldListPageSkin extends ToolbarListPageSkin<World, WorldLi

WorldListPageSkin() {
super(WorldListPage.this);

StackPane placeholderContainer = new StackPane();
placeholderContainer.getStyleClass().add("notice-pane");
Label placeholderLabel = new Label(i18n("world.empty"));
placeholderContainer.getChildren().add(placeholderLabel);
listView.setPlaceholder(placeholderContainer);
}

@Override
Expand Down
Loading
Loading