添加搜索功能

This commit is contained in:
Zkitefly
2025-01-01 05:21:31 +00:00
committed by Haowei Wen
parent d61826ba4c
commit 5197157a97

View File

@@ -21,12 +21,16 @@ import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXCheckBox;
import com.jfoenix.controls.JFXListView;
import com.jfoenix.controls.JFXSpinner;
import com.jfoenix.controls.JFXTextField;
import javafx.animation.PauseTransition;
import javafx.application.Platform;
import javafx.beans.InvalidationListener;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.layout.*;
import javafx.util.Duration;
import org.jackhuang.hmcl.download.DownloadProvider;
import org.jackhuang.hmcl.download.RemoteVersion;
import org.jackhuang.hmcl.download.VersionList;
@@ -55,14 +59,18 @@ import org.jackhuang.hmcl.ui.wizard.WizardPage;
import org.jackhuang.hmcl.util.Holder;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.function.Predicate;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static org.jackhuang.hmcl.ui.ToolbarListPageSkin.wrap;
import static org.jackhuang.hmcl.util.logging.Logger.LOG;
import static org.jackhuang.hmcl.util.i18n.I18n.formatDateTime;
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
import static org.jackhuang.hmcl.util.StringUtils.isBlank;
public final class VersionsPage extends BorderPane implements WizardPage, Refreshable {
private final String gameVersion;
@@ -86,6 +94,11 @@ public final class VersionsPage extends BorderPane implements WizardPage, Refres
private final VersionList<?> versionList;
private CompletableFuture<?> executor;
private final TransitionPane toolbarPane;
private final HBox searchBar;
private final JFXTextField searchField;
private boolean isSearching = false;
public VersionsPage(Navigation navigation, String title, String gameVersion, DownloadProvider downloadProvider, String libraryId, Runnable callback) {
this.title = title;
this.gameVersion = gameVersion;
@@ -187,6 +200,49 @@ public final class VersionsPage extends BorderPane implements WizardPage, Refres
callback.run();
});
{
toolbarPane = new TransitionPane();
searchBar = new HBox();
searchBar.setAlignment(Pos.CENTER);
searchBar.setPadding(new Insets(0, 5, 0, 5));
searchField = new JFXTextField();
searchField.setPromptText(i18n("search"));
HBox.setHgrow(searchField, Priority.ALWAYS);
JFXButton closeSearchBar = new JFXButton();
closeSearchBar.getStyleClass().add("jfx-tool-bar-button");
closeSearchBar.setGraphic(wrap(SVG.CLOSE.createIcon(Theme.blackFill(), -1, -1)));
closeSearchBar.setOnAction(e -> {
toolbarPane.setContent(checkPane, ContainerAnimations.FADE);
isSearching = false;
searchField.clear();
list.getItems().setAll(loadVersions());
});
searchBar.getChildren().setAll(searchField, closeSearchBar);
JFXButton searchButton = new JFXButton(i18n("search"));
searchButton.getStyleClass().add("jfx-tool-bar-button");
searchButton.setGraphic(wrap(SVG.MAGNIFY.createIcon(Theme.blackFill(), -1, -1)));
searchButton.setOnAction(e -> {
toolbarPane.setContent(searchBar, ContainerAnimations.FADE);
searchField.requestFocus();
});
checkPane.getChildren().add(checkPane.getChildren().size() - 1, searchButton);
centrePane.getContent().remove(checkPane);
toolbarPane.setContent(checkPane, ContainerAnimations.FADE);
centrePane.getContent().add(0, toolbarPane);
PauseTransition pause = new PauseTransition(Duration.millis(100));
pause.setOnFinished(e -> search());
searchField.textProperty().addListener((observable, oldValue, newValue) -> {
pause.setRate(1);
pause.playFromStart();
});
}
refresh();
}
@@ -265,6 +321,37 @@ public final class VersionsPage extends BorderPane implements WizardPage, Refres
FXUtils.openLink("https://bmclapidoc.bangbang93.com");
}
private void search() {
isSearching = true;
String queryString = searchField.getText();
if (isBlank(queryString)) {
list.getItems().setAll(loadVersions());
} else {
list.getItems().clear();
Predicate<String> predicate;
if (queryString.startsWith("regex:")) {
try {
Pattern pattern = Pattern.compile(queryString.substring("regex:".length()));
predicate = s -> pattern.matcher(s).find();
} catch (Throwable e) {
LOG.warning("Illegal regular expression", e);
return;
}
} else {
String lowerQueryString = queryString.toLowerCase(Locale.ROOT);
predicate = s -> s.toLowerCase(Locale.ROOT).contains(lowerQueryString);
}
for (RemoteVersion version : loadVersions()) {
if (predicate.test(version.getSelfVersion())) {
list.getItems().add(version);
}
}
}
}
private static class RemoteVersionListCell extends ListCell<RemoteVersion> {
final IconedTwoLineListItem content = new IconedTwoLineListItem();
final RipplerContainer ripplerContainer = new RipplerContainer(content);