diff --git a/app/src/main/java/io/xpipe/app/comp/store/StoreEntryListStatusComp.java b/app/src/main/java/io/xpipe/app/comp/store/StoreEntryListOverviewComp.java similarity index 93% rename from app/src/main/java/io/xpipe/app/comp/store/StoreEntryListStatusComp.java rename to app/src/main/java/io/xpipe/app/comp/store/StoreEntryListOverviewComp.java index 93f2655d4..4c7755431 100644 --- a/app/src/main/java/io/xpipe/app/comp/store/StoreEntryListStatusComp.java +++ b/app/src/main/java/io/xpipe/app/comp/store/StoreEntryListOverviewComp.java @@ -27,11 +27,11 @@ import javafx.scene.text.TextAlignment; import org.kordamp.ikonli.javafx.FontIcon; -public class StoreEntryListStatusComp extends SimpleComp { +public class StoreEntryListOverviewComp extends SimpleComp { private final Property sortMode; - public StoreEntryListStatusComp() { + public StoreEntryListOverviewComp() { this.sortMode = new SimpleObjectProperty<>(); StoreViewState.get().getActiveCategory().subscribe(val -> { sortMode.setValue(val.getSortMode().getValue()); @@ -110,30 +110,20 @@ public class StoreEntryListStatusComp extends SimpleComp { }); }); 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 hbox = new HBox(createButtons(), f); + var buttons = createAddButton(); + var hbox = new HBox(buttons, f); + f.prefHeightProperty().bind(buttons.heightProperty()); hbox.setSpacing(8); hbox.setAlignment(Pos.CENTER); HBox.setHgrow(f, Priority.ALWAYS); 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); return hbox; } - private Region createButtons() { + private Region createAddButton() { var menu = new MenuButton(null, new FontIcon("mdi2p-plus-thick")); menu.textProperty().bind(AppI18n.observable("addConnections")); menu.setAlignment(Pos.CENTER); diff --git a/app/src/main/java/io/xpipe/app/comp/store/StoreSidebarComp.java b/app/src/main/java/io/xpipe/app/comp/store/StoreSidebarComp.java index 6732dc091..78787f909 100644 --- a/app/src/main/java/io/xpipe/app/comp/store/StoreSidebarComp.java +++ b/app/src/main/java/io/xpipe/app/comp/store/StoreSidebarComp.java @@ -14,7 +14,7 @@ public class StoreSidebarComp extends SimpleComp { @Override protected Region createSimple() { var sideBar = new VerticalComp(List.of( - new StoreEntryListStatusComp() + new StoreEntryListOverviewComp() .styleClass("color-box") .styleClass("gray") .styleClass("bar"), diff --git a/app/src/main/java/io/xpipe/app/fxcomps/impl/DataStoreChoiceComp.java b/app/src/main/java/io/xpipe/app/fxcomps/impl/DataStoreChoiceComp.java index 846459c2b..54560b961 100644 --- a/app/src/main/java/io/xpipe/app/fxcomps/impl/DataStoreChoiceComp.java +++ b/app/src/main/java/io/xpipe/app/fxcomps/impl/DataStoreChoiceComp.java @@ -1,5 +1,7 @@ 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.store.*; 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.LocalStore; import io.xpipe.core.store.ShellStore; - import javafx.beans.binding.Bindings; import javafx.beans.property.Property; import javafx.beans.property.SimpleBooleanProperty; @@ -25,9 +26,6 @@ import javafx.scene.control.MenuButton; import javafx.scene.layout.Region; import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; - -import atlantafx.base.controls.Popover; -import atlantafx.base.theme.Styles; import lombok.RequiredArgsConstructor; import org.kordamp.ikonli.javafx.FontIcon; @@ -139,10 +137,7 @@ public class DataStoreChoiceComp extends SimpleComp { .focusedProperty() .addListener((observable, oldValue, newValue) -> { if (newValue) { - ((StackPane) struc.get().getChildren().get(1)) - .getChildren() - .get(1) - .requestFocus(); + struc.get().getChildren().get(1).requestFocus(); } }); }) diff --git a/app/src/main/java/io/xpipe/app/fxcomps/impl/FilterComp.java b/app/src/main/java/io/xpipe/app/fxcomps/impl/FilterComp.java index ec1d5561c..4aa431338 100644 --- a/app/src/main/java/io/xpipe/app/fxcomps/impl/FilterComp.java +++ b/app/src/main/java/io/xpipe/app/fxcomps/impl/FilterComp.java @@ -1,25 +1,22 @@ package io.xpipe.app.fxcomps.impl; +import atlantafx.base.controls.CustomTextField; import io.xpipe.app.core.AppActionLinkDetector; import io.xpipe.app.core.AppI18n; import io.xpipe.app.fxcomps.Comp; import io.xpipe.app.fxcomps.CompStructure; +import io.xpipe.app.fxcomps.SimpleCompStructure; import io.xpipe.app.fxcomps.util.PlatformThread; - import javafx.beans.binding.Bindings; import javafx.beans.property.Property; -import javafx.scene.Node; -import javafx.scene.control.Label; -import javafx.scene.control.TextField; -import javafx.scene.layout.StackPane; - -import lombok.Builder; -import lombok.Value; +import javafx.geometry.Pos; +import javafx.scene.Cursor; +import javafx.scene.input.MouseButton; import org.kordamp.ikonli.javafx.FontIcon; import java.util.Objects; -public class FilterComp extends Comp { +public class FilterComp extends Comp> { private final Property filterText; @@ -28,61 +25,47 @@ public class FilterComp extends Comp { } @Override - public Structure createBase() { + public CompStructure createBase() { var fi = new FontIcon("mdi2m-magnify"); - var bgLabel = new Label(null, fi); - bgLabel.textProperty().bind(AppI18n.observable("searchFilter")); - bgLabel.getStyleClass().add("filter-background"); - var filter = new TextField(); + var clear = new FontIcon("mdi2c-close"); + clear.setCursor(Cursor.DEFAULT); + clear.setOnMousePressed(event -> { + 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"); filterText.subscribe(val -> { PlatformThread.runLaterIfNeeded(() -> { + clear.setVisible(val != null); if (!Objects.equals(filter.getText(), val)) { filter.setText(val); } }); }); - filter.textProperty().addListener((observable, oldValue, newValue) -> { + + filter.textProperty().addListener((observable, oldValue, n) -> { // Handle pasted xpipe URLs - if (newValue != null && newValue.startsWith("xpipe://")) { - AppActionLinkDetector.handle(newValue, false); + if (n != null && n.startsWith("xpipe://")) { + AppActionLinkDetector.handle(n, false); filter.setText(null); return; } - filterText.setValue(newValue); + filterText.setValue(n != null && n.length() > 0 ? n : null); }); - bgLabel.visibleProperty() - .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 pane; - Node inactiveIcon; - Label inactiveText; - TextField text; - - @Override - public StackPane get() { - return pane; - } + return new SimpleCompStructure<>(filter); } } diff --git a/app/src/main/resources/io/xpipe/app/resources/style/filter-comp.css b/app/src/main/resources/io/xpipe/app/resources/style/filter-comp.css index 3b5be3cb2..331fd8c3c 100644 --- a/app/src/main/resources/io/xpipe/app/resources/style/filter-comp.css +++ b/app/src/main/resources/io/xpipe/app/resources/style/filter-comp.css @@ -1,8 +1,4 @@ -.filter-comp .text-field { +.filter-comp { -fx-padding: 0.15em 0.3em 0.15em 0.3em; -fx-background-color: transparent; } - -.filter-comp .input-line { - -fx-opacity: 0.2; -} \ No newline at end of file diff --git a/app/src/main/resources/io/xpipe/app/resources/style/header-bars.css b/app/src/main/resources/io/xpipe/app/resources/style/header-bars.css index 5c5db9593..ac16a0810 100644 --- a/app/src/main/resources/io/xpipe/app/resources/style/header-bars.css +++ b/app/src/main/resources/io/xpipe/app/resources/style/header-bars.css @@ -136,12 +136,3 @@ -fx-border-width: 0.05em; -fx-border-radius: 3px; } - - -.store-header-bar .filter-bar .filter-background { - -fx-opacity: 0.7; -} - -.filter-bar .input-line { - -fx-opacity: 0.2; -} \ No newline at end of file