Rework filter field

This commit is contained in:
crschnick 2024-07-04 20:13:20 +00:00
parent 3ef26d0b0b
commit c1b2086e90
6 changed files with 42 additions and 87 deletions

View file

@ -27,11 +27,11 @@ import javafx.scene.text.TextAlignment;
import org.kordamp.ikonli.javafx.FontIcon; import org.kordamp.ikonli.javafx.FontIcon;
public class StoreEntryListStatusComp extends SimpleComp { public class StoreEntryListOverviewComp extends SimpleComp {
private final Property<StoreSortMode> sortMode; private final Property<StoreSortMode> sortMode;
public StoreEntryListStatusComp() { public StoreEntryListOverviewComp() {
this.sortMode = new SimpleObjectProperty<>(); this.sortMode = new SimpleObjectProperty<>();
StoreViewState.get().getActiveCategory().subscribe(val -> { StoreViewState.get().getActiveCategory().subscribe(val -> {
sortMode.setValue(val.getSortMode().getValue()); sortMode.setValue(val.getSortMode().getValue());
@ -110,30 +110,20 @@ public class StoreEntryListStatusComp extends SimpleComp {
}); });
}); });
var filter = new FilterComp(StoreViewState.get().getFilterString()); var filter = new FilterComp(StoreViewState.get().getFilterString());
filter.apply(struc -> struc.get().sceneProperty().addListener((observable, oldValue, newValue) -> {
if (newValue != null) {
struc.getText().requestFocus();
}
}));
var f = filter.createRegion(); var f = filter.createRegion();
var hbox = new HBox(createButtons(), f); var buttons = createAddButton();
var hbox = new HBox(buttons, f);
f.prefHeightProperty().bind(buttons.heightProperty());
hbox.setSpacing(8); hbox.setSpacing(8);
hbox.setAlignment(Pos.CENTER); hbox.setAlignment(Pos.CENTER);
HBox.setHgrow(f, Priority.ALWAYS); HBox.setHgrow(f, Priority.ALWAYS);
f.getStyleClass().add("filter-bar"); f.getStyleClass().add("filter-bar");
if (OsType.getLocal().equals(OsType.MACOS)) {
f.setPadding(new Insets(-2, 0, -2, 0));
} else {
f.setPadding(new Insets(-3, 0, -3, 0));
}
AppFont.medium(hbox); AppFont.medium(hbox);
return hbox; return hbox;
} }
private Region createButtons() { private Region createAddButton() {
var menu = new MenuButton(null, new FontIcon("mdi2p-plus-thick")); var menu = new MenuButton(null, new FontIcon("mdi2p-plus-thick"));
menu.textProperty().bind(AppI18n.observable("addConnections")); menu.textProperty().bind(AppI18n.observable("addConnections"));
menu.setAlignment(Pos.CENTER); menu.setAlignment(Pos.CENTER);

View file

@ -14,7 +14,7 @@ public class StoreSidebarComp extends SimpleComp {
@Override @Override
protected Region createSimple() { protected Region createSimple() {
var sideBar = new VerticalComp(List.of( var sideBar = new VerticalComp(List.of(
new StoreEntryListStatusComp() new StoreEntryListOverviewComp()
.styleClass("color-box") .styleClass("color-box")
.styleClass("gray") .styleClass("gray")
.styleClass("bar"), .styleClass("bar"),

View file

@ -1,5 +1,7 @@
package io.xpipe.app.fxcomps.impl; package io.xpipe.app.fxcomps.impl;
import atlantafx.base.controls.Popover;
import atlantafx.base.theme.Styles;
import io.xpipe.app.comp.base.ButtonComp; import io.xpipe.app.comp.base.ButtonComp;
import io.xpipe.app.comp.store.*; import io.xpipe.app.comp.store.*;
import io.xpipe.app.core.AppFont; import io.xpipe.app.core.AppFont;
@ -13,7 +15,6 @@ import io.xpipe.app.util.DataStoreCategoryChoiceComp;
import io.xpipe.core.store.DataStore; import io.xpipe.core.store.DataStore;
import io.xpipe.core.store.LocalStore; import io.xpipe.core.store.LocalStore;
import io.xpipe.core.store.ShellStore; import io.xpipe.core.store.ShellStore;
import javafx.beans.binding.Bindings; import javafx.beans.binding.Bindings;
import javafx.beans.property.Property; import javafx.beans.property.Property;
import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleBooleanProperty;
@ -25,9 +26,6 @@ import javafx.scene.control.MenuButton;
import javafx.scene.layout.Region; import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane; import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox; import javafx.scene.layout.VBox;
import atlantafx.base.controls.Popover;
import atlantafx.base.theme.Styles;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.kordamp.ikonli.javafx.FontIcon; import org.kordamp.ikonli.javafx.FontIcon;
@ -139,10 +137,7 @@ public class DataStoreChoiceComp<T extends DataStore> extends SimpleComp {
.focusedProperty() .focusedProperty()
.addListener((observable, oldValue, newValue) -> { .addListener((observable, oldValue, newValue) -> {
if (newValue) { if (newValue) {
((StackPane) struc.get().getChildren().get(1)) struc.get().getChildren().get(1).requestFocus();
.getChildren()
.get(1)
.requestFocus();
} }
}); });
}) })

View file

@ -1,25 +1,22 @@
package io.xpipe.app.fxcomps.impl; package io.xpipe.app.fxcomps.impl;
import atlantafx.base.controls.CustomTextField;
import io.xpipe.app.core.AppActionLinkDetector; import io.xpipe.app.core.AppActionLinkDetector;
import io.xpipe.app.core.AppI18n; import io.xpipe.app.core.AppI18n;
import io.xpipe.app.fxcomps.Comp; import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.fxcomps.CompStructure; import io.xpipe.app.fxcomps.CompStructure;
import io.xpipe.app.fxcomps.SimpleCompStructure;
import io.xpipe.app.fxcomps.util.PlatformThread; import io.xpipe.app.fxcomps.util.PlatformThread;
import javafx.beans.binding.Bindings; import javafx.beans.binding.Bindings;
import javafx.beans.property.Property; import javafx.beans.property.Property;
import javafx.scene.Node; import javafx.geometry.Pos;
import javafx.scene.control.Label; import javafx.scene.Cursor;
import javafx.scene.control.TextField; import javafx.scene.input.MouseButton;
import javafx.scene.layout.StackPane;
import lombok.Builder;
import lombok.Value;
import org.kordamp.ikonli.javafx.FontIcon; import org.kordamp.ikonli.javafx.FontIcon;
import java.util.Objects; import java.util.Objects;
public class FilterComp extends Comp<FilterComp.Structure> { public class FilterComp extends Comp<CompStructure<CustomTextField>> {
private final Property<String> filterText; private final Property<String> filterText;
@ -28,61 +25,47 @@ public class FilterComp extends Comp<FilterComp.Structure> {
} }
@Override @Override
public Structure createBase() { public CompStructure<CustomTextField> createBase() {
var fi = new FontIcon("mdi2m-magnify"); var fi = new FontIcon("mdi2m-magnify");
var bgLabel = new Label(null, fi); var clear = new FontIcon("mdi2c-close");
bgLabel.textProperty().bind(AppI18n.observable("searchFilter")); clear.setCursor(Cursor.DEFAULT);
bgLabel.getStyleClass().add("filter-background"); clear.setOnMousePressed(event -> {
var filter = new TextField(); if (event.getButton() == MouseButton.PRIMARY) {
filterText.setValue(null);
event.consume();
}
});
var filter = new CustomTextField();
filter.alignmentProperty().bind(Bindings.createObjectBinding(() -> {
return filter.isFocused() || (filter.getText() != null && !filter.getText().isEmpty()) ? Pos.CENTER_LEFT : Pos.CENTER;
}, filter.textProperty(), filter.focusedProperty()));
filter.setMaxHeight(2000);
filter.getStyleClass().add("filter-comp");
filter.promptTextProperty().bind(AppI18n.observable("searchFilter"));
filter.setLeft(fi);
filter.setRight(clear);
filter.setAccessibleText("Filter"); filter.setAccessibleText("Filter");
filterText.subscribe(val -> { filterText.subscribe(val -> {
PlatformThread.runLaterIfNeeded(() -> { PlatformThread.runLaterIfNeeded(() -> {
clear.setVisible(val != null);
if (!Objects.equals(filter.getText(), val)) { if (!Objects.equals(filter.getText(), val)) {
filter.setText(val); filter.setText(val);
} }
}); });
}); });
filter.textProperty().addListener((observable, oldValue, newValue) -> {
filter.textProperty().addListener((observable, oldValue, n) -> {
// Handle pasted xpipe URLs // Handle pasted xpipe URLs
if (newValue != null && newValue.startsWith("xpipe://")) { if (n != null && n.startsWith("xpipe://")) {
AppActionLinkDetector.handle(newValue, false); AppActionLinkDetector.handle(n, false);
filter.setText(null); filter.setText(null);
return; return;
} }
filterText.setValue(newValue); filterText.setValue(n != null && n.length() > 0 ? n : null);
}); });
bgLabel.visibleProperty() return new SimpleCompStructure<>(filter);
.bind(Bindings.createBooleanBinding(
() -> (filter.getText() == null || filter.getText().isEmpty()),
filter.textProperty(),
filter.focusedProperty()));
var stack = new StackPane(bgLabel, filter);
stack.getStyleClass().add("filter-comp");
stack.minWidthProperty().bind(bgLabel.prefWidthProperty());
return Structure.builder()
.inactiveIcon(fi)
.inactiveText(bgLabel)
.text(filter)
.pane(stack)
.build();
}
@Value
@Builder
public static class Structure implements CompStructure<StackPane> {
StackPane pane;
Node inactiveIcon;
Label inactiveText;
TextField text;
@Override
public StackPane get() {
return pane;
}
} }
} }

View file

@ -1,8 +1,4 @@
.filter-comp .text-field { .filter-comp {
-fx-padding: 0.15em 0.3em 0.15em 0.3em; -fx-padding: 0.15em 0.3em 0.15em 0.3em;
-fx-background-color: transparent; -fx-background-color: transparent;
} }
.filter-comp .input-line {
-fx-opacity: 0.2;
}

View file

@ -136,12 +136,3 @@
-fx-border-width: 0.05em; -fx-border-width: 0.05em;
-fx-border-radius: 3px; -fx-border-radius: 3px;
} }
.store-header-bar .filter-bar .filter-background {
-fx-opacity: 0.7;
}
.filter-bar .input-line {
-fx-opacity: 0.2;
}