From cd2933eef82eadbc3aa3a8dd0ed47db51f518afd Mon Sep 17 00:00:00 2001 From: crschnick Date: Thu, 4 Apr 2024 06:32:11 +0000 Subject: [PATCH] Rework bindings --- .../io/xpipe/app/browser/BrowserComp.java | 7 +- .../app/browser/BrowserFileListComp.java | 5 +- .../app/browser/BrowserFileListModel.java | 4 +- .../xpipe/app/browser/BrowserFilterComp.java | 4 +- .../app/browser/BrowserGreetingComp.java | 5 +- .../io/xpipe/app/browser/BrowserModel.java | 4 +- .../app/browser/BrowserOverviewComp.java | 4 +- .../app/browser/BrowserSelectionListComp.java | 4 +- .../app/browser/BrowserStatusBarComp.java | 8 +- .../app/browser/BrowserTransferComp.java | 14 +- .../xpipe/app/browser/BrowserWelcomeComp.java | 5 +- .../xpipe/app/browser/OpenFileSystemComp.java | 3 +- .../xpipe/app/browser/action/LeafAction.java | 4 +- .../java/io/xpipe/app/comp/AppLayoutComp.java | 8 +- .../io/xpipe/app/comp/base/DropdownComp.java | 4 +- .../io/xpipe/app/comp/base/FontIconComp.java | 8 +- .../xpipe/app/comp/base/ListBoxViewComp.java | 4 +- .../xpipe/app/comp/base/MultiContentComp.java | 8 +- .../io/xpipe/app/comp/base/OsLogoComp.java | 4 +- .../xpipe/app/comp/base/SideMenuBarComp.java | 14 +- .../xpipe/app/comp/base/StoreToggleComp.java | 5 +- .../xpipe/app/comp/base/TileButtonComp.java | 5 +- .../xpipe/app/comp/store/StoreEntryComp.java | 10 +- .../app/comp/store/StoreEntryListComp.java | 9 +- .../comp/store/StoreEntryListStatusComp.java | 11 +- .../io/xpipe/app/comp/store/StoreSection.java | 21 +- .../app/comp/store/StoreSectionComp.java | 21 +- .../app/comp/store/StoreSectionMiniComp.java | 15 +- .../xpipe/app/comp/store/StoreViewState.java | 4 +- .../java/io/xpipe/app/core/AppGreetings.java | 3 +- .../main/java/io/xpipe/app/core/AppI18n.java | 4 +- .../io/xpipe/app/core/AppLayoutModel.java | 9 +- .../main/java/io/xpipe/app/fxcomps/Comp.java | 10 +- .../io/xpipe/app/fxcomps/impl/ChoiceComp.java | 4 +- .../ContextualFileReferenceChoiceComp.java | 7 +- .../fxcomps/impl/DataStoreFlowChoiceComp.java | 6 +- .../io/xpipe/app/fxcomps/impl/LabelComp.java | 1 - .../app/fxcomps/impl/StoreCategoryComp.java | 9 +- ...ooltipAugment.java => TooltipAugment.java} | 11 +- .../app/fxcomps/util/BindingsHelper.java | 292 +----------------- .../app/fxcomps/util/ListBindingsHelper.java | 190 ++++++++++++ .../app/fxcomps/util/PlatformThread.java | 2 - .../io/xpipe/app/prefs/TerminalCategory.java | 5 +- 43 files changed, 340 insertions(+), 435 deletions(-) rename app/src/main/java/io/xpipe/app/fxcomps/impl/{FancyTooltipAugment.java => TooltipAugment.java} (76%) create mode 100644 app/src/main/java/io/xpipe/app/fxcomps/util/ListBindingsHelper.java diff --git a/app/src/main/java/io/xpipe/app/browser/BrowserComp.java b/app/src/main/java/io/xpipe/app/browser/BrowserComp.java index 5e28faaae..a47ccf43c 100644 --- a/app/src/main/java/io/xpipe/app/browser/BrowserComp.java +++ b/app/src/main/java/io/xpipe/app/browser/BrowserComp.java @@ -8,10 +8,9 @@ import io.xpipe.app.comp.base.SideSplitPaneComp; import io.xpipe.app.core.AppLayoutModel; import io.xpipe.app.fxcomps.Comp; import io.xpipe.app.fxcomps.SimpleComp; -import io.xpipe.app.fxcomps.impl.FancyTooltipAugment; import io.xpipe.app.fxcomps.impl.PrettyImageHelper; +import io.xpipe.app.fxcomps.impl.TooltipAugment; import io.xpipe.app.fxcomps.impl.VerticalComp; -import io.xpipe.app.fxcomps.util.BindingsHelper; import io.xpipe.app.fxcomps.util.PlatformThread; import io.xpipe.app.storage.DataStorage; import io.xpipe.app.util.BooleanScope; @@ -122,7 +121,7 @@ public class BrowserComp extends SimpleComp { private Comp createTabs() { var multi = new MultiContentComp(Map., ObservableValue>of( Comp.of(() -> createTabPane()), - BindingsHelper.persist(Bindings.isNotEmpty(model.getOpenFileSystems())), + Bindings.isNotEmpty(model.getOpenFileSystems()), new BrowserWelcomeComp(model).apply(struc -> StackPane.setAlignment(struc.get(), Pos.CENTER_LEFT)), Bindings.createBooleanBinding( () -> { @@ -292,7 +291,7 @@ public class BrowserComp extends SimpleComp { if (color != null) { c.getStyleClass().add(color.getId()); } - new FancyTooltipAugment<>(new SimpleStringProperty(model.getTooltip())).augment(c); + new TooltipAugment<>(new SimpleStringProperty(model.getTooltip())).augment(c); c.addEventHandler( DragEvent.DRAG_ENTERED, mouseEvent -> Platform.runLater( diff --git a/app/src/main/java/io/xpipe/app/browser/BrowserFileListComp.java b/app/src/main/java/io/xpipe/app/browser/BrowserFileListComp.java index f26090f42..8aa86b7be 100644 --- a/app/src/main/java/io/xpipe/app/browser/BrowserFileListComp.java +++ b/app/src/main/java/io/xpipe/app/browser/BrowserFileListComp.java @@ -9,7 +9,6 @@ import io.xpipe.app.fxcomps.SimpleComp; import io.xpipe.app.fxcomps.SimpleCompStructure; import io.xpipe.app.fxcomps.augment.ContextMenuAugment; import io.xpipe.app.fxcomps.impl.PrettyImageHelper; -import io.xpipe.app.fxcomps.util.BindingsHelper; import io.xpipe.app.fxcomps.util.PlatformThread; import io.xpipe.app.util.BooleanScope; import io.xpipe.app.util.HumanReadableFormat; @@ -505,7 +504,7 @@ final class BrowserFileListComp extends SimpleComp { .get(); var quickAccess = new BrowserQuickAccessButtonComp( () -> getTableRow().getItem(), fileList.getFileSystemModel()) - .hide(BindingsHelper.persist(Bindings.createBooleanBinding( + .hide(Bindings.createBooleanBinding( () -> { var item = getTableRow().getItem(); var notDir = item.getRawFileEntry().resolved().getKind() != FileKind.DIRECTORY; @@ -514,7 +513,7 @@ final class BrowserFileListComp extends SimpleComp { .equals(fileList.getFileSystemModel().getCurrentParentDirectory()); return notDir || isParentLink; }, - itemProperty()))) + itemProperty()).not().not()) .createRegion(); editing.addListener((observable, oldValue, newValue) -> { diff --git a/app/src/main/java/io/xpipe/app/browser/BrowserFileListModel.java b/app/src/main/java/io/xpipe/app/browser/BrowserFileListModel.java index ac21ec5d2..7e7ae8232 100644 --- a/app/src/main/java/io/xpipe/app/browser/BrowserFileListModel.java +++ b/app/src/main/java/io/xpipe/app/browser/BrowserFileListModel.java @@ -1,6 +1,6 @@ package io.xpipe.app.browser; -import io.xpipe.app.fxcomps.util.BindingsHelper; +import io.xpipe.app.fxcomps.util.ListBindingsHelper; import io.xpipe.app.issue.ErrorEvent; import io.xpipe.core.store.FileKind; import io.xpipe.core.store.FileNames; @@ -33,7 +33,7 @@ public final class BrowserFileListModel { private final ObservableList previousSelection = FXCollections.observableArrayList(); private final ObservableList selection = FXCollections.observableArrayList(); private final ObservableList selectedRaw = - BindingsHelper.mappedContentBinding(selection, entry -> entry.getRawFileEntry()); + ListBindingsHelper.mappedContentBinding(selection, entry -> entry.getRawFileEntry()); private final Property draggedOverDirectory = new SimpleObjectProperty<>(); private final Property draggedOverEmpty = new SimpleBooleanProperty(); diff --git a/app/src/main/java/io/xpipe/app/browser/BrowserFilterComp.java b/app/src/main/java/io/xpipe/app/browser/BrowserFilterComp.java index d702ae9eb..839a393fa 100644 --- a/app/src/main/java/io/xpipe/app/browser/BrowserFilterComp.java +++ b/app/src/main/java/io/xpipe/app/browser/BrowserFilterComp.java @@ -3,7 +3,7 @@ package io.xpipe.app.browser; import atlantafx.base.theme.Styles; import io.xpipe.app.fxcomps.Comp; import io.xpipe.app.fxcomps.CompStructure; -import io.xpipe.app.fxcomps.impl.FancyTooltipAugment; +import io.xpipe.app.fxcomps.impl.TooltipAugment; import io.xpipe.app.fxcomps.impl.TextFieldComp; import javafx.beans.property.Property; import javafx.beans.property.SimpleBooleanProperty; @@ -28,7 +28,7 @@ public class BrowserFilterComp extends Comp { var expanded = new SimpleBooleanProperty(); var text = new TextFieldComp(filterString, false).createRegion(); var button = new Button(); - new FancyTooltipAugment<>("app.search").augment(button); + new TooltipAugment<>("app.search").augment(button); text.focusedProperty().addListener((observable, oldValue, newValue) -> { if (!newValue && filterString.getValue() == null) { if (button.isFocused()) { diff --git a/app/src/main/java/io/xpipe/app/browser/BrowserGreetingComp.java b/app/src/main/java/io/xpipe/app/browser/BrowserGreetingComp.java index 009382a98..2041ce02f 100644 --- a/app/src/main/java/io/xpipe/app/browser/BrowserGreetingComp.java +++ b/app/src/main/java/io/xpipe/app/browser/BrowserGreetingComp.java @@ -4,6 +4,7 @@ import atlantafx.base.theme.Styles; import io.xpipe.app.core.AppFont; import io.xpipe.app.core.AppLayoutModel; import io.xpipe.app.fxcomps.SimpleComp; +import io.xpipe.app.fxcomps.util.PlatformThread; import javafx.scene.control.Label; import javafx.scene.layout.Region; @@ -15,7 +16,9 @@ public class BrowserGreetingComp extends SimpleComp { protected Region createSimple() { var r = new Label(getText()); AppLayoutModel.get().getSelected().addListener((observableValue, entry, t1) -> { - r.setText(getText()); + PlatformThread.runLaterIfNeeded(() -> { + r.setText(getText()); + }); }); AppFont.setSize(r, 7); r.getStyleClass().add(Styles.TEXT_BOLD); diff --git a/app/src/main/java/io/xpipe/app/browser/BrowserModel.java b/app/src/main/java/io/xpipe/app/browser/BrowserModel.java index 51b3d8be4..0d3737320 100644 --- a/app/src/main/java/io/xpipe/app/browser/BrowserModel.java +++ b/app/src/main/java/io/xpipe/app/browser/BrowserModel.java @@ -3,7 +3,7 @@ package io.xpipe.app.browser; import io.xpipe.app.browser.icon.BrowserIconDirectoryType; import io.xpipe.app.browser.icon.BrowserIconFileType; import io.xpipe.app.browser.icon.FileIconManager; -import io.xpipe.app.fxcomps.util.BindingsHelper; +import io.xpipe.app.fxcomps.util.ListBindingsHelper; import io.xpipe.app.storage.DataStorage; import io.xpipe.app.storage.DataStoreEntryRef; import io.xpipe.app.util.BooleanScope; @@ -50,7 +50,7 @@ public class BrowserModel { return; } - BindingsHelper.bindContent(selection, newValue.getFileList().getSelection()); + ListBindingsHelper.bindContent(selection, newValue.getFileList().getSelection()); }); } diff --git a/app/src/main/java/io/xpipe/app/browser/BrowserOverviewComp.java b/app/src/main/java/io/xpipe/app/browser/BrowserOverviewComp.java index 4622876b7..a545860ce 100644 --- a/app/src/main/java/io/xpipe/app/browser/BrowserOverviewComp.java +++ b/app/src/main/java/io/xpipe/app/browser/BrowserOverviewComp.java @@ -4,7 +4,7 @@ import io.xpipe.app.comp.base.SimpleTitledPaneComp; import io.xpipe.app.core.AppI18n; import io.xpipe.app.fxcomps.SimpleComp; import io.xpipe.app.fxcomps.impl.VerticalComp; -import io.xpipe.app.fxcomps.util.BindingsHelper; +import io.xpipe.app.fxcomps.util.ListBindingsHelper; import io.xpipe.app.issue.ErrorEvent; import io.xpipe.app.util.ThreadHelper; import io.xpipe.core.process.ShellControl; @@ -66,7 +66,7 @@ public class BrowserOverviewComp extends SimpleComp { var rootsOverview = new BrowserFileOverviewComp(model, FXCollections.observableArrayList(roots), false); var rootsPane = new SimpleTitledPaneComp(AppI18n.observable("roots"), rootsOverview); - var recent = BindingsHelper.mappedContentBinding( + var recent = ListBindingsHelper.mappedContentBinding( model.getSavedState().getRecentDirectories(), s -> FileSystem.FileEntry.ofDirectory(model.getFileSystem(), s.getDirectory())); var recentOverview = new BrowserFileOverviewComp(model, recent, true); diff --git a/app/src/main/java/io/xpipe/app/browser/BrowserSelectionListComp.java b/app/src/main/java/io/xpipe/app/browser/BrowserSelectionListComp.java index cee9a506b..e339be87a 100644 --- a/app/src/main/java/io/xpipe/app/browser/BrowserSelectionListComp.java +++ b/app/src/main/java/io/xpipe/app/browser/BrowserSelectionListComp.java @@ -52,9 +52,9 @@ public class BrowserSelectionListComp extends SimpleComp { protected Region createSimple() { var c = new ListBoxViewComp<>(list, list, entry -> { return Comp.of(() -> { - var wv = PrettyImageHelper.ofFixedSizeSquare(FileIconManager.getFileIcon(entry, false), 20) + var image = PrettyImageHelper.ofFixedSizeSquare(FileIconManager.getFileIcon(entry, false), 24) .createRegion(); - var l = new Label(null, wv); + var l = new Label(null, image); l.setTextOverrun(OverrunStyle.CENTER_ELLIPSIS); l.textProperty().bind(PlatformThread.sync(nameTransformation.apply(entry))); return l; diff --git a/app/src/main/java/io/xpipe/app/browser/BrowserStatusBarComp.java b/app/src/main/java/io/xpipe/app/browser/BrowserStatusBarComp.java index 963334774..39e2b0e30 100644 --- a/app/src/main/java/io/xpipe/app/browser/BrowserStatusBarComp.java +++ b/app/src/main/java/io/xpipe/app/browser/BrowserStatusBarComp.java @@ -59,7 +59,7 @@ public class BrowserStatusBarComp extends SimpleComp { private Comp createClipboardStatus() { var cc = BrowserClipboard.currentCopyClipboard; - var ccCount = (BindingsHelper.persist(Bindings.createStringBinding( + var ccCount = Bindings.createStringBinding( () -> { if (cc.getValue() != null && cc.getValue().getEntries().size() > 0) { return cc.getValue().getEntries().size() + " file" @@ -68,7 +68,7 @@ public class BrowserStatusBarComp extends SimpleComp { return null; } }, - cc))); + cc); return new LabelComp(ccCount); } @@ -86,7 +86,7 @@ public class BrowserStatusBarComp extends SimpleComp { .count(); }, model.getFileList().getAll()); - var selectedComp = new LabelComp(BindingsHelper.persist(Bindings.createStringBinding( + var selectedComp = new LabelComp(Bindings.createStringBinding( () -> { if (selectedCount.getValue().intValue() == 0) { return null; @@ -95,7 +95,7 @@ public class BrowserStatusBarComp extends SimpleComp { } }, selectedCount, - allCount))); + allCount)); return selectedComp; } diff --git a/app/src/main/java/io/xpipe/app/browser/BrowserTransferComp.java b/app/src/main/java/io/xpipe/app/browser/BrowserTransferComp.java index 29b9b2c37..5955f3bbe 100644 --- a/app/src/main/java/io/xpipe/app/browser/BrowserTransferComp.java +++ b/app/src/main/java/io/xpipe/app/browser/BrowserTransferComp.java @@ -6,7 +6,7 @@ import io.xpipe.app.fxcomps.Comp; import io.xpipe.app.fxcomps.SimpleComp; import io.xpipe.app.fxcomps.augment.DragOverPseudoClassAugment; import io.xpipe.app.fxcomps.impl.*; -import io.xpipe.app.fxcomps.util.BindingsHelper; +import io.xpipe.app.fxcomps.util.ListBindingsHelper; import io.xpipe.app.fxcomps.util.PlatformThread; import io.xpipe.app.storage.DataStorage; import io.xpipe.core.process.OsType; @@ -39,11 +39,11 @@ public class BrowserTransferComp extends SimpleComp { protected Region createSimple() { var background = new LabelComp(AppI18n.observable("transferDescription")) .apply(struc -> struc.get().setGraphic(new FontIcon("mdi2d-download-outline"))) - .visible(BindingsHelper.persist(Bindings.isEmpty(model.getItems()))); + .visible(Bindings.isEmpty(model.getItems())); var backgroundStack = new StackComp(List.of(background)).grow(true, true).styleClass("download-background"); - var binding = BindingsHelper.mappedContentBinding(model.getItems(), item -> item.getFileEntry()); + var binding = ListBindingsHelper.mappedContentBinding(model.getItems(), item -> item.getFileEntry()); var list = new BrowserSelectionListComp( binding, entry -> Bindings.createStringBinding( @@ -70,20 +70,20 @@ public class BrowserTransferComp extends SimpleComp { .flatMap(aBoolean -> aBoolean ? AppI18n.observable("dragLocalFiles") : AppI18n.observable("dragFiles"))) .apply(struc -> struc.get().setGraphic(new FontIcon("mdi2h-hand-left"))) - .hide(PlatformThread.sync(BindingsHelper.persist(Bindings.isEmpty(model.getItems())))) + .hide(PlatformThread.sync(Bindings.isEmpty(model.getItems()))) .grow(true, false) .apply(struc -> struc.get().setPadding(new Insets(8))); var downloadButton = new IconButtonComp("mdi2d-download", () -> { model.download(); }) - .hide(BindingsHelper.persist(Bindings.isEmpty(model.getItems()))) + .hide(Bindings.isEmpty(model.getItems())) .disable(PlatformThread.sync(model.getAllDownloaded())) - .apply(new FancyTooltipAugment<>("downloadStageDescription")); + .apply(new TooltipAugment<>("downloadStageDescription")); var clearButton = new IconButtonComp("mdi2c-close", () -> { model.clear(); }) - .hide(BindingsHelper.persist(Bindings.isEmpty(model.getItems()))); + .hide(Bindings.isEmpty(model.getItems())); var clearPane = Comp.derive( new HorizontalComp(List.of(downloadButton, clearButton)) .apply(struc -> struc.get().setSpacing(10)), diff --git a/app/src/main/java/io/xpipe/app/browser/BrowserWelcomeComp.java b/app/src/main/java/io/xpipe/app/browser/BrowserWelcomeComp.java index e4418f07d..a652dda26 100644 --- a/app/src/main/java/io/xpipe/app/browser/BrowserWelcomeComp.java +++ b/app/src/main/java/io/xpipe/app/browser/BrowserWelcomeComp.java @@ -13,6 +13,7 @@ import io.xpipe.app.fxcomps.impl.LabelComp; import io.xpipe.app.fxcomps.impl.PrettyImageHelper; import io.xpipe.app.fxcomps.impl.PrettySvgComp; import io.xpipe.app.fxcomps.util.BindingsHelper; +import io.xpipe.app.fxcomps.util.ListBindingsHelper; import io.xpipe.app.storage.DataStorage; import io.xpipe.app.util.ThreadHelper; import javafx.beans.binding.Bindings; @@ -62,7 +63,7 @@ public class BrowserWelcomeComp extends SimpleComp { return new VBox(hbox); } - var list = BindingsHelper.filteredContentBinding(state.getEntries(), e -> { + var list = ListBindingsHelper.filteredContentBinding(state.getEntries(), e -> { var entry = DataStorage.get().getStoreEntryIfPresent(e.getUuid()); if (entry.isEmpty()) { return false; @@ -76,7 +77,7 @@ public class BrowserWelcomeComp extends SimpleComp { }); var empty = Bindings.createBooleanBinding(() -> list.isEmpty(), list); - var headerBinding = BindingsHelper.mappedBinding(empty,b -> { + var headerBinding = BindingsHelper.flatMap(empty,b -> { if (b) { return AppI18n.observable("browserWelcomeEmpty"); } else { diff --git a/app/src/main/java/io/xpipe/app/browser/OpenFileSystemComp.java b/app/src/main/java/io/xpipe/app/browser/OpenFileSystemComp.java index b2b15698f..bf123a358 100644 --- a/app/src/main/java/io/xpipe/app/browser/OpenFileSystemComp.java +++ b/app/src/main/java/io/xpipe/app/browser/OpenFileSystemComp.java @@ -9,7 +9,6 @@ import io.xpipe.app.fxcomps.SimpleComp; import io.xpipe.app.fxcomps.SimpleCompStructure; import io.xpipe.app.fxcomps.augment.ContextMenuAugment; import io.xpipe.app.fxcomps.impl.VerticalComp; -import io.xpipe.app.fxcomps.util.BindingsHelper; import io.xpipe.app.fxcomps.util.Shortcuts; import javafx.geometry.Insets; import javafx.geometry.Pos; @@ -97,7 +96,7 @@ public class OpenFileSystemComp extends SimpleComp { home, model.getCurrentPath().isNull(), fileList, - BindingsHelper.persist(model.getCurrentPath().isNull().not()))); + model.getCurrentPath().isNull().not())); return stack.createRegion(); } } diff --git a/app/src/main/java/io/xpipe/app/browser/action/LeafAction.java b/app/src/main/java/io/xpipe/app/browser/action/LeafAction.java index 4c7764890..a47044622 100644 --- a/app/src/main/java/io/xpipe/app/browser/action/LeafAction.java +++ b/app/src/main/java/io/xpipe/app/browser/action/LeafAction.java @@ -2,7 +2,7 @@ package io.xpipe.app.browser.action; import io.xpipe.app.browser.BrowserEntry; import io.xpipe.app.browser.OpenFileSystemModel; -import io.xpipe.app.fxcomps.impl.FancyTooltipAugment; +import io.xpipe.app.fxcomps.impl.TooltipAugment; import io.xpipe.app.fxcomps.util.Shortcuts; import io.xpipe.app.util.BooleanScope; import io.xpipe.app.util.LicenseProvider; @@ -39,7 +39,7 @@ public interface LeafAction extends BrowserAction { if (getShortcut() != null) { Shortcuts.addShortcut(b, getShortcut()); } - new FancyTooltipAugment<>(new SimpleStringProperty(getName(model, selected))).augment(b); + new TooltipAugment<>(new SimpleStringProperty(getName(model, selected))).augment(b); var graphic = getIcon(model, selected); if (graphic != null) { b.setGraphic(graphic); diff --git a/app/src/main/java/io/xpipe/app/comp/AppLayoutComp.java b/app/src/main/java/io/xpipe/app/comp/AppLayoutComp.java index 53503c7d4..e7161550f 100644 --- a/app/src/main/java/io/xpipe/app/comp/AppLayoutComp.java +++ b/app/src/main/java/io/xpipe/app/comp/AppLayoutComp.java @@ -7,7 +7,6 @@ import io.xpipe.app.core.AppLayoutModel; 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 io.xpipe.app.prefs.AppPrefs; import io.xpipe.app.storage.DataStorage; import javafx.beans.binding.Bindings; @@ -25,14 +24,15 @@ public class AppLayoutComp extends Comp> { var multi = new MultiContentComp(model.getEntries().stream() .collect(Collectors.toMap( entry -> entry.comp(), - entry -> PlatformThread.sync(Bindings.createBooleanBinding( + entry -> Bindings.createBooleanBinding( () -> { return model.getSelected().getValue().equals(entry); }, - model.getSelected()))))); + model.getSelected()))) + ); var pane = new BorderPane(); - var sidebar = new SideMenuBarComp(model.getSelectedInternal(), model.getEntries()); + var sidebar = new SideMenuBarComp(model.getSelected(), model.getEntries()); pane.setCenter(multi.createRegion()); pane.setRight(sidebar.createRegion()); pane.getStyleClass().add("background"); diff --git a/app/src/main/java/io/xpipe/app/comp/base/DropdownComp.java b/app/src/main/java/io/xpipe/app/comp/base/DropdownComp.java index f950f0c1e..1834bf104 100644 --- a/app/src/main/java/io/xpipe/app/comp/base/DropdownComp.java +++ b/app/src/main/java/io/xpipe/app/comp/base/DropdownComp.java @@ -4,7 +4,7 @@ import io.xpipe.app.fxcomps.Comp; import io.xpipe.app.fxcomps.CompStructure; import io.xpipe.app.fxcomps.SimpleCompStructure; import io.xpipe.app.fxcomps.augment.ContextMenuAugment; -import io.xpipe.app.fxcomps.util.BindingsHelper; +import io.xpipe.app.fxcomps.util.ListBindingsHelper; import javafx.css.Size; import javafx.css.SizeUnits; import javafx.scene.control.Button; @@ -37,7 +37,7 @@ public class DropdownComp extends Comp> { .createRegion(); button.visibleProperty() - .bind(BindingsHelper.anyMatch(cm.getItems().stream() + .bind(ListBindingsHelper.anyMatch(cm.getItems().stream() .map(menuItem -> menuItem.getGraphic().visibleProperty()) .toList())); diff --git a/app/src/main/java/io/xpipe/app/comp/base/FontIconComp.java b/app/src/main/java/io/xpipe/app/comp/base/FontIconComp.java index 1176409d6..99742218b 100644 --- a/app/src/main/java/io/xpipe/app/comp/base/FontIconComp.java +++ b/app/src/main/java/io/xpipe/app/comp/base/FontIconComp.java @@ -2,7 +2,6 @@ package io.xpipe.app.comp.base; import io.xpipe.app.fxcomps.Comp; import io.xpipe.app.fxcomps.CompStructure; -import io.xpipe.app.fxcomps.SimpleCompStructure; import io.xpipe.app.fxcomps.util.BindingsHelper; import io.xpipe.app.fxcomps.util.PlatformThread; import javafx.beans.property.SimpleStringProperty; @@ -37,9 +36,10 @@ public class FontIconComp extends Comp { public FontIconComp.Structure createBase() { var fi = new FontIcon(); var obs = PlatformThread.sync(icon); - BindingsHelper.linkPersistently(fi, obs); - obs.subscribe(val -> { - fi.setIconLiteral(val); + icon.subscribe(val -> { + PlatformThread.runLaterIfNeeded(() -> { + fi.setIconLiteral(val); + }); }); var pane = new StackPane(fi); diff --git a/app/src/main/java/io/xpipe/app/comp/base/ListBoxViewComp.java b/app/src/main/java/io/xpipe/app/comp/base/ListBoxViewComp.java index 5cefd9877..f5210c6a3 100644 --- a/app/src/main/java/io/xpipe/app/comp/base/ListBoxViewComp.java +++ b/app/src/main/java/io/xpipe/app/comp/base/ListBoxViewComp.java @@ -3,7 +3,7 @@ package io.xpipe.app.comp.base; import io.xpipe.app.fxcomps.Comp; import io.xpipe.app.fxcomps.CompStructure; import io.xpipe.app.fxcomps.SimpleCompStructure; -import io.xpipe.app.fxcomps.util.BindingsHelper; +import io.xpipe.app.fxcomps.util.ListBindingsHelper; import io.xpipe.app.fxcomps.util.PlatformThread; import javafx.application.Platform; import javafx.collections.ListChangeListener; @@ -88,7 +88,7 @@ public class ListBoxViewComp extends Comp> { } if (!listView.getChildren().equals(newShown)) { - BindingsHelper.setContent(listView.getChildren(), newShown); + ListBindingsHelper.setContent(listView.getChildren(), newShown); } }; diff --git a/app/src/main/java/io/xpipe/app/comp/base/MultiContentComp.java b/app/src/main/java/io/xpipe/app/comp/base/MultiContentComp.java index f865f2c88..b2119a86c 100644 --- a/app/src/main/java/io/xpipe/app/comp/base/MultiContentComp.java +++ b/app/src/main/java/io/xpipe/app/comp/base/MultiContentComp.java @@ -24,9 +24,11 @@ public class MultiContentComp extends SimpleComp { for (Map.Entry, ObservableValue> entry : content.entrySet()) { var region = entry.getKey().createRegion(); stack.getChildren().add(region); - PlatformThread.sync(entry.getValue()).subscribe(val -> { - region.setManaged(val); - region.setVisible(val); + entry.getValue().subscribe(val -> { + PlatformThread.runLaterIfNeeded(() -> { + region.setManaged(val); + region.setVisible(val); + }); }); } return stack; diff --git a/app/src/main/java/io/xpipe/app/comp/base/OsLogoComp.java b/app/src/main/java/io/xpipe/app/comp/base/OsLogoComp.java index a6d27f68b..b54fd38cb 100644 --- a/app/src/main/java/io/xpipe/app/comp/base/OsLogoComp.java +++ b/app/src/main/java/io/xpipe/app/comp/base/OsLogoComp.java @@ -37,7 +37,7 @@ public class OsLogoComp extends SimpleComp { @Override protected Region createSimple() { - var img = BindingsHelper.persist(Bindings.createObjectBinding( + var img = Bindings.createObjectBinding( () -> { if (state.getValue() != SystemStateComp.State.SUCCESS) { return null; @@ -51,7 +51,7 @@ public class OsLogoComp extends SimpleComp { return getImage(ons.getOsName()); }, wrapper.getPersistentState(), - state)); + state); var hide = BindingsHelper.map(img, s -> s != null); return new StackComp( List.of(new SystemStateComp(state).hide(hide), new PrettyImageComp(img, 24, 24).visible(hide))) diff --git a/app/src/main/java/io/xpipe/app/comp/base/SideMenuBarComp.java b/app/src/main/java/io/xpipe/app/comp/base/SideMenuBarComp.java index 458161552..0187a58e9 100644 --- a/app/src/main/java/io/xpipe/app/comp/base/SideMenuBarComp.java +++ b/app/src/main/java/io/xpipe/app/comp/base/SideMenuBarComp.java @@ -7,7 +7,7 @@ import io.xpipe.app.fxcomps.Comp; import io.xpipe.app.fxcomps.CompStructure; import io.xpipe.app.fxcomps.SimpleCompStructure; import io.xpipe.app.fxcomps.augment.Augment; -import io.xpipe.app.fxcomps.impl.FancyTooltipAugment; +import io.xpipe.app.fxcomps.impl.TooltipAugment; import io.xpipe.app.fxcomps.impl.IconButtonComp; import io.xpipe.app.fxcomps.util.PlatformThread; import io.xpipe.app.issue.ErrorEvent; @@ -73,7 +73,7 @@ public class SideMenuBarComp extends Comp> { var e = entries.get(i); var b = new IconButtonComp(e.icon(), () -> value.setValue(e)); b.shortcut(new KeyCodeCombination(KeyCode.values()[KeyCode.DIGIT1.ordinal() + i])); - b.apply(new FancyTooltipAugment<>(e.name())); + b.apply(new TooltipAugment<>(e.name())); b.apply(struc -> { AppFont.setSize(struc.get(), 2); struc.get().pseudoClassStateChanged(selected, value.getValue().equals(e)); @@ -133,7 +133,7 @@ public class SideMenuBarComp extends Comp> { UserReportComp.show(event.build()); }) .shortcut(new KeyCodeCombination(KeyCode.values()[KeyCode.DIGIT1.ordinal() + entries.size()])) - .apply(new FancyTooltipAugment<>("reportIssue")) + .apply(new TooltipAugment<>("reportIssue")) .apply(simpleBorders) .accessibleTextKey("reportIssue"); b.apply(struc -> { @@ -145,7 +145,7 @@ public class SideMenuBarComp extends Comp> { { var b = new IconButtonComp("mdi2g-github", () -> Hyperlinks.open(Hyperlinks.GITHUB)) .shortcut(new KeyCodeCombination(KeyCode.values()[KeyCode.DIGIT1.ordinal() + entries.size() + 1])) - .apply(new FancyTooltipAugment<>("visitGithubRepository")) + .apply(new TooltipAugment<>("visitGithubRepository")) .apply(simpleBorders) .accessibleTextKey("visitGithubRepository"); b.apply(struc -> { @@ -157,7 +157,7 @@ public class SideMenuBarComp extends Comp> { { var b = new IconButtonComp("mdi2d-discord", () -> Hyperlinks.open(Hyperlinks.DISCORD)) .shortcut(new KeyCodeCombination(KeyCode.values()[KeyCode.DIGIT1.ordinal() + entries.size() + 2])) - .apply(new FancyTooltipAugment<>("discord")) + .apply(new TooltipAugment<>("discord")) .apply(simpleBorders) .accessibleTextKey("discord"); b.apply(struc -> { @@ -169,7 +169,7 @@ public class SideMenuBarComp extends Comp> { { var b = new IconButtonComp("mdi2t-translate", () -> Hyperlinks.open(Hyperlinks.TRANSLATE)) .shortcut(new KeyCodeCombination(KeyCode.values()[KeyCode.DIGIT1.ordinal() + entries.size() + 3])) - .apply(new FancyTooltipAugment<>("translate")) + .apply(new TooltipAugment<>("translate")) .apply(simpleBorders) .accessibleTextKey("translate"); b.apply(struc -> { @@ -180,7 +180,7 @@ public class SideMenuBarComp extends Comp> { { var b = new IconButtonComp("mdi2u-update", () -> UpdateAvailableAlert.showIfNeeded()) - .apply(new FancyTooltipAugment<>("updateAvailableTooltip")) + .apply(new TooltipAugment<>("updateAvailableTooltip")) .accessibleTextKey("updateAvailableTooltip"); b.apply(struc -> { AppFont.setSize(struc.get(), 2); diff --git a/app/src/main/java/io/xpipe/app/comp/base/StoreToggleComp.java b/app/src/main/java/io/xpipe/app/comp/base/StoreToggleComp.java index 1d2e52ead..9aa03175b 100644 --- a/app/src/main/java/io/xpipe/app/comp/base/StoreToggleComp.java +++ b/app/src/main/java/io/xpipe/app/comp/base/StoreToggleComp.java @@ -3,7 +3,6 @@ package io.xpipe.app.comp.base; import io.xpipe.app.comp.store.StoreSection; import io.xpipe.app.core.AppI18n; import io.xpipe.app.fxcomps.SimpleComp; -import io.xpipe.app.fxcomps.util.BindingsHelper; import io.xpipe.app.storage.DataStoreEntry; import io.xpipe.app.util.ThreadHelper; import javafx.beans.binding.Bindings; @@ -32,13 +31,13 @@ public class StoreToggleComp extends SimpleComp { @Override protected Region createSimple() { var disable = section.getWrapper().getValidity().map(state -> state != DataStoreEntry.Validity.COMPLETE); - var visible = BindingsHelper.persist(Bindings.createBooleanBinding( + var visible = Bindings.createBooleanBinding( () -> { return section.getWrapper().getValidity().getValue() == DataStoreEntry.Validity.COMPLETE && section.getShowDetails().get(); }, section.getWrapper().getValidity(), - section.getShowDetails())); + section.getShowDetails()); var t = new ToggleSwitchComp(value, AppI18n.observable(nameKey)) .visible(visible) .disable(disable); diff --git a/app/src/main/java/io/xpipe/app/comp/base/TileButtonComp.java b/app/src/main/java/io/xpipe/app/comp/base/TileButtonComp.java index cb6b50be2..8b7867566 100644 --- a/app/src/main/java/io/xpipe/app/comp/base/TileButtonComp.java +++ b/app/src/main/java/io/xpipe/app/comp/base/TileButtonComp.java @@ -4,7 +4,6 @@ import io.xpipe.app.core.AppFont; import io.xpipe.app.core.AppI18n; import io.xpipe.app.fxcomps.Comp; import io.xpipe.app.fxcomps.CompStructure; -import io.xpipe.app.fxcomps.util.BindingsHelper; import io.xpipe.app.fxcomps.util.PlatformThread; import javafx.beans.binding.Bindings; import javafx.beans.property.SimpleStringProperty; @@ -47,9 +46,9 @@ public class TileButtonComp extends Comp { }); var header = new Label(); - BindingsHelper.bindStrong(header.textProperty(), PlatformThread.sync(name)); + header.textProperty().bind(PlatformThread.sync(name)); var desc = new Label(); - BindingsHelper.bindStrong(desc.textProperty(), PlatformThread.sync(description)); + desc.textProperty().bind(PlatformThread.sync(description)); AppFont.small(desc); desc.setOpacity(0.65); var text = new VBox(header, desc); diff --git a/app/src/main/java/io/xpipe/app/comp/store/StoreEntryComp.java b/app/src/main/java/io/xpipe/app/comp/store/StoreEntryComp.java index f8b354000..b93d23326 100644 --- a/app/src/main/java/io/xpipe/app/comp/store/StoreEntryComp.java +++ b/app/src/main/java/io/xpipe/app/comp/store/StoreEntryComp.java @@ -13,7 +13,6 @@ import io.xpipe.app.fxcomps.SimpleCompStructure; import io.xpipe.app.fxcomps.augment.ContextMenuAugment; import io.xpipe.app.fxcomps.augment.GrowAugment; import io.xpipe.app.fxcomps.impl.*; -import io.xpipe.app.fxcomps.util.BindingsHelper; import io.xpipe.app.fxcomps.util.PlatformThread; import io.xpipe.app.prefs.AppPrefs; import io.xpipe.app.storage.DataStorage; @@ -100,8 +99,7 @@ public abstract class StoreEntryComp extends SimpleComp { var loading = LoadingOverlayComp.noProgress( Comp.of(() -> button), - BindingsHelper.persist( - wrapper.getInRefresh().and(wrapper.getObserving().not()))); + wrapper.getInRefresh().and(wrapper.getObserving().not())); return loading.createRegion(); } @@ -173,7 +171,7 @@ public abstract class StoreEntryComp extends SimpleComp { var imageComp = PrettyImageHelper.ofFixedSize(img, w, h); var storeIcon = imageComp.createRegion(); if (wrapper.getValidity().getValue().isUsable()) { - new FancyTooltipAugment<>(new SimpleStringProperty( + new TooltipAugment<>(new SimpleStringProperty( wrapper.getEntry().getProvider().getDisplayName())) .augment(storeIcon); } @@ -211,7 +209,7 @@ public abstract class StoreEntryComp extends SimpleComp { }); button.accessibleText( actionProvider.getName(wrapper.getEntry().ref()).getValue()); - button.apply(new FancyTooltipAugment<>( + button.apply(new TooltipAugment<>( actionProvider.getName(wrapper.getEntry().ref()))); if (actionProvider.activeType() == ActionProvider.DataStoreCallSite.ActiveType.ONLY_SHOW_IF_ENABLED) { button.hide(Bindings.not(p.getValue())); @@ -247,7 +245,7 @@ public abstract class StoreEntryComp extends SimpleComp { settingsButton.accessibleText("More"); settingsButton.apply(new ContextMenuAugment<>( event -> event.getButton() == MouseButton.PRIMARY, null, () -> StoreEntryComp.this.createContextMenu())); - settingsButton.apply(new FancyTooltipAugment<>("more")); + settingsButton.apply(new TooltipAugment<>("more")); return settingsButton; } diff --git a/app/src/main/java/io/xpipe/app/comp/store/StoreEntryListComp.java b/app/src/main/java/io/xpipe/app/comp/store/StoreEntryListComp.java index 2973a396a..979e8903f 100644 --- a/app/src/main/java/io/xpipe/app/comp/store/StoreEntryListComp.java +++ b/app/src/main/java/io/xpipe/app/comp/store/StoreEntryListComp.java @@ -5,7 +5,6 @@ import io.xpipe.app.comp.base.MultiContentComp; import io.xpipe.app.fxcomps.Comp; import io.xpipe.app.fxcomps.SimpleComp; import io.xpipe.app.fxcomps.impl.HorizontalComp; -import io.xpipe.app.fxcomps.util.BindingsHelper; import javafx.beans.binding.Bindings; import javafx.beans.value.ObservableValue; import javafx.geometry.Insets; @@ -50,16 +49,16 @@ public class StoreEntryListComp extends SimpleComp { var map = new LinkedHashMap, ObservableValue>(); map.put( createList(), - BindingsHelper.persist(Bindings.not(Bindings.isEmpty( - StoreViewState.get().getCurrentTopLevelSection().getShownChildren())))); + Bindings.not(Bindings.isEmpty( + StoreViewState.get().getCurrentTopLevelSection().getShownChildren()))); map.put(new StoreIntroComp(), showIntro); map.put( new StoreNotFoundComp(), - BindingsHelper.persist(Bindings.and( + Bindings.and( Bindings.not(Bindings.isEmpty(StoreViewState.get().getAllEntries())), Bindings.isEmpty( - StoreViewState.get().getCurrentTopLevelSection().getShownChildren())))); + StoreViewState.get().getCurrentTopLevelSection().getShownChildren()))); return new MultiContentComp(map).createRegion(); } } diff --git a/app/src/main/java/io/xpipe/app/comp/store/StoreEntryListStatusComp.java b/app/src/main/java/io/xpipe/app/comp/store/StoreEntryListStatusComp.java index e7d4d5552..e799a442e 100644 --- a/app/src/main/java/io/xpipe/app/comp/store/StoreEntryListStatusComp.java +++ b/app/src/main/java/io/xpipe/app/comp/store/StoreEntryListStatusComp.java @@ -5,10 +5,11 @@ import io.xpipe.app.core.AppFont; import io.xpipe.app.core.AppI18n; import io.xpipe.app.fxcomps.Comp; import io.xpipe.app.fxcomps.SimpleComp; -import io.xpipe.app.fxcomps.impl.FancyTooltipAugment; +import io.xpipe.app.fxcomps.impl.TooltipAugment; import io.xpipe.app.fxcomps.impl.FilterComp; import io.xpipe.app.fxcomps.impl.IconButtonComp; import io.xpipe.app.fxcomps.util.BindingsHelper; +import io.xpipe.app.fxcomps.util.ListBindingsHelper; import io.xpipe.app.util.ThreadHelper; import io.xpipe.core.process.OsType; import javafx.beans.binding.Bindings; @@ -55,7 +56,7 @@ public class StoreEntryListStatusComp extends SimpleComp { label.textProperty().bind(name); label.getStyleClass().add("name"); - var all = BindingsHelper.filteredContentBinding( + var all = ListBindingsHelper.filteredContentBinding( StoreViewState.get().getAllEntries(), storeEntryWrapper -> { var storeRoot = storeEntryWrapper.getCategory().getValue().getRoot(); @@ -66,7 +67,7 @@ public class StoreEntryListStatusComp extends SimpleComp { .equals(storeRoot); }, StoreViewState.get().getActiveCategory()); - var shownList = BindingsHelper.filteredContentBinding( + var shownList = ListBindingsHelper.filteredContentBinding( all, storeEntryWrapper -> { return storeEntryWrapper.shouldShow( @@ -178,7 +179,7 @@ public class StoreEntryListStatusComp extends SimpleComp { sortMode)); }); alphabetical.accessibleTextKey("sortAlphabetical"); - alphabetical.apply(new FancyTooltipAugment<>("sortAlphabetical")); + alphabetical.apply(new TooltipAugment<>("sortAlphabetical")); return alphabetical; } @@ -217,7 +218,7 @@ public class StoreEntryListStatusComp extends SimpleComp { sortMode)); }); date.accessibleTextKey("sortLastUsed"); - date.apply(new FancyTooltipAugment<>("sortLastUsed")); + date.apply(new TooltipAugment<>("sortLastUsed")); return date; } diff --git a/app/src/main/java/io/xpipe/app/comp/store/StoreSection.java b/app/src/main/java/io/xpipe/app/comp/store/StoreSection.java index 3780cc91c..c2939b9ac 100644 --- a/app/src/main/java/io/xpipe/app/comp/store/StoreSection.java +++ b/app/src/main/java/io/xpipe/app/comp/store/StoreSection.java @@ -2,6 +2,7 @@ package io.xpipe.app.comp.store; import io.xpipe.app.fxcomps.Comp; import io.xpipe.app.fxcomps.util.BindingsHelper; +import io.xpipe.app.fxcomps.util.ListBindingsHelper; import io.xpipe.app.prefs.AppPrefs; import io.xpipe.app.storage.DataStorage; import io.xpipe.app.storage.DataStoreEntry; @@ -64,10 +65,10 @@ public class StoreSection { var c = Comparator.comparingInt( value -> value.getWrapper().getEntry().getValidity().isUsable() ? -1 : 1); - var mappedSortMode = BindingsHelper.mappedBinding( + var mappedSortMode = BindingsHelper.flatMap( category, storeCategoryWrapper -> storeCategoryWrapper != null ? storeCategoryWrapper.getSortMode() : null); - return BindingsHelper.orderedContentBinding( + return ListBindingsHelper.orderedContentBinding( list, (o1, o2) -> { var current = mappedSortMode.getValue(); @@ -86,16 +87,16 @@ public class StoreSection { Predicate entryFilter, ObservableStringValue filterString, ObservableValue category) { - var topLevel = BindingsHelper.filteredContentBinding( + var topLevel = ListBindingsHelper.filteredContentBinding( all, section -> { return DataStorage.get().isRootEntry(section.getEntry()); }, category); - var cached = BindingsHelper.cachedMappedContentBinding( - topLevel, storeEntryWrapper -> create(storeEntryWrapper, 1, all, entryFilter, filterString, category)); + var cached = ListBindingsHelper.cachedMappedContentBinding( + topLevel, topLevel, storeEntryWrapper -> create(storeEntryWrapper, 1, all, entryFilter, filterString, category)); var ordered = sorted(cached, category); - var shown = BindingsHelper.filteredContentBinding( + var shown = ListBindingsHelper.filteredContentBinding( ordered, section -> { var showFilter = filterString == null || section.shouldShow(filterString.get()); @@ -121,7 +122,7 @@ public class StoreSection { return new StoreSection(e, FXCollections.observableArrayList(), FXCollections.observableArrayList(), depth); } - var allChildren = BindingsHelper.filteredContentBinding(all, other -> { + var allChildren = ListBindingsHelper.filteredContentBinding(all, other -> { // Legacy implementation that does not use children caches. Use for testing // if (true) return DataStorage.get() // .getDisplayParent(other.getEntry()) @@ -131,10 +132,10 @@ public class StoreSection { // This check is fast as the children are cached in the storage return DataStorage.get().getStoreChildren(e.getEntry()).contains(other.getEntry()); }); - var cached = BindingsHelper.cachedMappedContentBinding( - allChildren, entry1 -> create(entry1, depth + 1, all, entryFilter, filterString, category)); + var cached = ListBindingsHelper.cachedMappedContentBinding( + allChildren, allChildren, entry1 -> create(entry1, depth + 1, all, entryFilter, filterString, category)); var ordered = sorted(cached, category); - var filtered = BindingsHelper.filteredContentBinding( + var filtered = ListBindingsHelper.filteredContentBinding( ordered, section -> { var showFilter = filterString == null || section.shouldShow(filterString.get()); diff --git a/app/src/main/java/io/xpipe/app/comp/store/StoreSectionComp.java b/app/src/main/java/io/xpipe/app/comp/store/StoreSectionComp.java index 8ed3c7de1..8c6a9b764 100644 --- a/app/src/main/java/io/xpipe/app/comp/store/StoreSectionComp.java +++ b/app/src/main/java/io/xpipe/app/comp/store/StoreSectionComp.java @@ -7,7 +7,7 @@ import io.xpipe.app.fxcomps.augment.GrowAugment; import io.xpipe.app.fxcomps.impl.HorizontalComp; import io.xpipe.app.fxcomps.impl.IconButtonComp; import io.xpipe.app.fxcomps.impl.VerticalComp; -import io.xpipe.app.fxcomps.util.BindingsHelper; +import io.xpipe.app.fxcomps.util.ListBindingsHelper; import io.xpipe.app.storage.DataStoreColor; import io.xpipe.app.util.ThreadHelper; import javafx.beans.binding.Bindings; @@ -39,11 +39,11 @@ public class StoreSectionComp extends Comp> { } private Comp> createQuickAccessButton() { - var quickAccessDisabled = BindingsHelper.persist(Bindings.createBooleanBinding( + var quickAccessDisabled = Bindings.createBooleanBinding( () -> { return section.getShownChildren().isEmpty(); }, - section.getShownChildren())); + section.getShownChildren()); Consumer quickAccessAction = w -> { ThreadHelper.runFailableAsync(() -> { w.executeDefaultAction(); @@ -90,8 +90,7 @@ public class StoreSectionComp extends Comp> { return "Expand " + section.getWrapper().getName().getValue(); }, section.getWrapper().getName())) - .disable(BindingsHelper.persist( - Bindings.size(section.getShownChildren()).isEqualTo(0))) + .disable(Bindings.size(section.getShownChildren()).isEqualTo(0)) .styleClass("expand-button") .maxHeight(100) .vgrow(); @@ -130,7 +129,7 @@ public class StoreSectionComp extends Comp> { // Optimization for large sections. If there are more than 20 children, only add the nodes to the scene if the // section is actually expanded - var listSections = BindingsHelper.filteredContentBinding( + var listSections = ListBindingsHelper.filteredContentBinding( section.getShownChildren(), storeSection -> section.getAllChildren().size() <= 20 || section.getWrapper().getExpanded().get(), @@ -142,22 +141,22 @@ public class StoreSectionComp extends Comp> { .minHeight(0) .hgrow(); - var expanded = BindingsHelper.persist(Bindings.createBooleanBinding( + var expanded = Bindings.createBooleanBinding( () -> { return section.getWrapper().getExpanded().get() && section.getShownChildren().size() > 0; }, section.getWrapper().getExpanded(), - section.getShownChildren())); + section.getShownChildren()); var full = new VerticalComp(List.of( topEntryList, - Comp.separator().hide(BindingsHelper.persist(expanded.not())), + Comp.separator().hide(expanded.not()), new HorizontalComp(List.of(content)) .styleClass("content") .apply(struc -> struc.get().setFillHeight(true)) - .hide(BindingsHelper.persist(Bindings.or( + .hide(Bindings.or( Bindings.not(section.getWrapper().getExpanded()), - Bindings.size(section.getShownChildren()).isEqualTo(0)))))); + Bindings.size(section.getShownChildren()).isEqualTo(0))))); return full.styleClass("store-entry-section-comp") .apply(struc -> { struc.get().setFillWidth(true); diff --git a/app/src/main/java/io/xpipe/app/comp/store/StoreSectionMiniComp.java b/app/src/main/java/io/xpipe/app/comp/store/StoreSectionMiniComp.java index a6556ea7b..dc22b86f8 100644 --- a/app/src/main/java/io/xpipe/app/comp/store/StoreSectionMiniComp.java +++ b/app/src/main/java/io/xpipe/app/comp/store/StoreSectionMiniComp.java @@ -8,7 +8,7 @@ import io.xpipe.app.fxcomps.impl.HorizontalComp; import io.xpipe.app.fxcomps.impl.IconButtonComp; import io.xpipe.app.fxcomps.impl.PrettyImageHelper; import io.xpipe.app.fxcomps.impl.VerticalComp; -import io.xpipe.app.fxcomps.util.BindingsHelper; +import io.xpipe.app.fxcomps.util.ListBindingsHelper; import io.xpipe.app.storage.DataStoreColor; import javafx.beans.binding.Bindings; import javafx.beans.property.BooleanProperty; @@ -100,16 +100,15 @@ public class StoreSectionMiniComp extends Comp> { + section.getWrapper().getName().getValue(); }, section.getWrapper().getName())) - .disable(BindingsHelper.persist( - Bindings.size(section.getAllChildren()).isEqualTo(0))) + .disable(Bindings.size(section.getAllChildren()).isEqualTo(0)) .grow(false, true) .styleClass("expand-button"); - var quickAccessDisabled = BindingsHelper.persist(Bindings.createBooleanBinding( + var quickAccessDisabled = Bindings.createBooleanBinding( () -> { return section.getShownChildren().isEmpty(); }, - section.getShownChildren())); + section.getShownChildren()); Consumer quickAccessAction = w -> { action.accept(w); }; @@ -133,7 +132,7 @@ public class StoreSectionMiniComp extends Comp> { // Optimization for large sections. If there are more than 20 children, only add the nodes to the scene if the // section is actually expanded var listSections = section.getWrapper() != null - ? BindingsHelper.filteredContentBinding( + ? ListBindingsHelper.filteredContentBinding( section.getShownChildren(), storeSection -> section.getAllChildren().size() <= 20 || expanded.get(), expanded, @@ -148,9 +147,9 @@ public class StoreSectionMiniComp extends Comp> { list.add(new HorizontalComp(List.of(content)) .styleClass("content") .apply(struc -> struc.get().setFillHeight(true)) - .hide(BindingsHelper.persist(Bindings.or( + .hide(Bindings.or( Bindings.not(expanded), - Bindings.size(section.getAllChildren()).isEqualTo(0))))); + Bindings.size(section.getAllChildren()).isEqualTo(0)))); var vert = new VerticalComp(list); if (condensedStyle) { diff --git a/app/src/main/java/io/xpipe/app/comp/store/StoreViewState.java b/app/src/main/java/io/xpipe/app/comp/store/StoreViewState.java index 8b6d019b0..cc5b80337 100644 --- a/app/src/main/java/io/xpipe/app/comp/store/StoreViewState.java +++ b/app/src/main/java/io/xpipe/app/comp/store/StoreViewState.java @@ -1,7 +1,7 @@ package io.xpipe.app.comp.store; import io.xpipe.app.core.AppCache; -import io.xpipe.app.fxcomps.util.BindingsHelper; +import io.xpipe.app.fxcomps.util.ListBindingsHelper; import io.xpipe.app.issue.ErrorEvent; import io.xpipe.app.prefs.AppPrefs; import io.xpipe.app.storage.DataStorage; @@ -273,7 +273,7 @@ public class StoreViewState { return o1.getName().compareToIgnoreCase(o2.getName()); } }; - return BindingsHelper.filteredContentBinding( + return ListBindingsHelper.filteredContentBinding( categories, cat -> root == null || cat.getRoot().equals(root)) .sorted(comparator); } diff --git a/app/src/main/java/io/xpipe/app/core/AppGreetings.java b/app/src/main/java/io/xpipe/app/core/AppGreetings.java index 08be1218e..9f2f92486 100644 --- a/app/src/main/java/io/xpipe/app/core/AppGreetings.java +++ b/app/src/main/java/io/xpipe/app/core/AppGreetings.java @@ -3,7 +3,6 @@ package io.xpipe.app.core; import io.xpipe.app.comp.base.MarkdownComp; import io.xpipe.app.core.mode.OperationMode; import io.xpipe.app.fxcomps.Comp; -import io.xpipe.app.fxcomps.util.BindingsHelper; import javafx.beans.property.SimpleBooleanProperty; import javafx.geometry.Insets; import javafx.geometry.Pos; @@ -98,7 +97,7 @@ public class AppGreetings { alert.getButtonTypes().add(buttonType); Button button = (Button) alert.getDialogPane().lookupButton(buttonType); - button.disableProperty().bind(BindingsHelper.persist(accepted.not())); + button.disableProperty().bind(accepted.not()); } alert.getButtonTypes().add(ButtonType.CANCEL); diff --git a/app/src/main/java/io/xpipe/app/core/AppI18n.java b/app/src/main/java/io/xpipe/app/core/AppI18n.java index cffae71c1..7b57fd37b 100644 --- a/app/src/main/java/io/xpipe/app/core/AppI18n.java +++ b/app/src/main/java/io/xpipe/app/core/AppI18n.java @@ -2,7 +2,7 @@ package io.xpipe.app.core; import io.xpipe.app.comp.base.ModalOverlayComp; import io.xpipe.app.ext.PrefsChoiceValue; -import io.xpipe.app.fxcomps.impl.FancyTooltipAugment; +import io.xpipe.app.fxcomps.impl.TooltipAugment; import io.xpipe.app.issue.ErrorEvent; import io.xpipe.app.issue.TrackEvent; import io.xpipe.app.prefs.AppPrefs; @@ -116,7 +116,7 @@ public class AppI18n { || caller.equals(ModuleHelper.class) || caller.equals(ModalOverlayComp.class) || caller.equals(AppI18n.class) - || caller.equals(FancyTooltipAugment.class) + || caller.equals(TooltipAugment.class) || caller.equals(PrefsChoiceValue.class) || caller.equals(Translatable.class) || caller.equals(AppWindowHelper.class) diff --git a/app/src/main/java/io/xpipe/app/core/AppLayoutModel.java b/app/src/main/java/io/xpipe/app/core/AppLayoutModel.java index 8860ef334..91f17b93b 100644 --- a/app/src/main/java/io/xpipe/app/core/AppLayoutModel.java +++ b/app/src/main/java/io/xpipe/app/core/AppLayoutModel.java @@ -5,7 +5,6 @@ import io.xpipe.app.browser.BrowserModel; import io.xpipe.app.comp.DeveloperTabComp; import io.xpipe.app.comp.store.StoreLayoutComp; import io.xpipe.app.fxcomps.Comp; -import io.xpipe.app.fxcomps.util.PlatformThread; import io.xpipe.app.prefs.AppPrefsComp; import io.xpipe.app.util.LicenseProvider; import javafx.beans.property.Property; @@ -30,13 +29,11 @@ public class AppLayoutModel { private final List entries; private final Property selected; - private final ObservableValue selectedWrapper; public AppLayoutModel(SavedState savedState) { this.savedState = savedState; this.entries = createEntryList(); this.selected = new SimpleObjectProperty<>(entries.get(1)); - this.selectedWrapper = PlatformThread.sync(selected); } public static AppLayoutModel get() { @@ -53,14 +50,10 @@ public class AppLayoutModel { INSTANCE = null; } - public Property getSelectedInternal() { + public Property getSelected() { return selected; } - public ObservableValue getSelected() { - return selectedWrapper; - } - public void selectBrowser() { selected.setValue(entries.getFirst()); } diff --git a/app/src/main/java/io/xpipe/app/fxcomps/Comp.java b/app/src/main/java/io/xpipe/app/fxcomps/Comp.java index 988e56f90..dce02a41a 100644 --- a/app/src/main/java/io/xpipe/app/fxcomps/Comp.java +++ b/app/src/main/java/io/xpipe/app/fxcomps/Comp.java @@ -4,7 +4,8 @@ import atlantafx.base.controls.Spacer; import io.xpipe.app.core.AppI18n; import io.xpipe.app.fxcomps.augment.Augment; import io.xpipe.app.fxcomps.augment.GrowAugment; -import io.xpipe.app.fxcomps.impl.FancyTooltipAugment; +import io.xpipe.app.fxcomps.impl.TooltipAugment; +import io.xpipe.app.fxcomps.util.BindingsHelper; import io.xpipe.app.fxcomps.util.Shortcuts; import javafx.application.Platform; import javafx.beans.value.ObservableValue; @@ -143,6 +144,7 @@ public abstract class Comp> { public Comp hide(ObservableValue o) { return apply(struc -> { var region = struc.get(); + BindingsHelper.preserve(region, o); o.subscribe(n -> { if (!n) { region.setVisible(true); @@ -188,11 +190,11 @@ public abstract class Comp> { } public Comp tooltip(ObservableValue text) { - return apply(new FancyTooltipAugment<>(text)); + return apply(new TooltipAugment<>(text)); } public Comp tooltipKey(String key) { - return apply(new FancyTooltipAugment<>(key)); + return apply(new TooltipAugment<>(key)); } public Region createRegion() { @@ -201,6 +203,8 @@ public abstract class Comp> { public S createStructure() { S struc = createBase(); + // Make comp last at least as long as region + BindingsHelper.preserve(struc.get(), this); if (augments != null) { for (var a : augments) { a.augment(struc); diff --git a/app/src/main/java/io/xpipe/app/fxcomps/impl/ChoiceComp.java b/app/src/main/java/io/xpipe/app/fxcomps/impl/ChoiceComp.java index d7a9d41d5..2a56182ce 100644 --- a/app/src/main/java/io/xpipe/app/fxcomps/impl/ChoiceComp.java +++ b/app/src/main/java/io/xpipe/app/fxcomps/impl/ChoiceComp.java @@ -4,7 +4,7 @@ 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.BindingsHelper; +import io.xpipe.app.fxcomps.util.ListBindingsHelper; import io.xpipe.app.fxcomps.util.PlatformThread; import io.xpipe.app.util.Translatable; import javafx.beans.property.Property; @@ -77,7 +77,7 @@ public class ChoiceComp extends Comp>> { list.add(null); } - BindingsHelper.setContent(cb.getItems(), list); + ListBindingsHelper.setContent(cb.getItems(), list); }); cb.valueProperty().addListener((observable, oldValue, newValue) -> { diff --git a/app/src/main/java/io/xpipe/app/fxcomps/impl/ContextualFileReferenceChoiceComp.java b/app/src/main/java/io/xpipe/app/fxcomps/impl/ContextualFileReferenceChoiceComp.java index bea99195b..189e732cb 100644 --- a/app/src/main/java/io/xpipe/app/fxcomps/impl/ContextualFileReferenceChoiceComp.java +++ b/app/src/main/java/io/xpipe/app/fxcomps/impl/ContextualFileReferenceChoiceComp.java @@ -6,7 +6,6 @@ import io.xpipe.app.comp.base.ButtonComp; import io.xpipe.app.core.AppI18n; import io.xpipe.app.core.AppWindowHelper; import io.xpipe.app.fxcomps.SimpleComp; -import io.xpipe.app.fxcomps.util.BindingsHelper; import io.xpipe.app.issue.ErrorEvent; import io.xpipe.app.prefs.AppPrefs; import io.xpipe.app.storage.ContextualFileReference; @@ -65,7 +64,7 @@ public class ContextualFileReferenceChoiceComp extends SimpleComp { .styleClass(Styles.CENTER_PILL) .grow(false, true); - var canGitShare = BindingsHelper.persist(Bindings.createBooleanBinding( + var canGitShare = Bindings.createBooleanBinding( () -> { if (!AppPrefs.get().enableGitStorage().get() || filePath.getValue() == null @@ -76,7 +75,7 @@ public class ContextualFileReferenceChoiceComp extends SimpleComp { return true; }, filePath, - AppPrefs.get().enableGitStorage())); + AppPrefs.get().enableGitStorage()); var gitShareButton = new ButtonComp(null, new FontIcon("mdi2g-git"), () -> { if (filePath.getValue() == null || filePath.getValue().isBlank() || !canGitShare.get()) { return; @@ -107,7 +106,7 @@ public class ContextualFileReferenceChoiceComp extends SimpleComp { ErrorEvent.fromThrowable(e).handle(); } }); - gitShareButton.apply(new FancyTooltipAugment<>("gitShareFileTooltip")); + gitShareButton.apply(new TooltipAugment<>("gitShareFileTooltip")); gitShareButton.styleClass(Styles.RIGHT_PILL).grow(false, true); var layout = new HorizontalComp(List.of(fileNameComp, fileBrowseButton, gitShareButton)) diff --git a/app/src/main/java/io/xpipe/app/fxcomps/impl/DataStoreFlowChoiceComp.java b/app/src/main/java/io/xpipe/app/fxcomps/impl/DataStoreFlowChoiceComp.java index 6568a563c..8f98b608d 100644 --- a/app/src/main/java/io/xpipe/app/fxcomps/impl/DataStoreFlowChoiceComp.java +++ b/app/src/main/java/io/xpipe/app/fxcomps/impl/DataStoreFlowChoiceComp.java @@ -27,11 +27,11 @@ public class DataStoreFlowChoiceComp extends SimpleComp { map.put(DataFlow.INPUT_OUTPUT, AppI18n.observable("app.inout")); return new ToggleGroupComp<>(selected, new SimpleObjectProperty<>(map)) .apply(struc -> { - new FancyTooltipAugment<>("app.inputDescription") + new TooltipAugment<>("app.inputDescription") .augment(struc.get().getChildren().get(0)); - new FancyTooltipAugment<>("app.outputDescription") + new TooltipAugment<>("app.outputDescription") .augment(struc.get().getChildren().get(1)); - new FancyTooltipAugment<>("app.inoutDescription") + new TooltipAugment<>("app.inoutDescription") .augment(struc.get().getChildren().get(2)); }) .createRegion(); diff --git a/app/src/main/java/io/xpipe/app/fxcomps/impl/LabelComp.java b/app/src/main/java/io/xpipe/app/fxcomps/impl/LabelComp.java index 45ed6e40e..3556f7712 100644 --- a/app/src/main/java/io/xpipe/app/fxcomps/impl/LabelComp.java +++ b/app/src/main/java/io/xpipe/app/fxcomps/impl/LabelComp.java @@ -25,7 +25,6 @@ public class LabelComp extends Comp> { @Override public CompStructure