mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2025-09-16 07:16:27 -04:00
update
This commit is contained in:
parent
394a74e566
commit
f9eca35422
@ -23,6 +23,7 @@ import javafx.beans.binding.Bindings;
|
|||||||
import javafx.beans.property.BooleanProperty;
|
import javafx.beans.property.BooleanProperty;
|
||||||
import javafx.geometry.Insets;
|
import javafx.geometry.Insets;
|
||||||
import javafx.geometry.Pos;
|
import javafx.geometry.Pos;
|
||||||
|
import javafx.scene.Node;
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
import javafx.scene.control.SelectionMode;
|
import javafx.scene.control.SelectionMode;
|
||||||
import javafx.scene.control.SkinBase;
|
import javafx.scene.control.SkinBase;
|
||||||
@ -57,18 +58,36 @@ import java.nio.file.FileSystem;
|
|||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.jackhuang.hmcl.ui.FXUtils.onEscPressed;
|
import static org.jackhuang.hmcl.ui.FXUtils.onEscPressed;
|
||||||
import static org.jackhuang.hmcl.ui.ToolbarListPageSkin.createToolbarButton2;
|
import static org.jackhuang.hmcl.ui.ToolbarListPageSkin.createToolbarButton2;
|
||||||
import static org.jackhuang.hmcl.ui.ToolbarListPageSkin.wrap;
|
|
||||||
import static org.jackhuang.hmcl.util.Lang.mapOf;
|
import static org.jackhuang.hmcl.util.Lang.mapOf;
|
||||||
|
import static org.jackhuang.hmcl.util.Logging.LOG;
|
||||||
import static org.jackhuang.hmcl.util.Pair.pair;
|
import static org.jackhuang.hmcl.util.Pair.pair;
|
||||||
import static org.jackhuang.hmcl.util.StringUtils.isNotBlank;
|
import static org.jackhuang.hmcl.util.StringUtils.isNotBlank;
|
||||||
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||||
|
|
||||||
class ModListPageSkin extends SkinBase<ModListPage> {
|
class ModListPageSkin extends SkinBase<ModListPage> {
|
||||||
|
|
||||||
|
// FXThread
|
||||||
|
private ThreadPoolExecutor searchPool;
|
||||||
|
|
||||||
|
private final TransitionPane toolbarPane;
|
||||||
|
private final HBox searchBar;
|
||||||
|
private final HBox toolbarNormal;
|
||||||
|
private final HBox toolbarSelecting;
|
||||||
|
|
||||||
|
private final JFXListView<ModInfoObject> listView;
|
||||||
|
private final JFXTextField searchField;
|
||||||
|
|
||||||
|
// FXThread
|
||||||
|
private boolean isSearching = false;
|
||||||
|
|
||||||
ModListPageSkin(ModListPage skinnable) {
|
ModListPageSkin(ModListPage skinnable) {
|
||||||
super(skinnable);
|
super(skinnable);
|
||||||
|
|
||||||
@ -78,30 +97,27 @@ class ModListPageSkin extends SkinBase<ModListPage> {
|
|||||||
|
|
||||||
ComponentList root = new ComponentList();
|
ComponentList root = new ComponentList();
|
||||||
root.getStyleClass().add("no-padding");
|
root.getStyleClass().add("no-padding");
|
||||||
JFXListView<ModInfoObject> listView = new JFXListView<>();
|
listView = new JFXListView<>();
|
||||||
|
|
||||||
{
|
{
|
||||||
TransitionPane toolBarPane = new TransitionPane();
|
toolbarPane = new TransitionPane();
|
||||||
|
|
||||||
HBox searchBar = new HBox();
|
searchBar = new HBox();
|
||||||
HBox toolbarNormal = new HBox();
|
toolbarNormal = new HBox();
|
||||||
HBox toolbarSelecting = new HBox();
|
toolbarSelecting = new HBox();
|
||||||
|
|
||||||
// Search Bar
|
// Search Bar
|
||||||
searchBar.setAlignment(Pos.CENTER);
|
searchBar.setAlignment(Pos.CENTER);
|
||||||
searchBar.setPadding(new Insets(0, 5, 0, 5));
|
searchBar.setPadding(new Insets(0, 5, 0, 5));
|
||||||
|
searchField = new JFXTextField();
|
||||||
JFXTextField searchField = new JFXTextField();
|
|
||||||
searchField.setPromptText(i18n("search"));
|
searchField.setPromptText(i18n("search"));
|
||||||
HBox.setHgrow(searchField, Priority.ALWAYS);
|
HBox.setHgrow(searchField, Priority.ALWAYS);
|
||||||
|
searchField.setOnAction(e -> search());
|
||||||
|
|
||||||
JFXButton cancel = createToolbarButton2(null, SVG::close,
|
JFXButton closeSearchBar = createToolbarButton2(null, SVG::close,
|
||||||
() -> {
|
() -> changeToolbar(toolbarNormal));
|
||||||
searchField.clear();
|
|
||||||
toolBarPane.setContent(toolbarNormal, ContainerAnimations.FADE.getAnimationProducer());
|
|
||||||
});
|
|
||||||
|
|
||||||
searchBar.getChildren().setAll(searchField, cancel);
|
searchBar.getChildren().setAll(searchField, closeSearchBar);
|
||||||
|
|
||||||
// Toolbar Normal
|
// Toolbar Normal
|
||||||
toolbarNormal.getChildren().setAll(
|
toolbarNormal.getChildren().setAll(
|
||||||
@ -110,8 +126,7 @@ class ModListPageSkin extends SkinBase<ModListPage> {
|
|||||||
createToolbarButton2(i18n("folder.mod"), SVG::folderOpen, skinnable::openModFolder),
|
createToolbarButton2(i18n("folder.mod"), SVG::folderOpen, skinnable::openModFolder),
|
||||||
createToolbarButton2(i18n("mods.check_updates"), SVG::update, skinnable::checkUpdates),
|
createToolbarButton2(i18n("mods.check_updates"), SVG::update, skinnable::checkUpdates),
|
||||||
createToolbarButton2(i18n("download"), SVG::downloadOutline, skinnable::download),
|
createToolbarButton2(i18n("download"), SVG::downloadOutline, skinnable::download),
|
||||||
createToolbarButton2(i18n("search"), SVG::magnify,
|
createToolbarButton2(i18n("search"), SVG::magnify, () -> changeToolbar(searchBar))
|
||||||
() -> toolBarPane.setContent(searchBar, ContainerAnimations.FADE.getAnimationProducer()))
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Toolbar Selecting
|
// Toolbar Selecting
|
||||||
@ -131,14 +146,14 @@ class ModListPageSkin extends SkinBase<ModListPage> {
|
|||||||
listView.getSelectionModel().clearSelection())
|
listView.getSelectionModel().clearSelection())
|
||||||
);
|
);
|
||||||
|
|
||||||
FXUtils.onChangeAndOperate(listView.getSelectionModel().selectedItemProperty(), selectedItem -> {
|
FXUtils.onChangeAndOperate(listView.getSelectionModel().selectedItemProperty(),
|
||||||
if (selectedItem == null) {
|
selectedItem -> {
|
||||||
toolBarPane.setContent(toolbarNormal, ContainerAnimations.FADE.getAnimationProducer());
|
if (selectedItem == null)
|
||||||
} else {
|
changeToolbar(isSearching ? searchBar : toolbarNormal);
|
||||||
toolBarPane.setContent(toolbarSelecting, ContainerAnimations.FADE.getAnimationProducer());
|
else
|
||||||
}
|
changeToolbar(toolbarSelecting);
|
||||||
});
|
});
|
||||||
root.getContent().add(toolBarPane);
|
root.getContent().add(toolbarPane);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -160,7 +175,6 @@ class ModListPageSkin extends SkinBase<ModListPage> {
|
|||||||
label.prefWidthProperty().bind(pane.widthProperty().add(-100));
|
label.prefWidthProperty().bind(pane.widthProperty().add(-100));
|
||||||
|
|
||||||
FXUtils.onChangeAndOperate(skinnable.moddedProperty(), modded -> {
|
FXUtils.onChangeAndOperate(skinnable.moddedProperty(), modded -> {
|
||||||
|
|
||||||
if (modded) pane.getChildren().setAll(root);
|
if (modded) pane.getChildren().setAll(root);
|
||||||
else pane.getChildren().setAll(label);
|
else pane.getChildren().setAll(label);
|
||||||
});
|
});
|
||||||
@ -168,6 +182,52 @@ class ModListPageSkin extends SkinBase<ModListPage> {
|
|||||||
getChildren().setAll(pane);
|
getChildren().setAll(pane);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void changeToolbar(HBox newToolbar) {
|
||||||
|
Node oldToolbar = toolbarPane.getCurrentNode();
|
||||||
|
if (newToolbar != oldToolbar) {
|
||||||
|
toolbarPane.setContent(newToolbar, ContainerAnimations.FADE.getAnimationProducer());
|
||||||
|
if (isSearching && newToolbar == toolbarNormal) {
|
||||||
|
isSearching = false;
|
||||||
|
searchField.clear();
|
||||||
|
Bindings.bindContent(listView.getItems(), getSkinnable().getItems());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void search() {
|
||||||
|
isSearching = true;
|
||||||
|
|
||||||
|
Bindings.unbindContent(listView.getItems(), getSkinnable().getItems());
|
||||||
|
|
||||||
|
String queryString = searchField.getText();
|
||||||
|
if (StringUtils.isBlank(queryString)) {
|
||||||
|
listView.getItems().setAll(getSkinnable().getItems());
|
||||||
|
} else {
|
||||||
|
listView.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.log(Level.WARNING, "Illegal regular expression", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
String lowerQueryString = queryString.toLowerCase(Locale.ROOT);
|
||||||
|
predicate = s -> s.toLowerCase(Locale.ROOT).contains(lowerQueryString);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do we need to search in the background thread?
|
||||||
|
for (ModInfoObject item : getSkinnable().getItems()) {
|
||||||
|
if (predicate.test(item.getModInfo().getFileName())) {
|
||||||
|
listView.getItems().add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static class ModInfoObject extends RecursiveTreeObject<ModInfoObject> implements Comparable<ModInfoObject> {
|
static class ModInfoObject extends RecursiveTreeObject<ModInfoObject> implements Comparable<ModInfoObject> {
|
||||||
private final BooleanProperty active;
|
private final BooleanProperty active;
|
||||||
private final LocalModFile localModFile;
|
private final LocalModFile localModFile;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user