From d92b87090871e8ab870bf11aac651b7869872cc2 Mon Sep 17 00:00:00 2001 From: crschnick Date: Wed, 21 Aug 2024 15:20:58 +0000 Subject: [PATCH] Make categories expendable --- .../app/comp/store/StoreCategoryWrapper.java | 10 +++++++--- .../app/fxcomps/impl/StoreCategoryComp.java | 15 ++++++++++----- .../java/io/xpipe/app/storage/DataStorage.java | 3 ++- .../io/xpipe/app/storage/DataStoreCategory.java | 17 ++++++++++++----- .../io/xpipe/app/storage/DataStoreEntry.java | 16 ++-------------- .../xpipe/app/storage/ImpersistentStorage.java | 1 + .../io/xpipe/app/storage/StorageElement.java | 16 +++++++++++++++- 7 files changed, 49 insertions(+), 29 deletions(-) diff --git a/app/src/main/java/io/xpipe/app/comp/store/StoreCategoryWrapper.java b/app/src/main/java/io/xpipe/app/comp/store/StoreCategoryWrapper.java index 414e8ac48..2eac24a21 100644 --- a/app/src/main/java/io/xpipe/app/comp/store/StoreCategoryWrapper.java +++ b/app/src/main/java/io/xpipe/app/comp/store/StoreCategoryWrapper.java @@ -6,9 +6,7 @@ import io.xpipe.app.prefs.AppPrefs; import io.xpipe.app.storage.DataStorage; import io.xpipe.app.storage.DataStoreCategory; -import javafx.beans.property.Property; -import javafx.beans.property.SimpleObjectProperty; -import javafx.beans.property.SimpleStringProperty; +import javafx.beans.property.*; import javafx.collections.FXCollections; import javafx.collections.ObservableList; @@ -30,6 +28,7 @@ public class StoreCategoryWrapper { private final Property share; private final ObservableList children; private final ObservableList containedEntries; + private final BooleanProperty expanded = new SimpleBooleanProperty(); public StoreCategoryWrapper(DataStoreCategory category) { var d = 0; @@ -111,6 +110,10 @@ public class StoreCategoryWrapper { }); } + public void toggleExpanded() { + this.expanded.set(!expanded.getValue()); + } + public void update() { // We are probably in shutdown then if (StoreViewState.get() == null) { @@ -126,6 +129,7 @@ public class StoreCategoryWrapper { lastAccess.setValue(category.getLastAccess().minus(Duration.ofMillis(500))); sortMode.setValue(category.getSortMode()); share.setValue(category.isShare()); + expanded.setValue(category.isExpanded()); containedEntries.setAll(StoreViewState.get().getAllEntries().getList().stream() .filter(entry -> { diff --git a/app/src/main/java/io/xpipe/app/fxcomps/impl/StoreCategoryComp.java b/app/src/main/java/io/xpipe/app/fxcomps/impl/StoreCategoryComp.java index 0d0d77f5f..40f8c359d 100644 --- a/app/src/main/java/io/xpipe/app/fxcomps/impl/StoreCategoryComp.java +++ b/app/src/main/java/io/xpipe/app/fxcomps/impl/StoreCategoryComp.java @@ -49,13 +49,16 @@ public class StoreCategoryComp extends SimpleComp { () -> { if (!DataStorage.get().supportsSharing() || !category.getCategory().canShare()) { - return "mdal-keyboard_arrow_right"; + var exp = category.getExpanded().get() && category.getChildren().size() > 0; + return exp ? "mdal-keyboard_arrow_down" : "mdal-keyboard_arrow_right"; } return category.getShare().getValue() ? "mdi2g-git" : "mdi2a-account-cancel"; }, - category.getShare()); - var icon = new IconButtonComp(i) + category.getShare(), category.getExpanded(), category.getChildren()); + var icon = new IconButtonComp(i, () -> { + category.toggleExpanded(); + }) .apply(struc -> AppFont.small(struc.get())) .apply(struc -> { struc.get().setAlignment(Pos.CENTER); @@ -116,8 +119,10 @@ public class StoreCategoryComp extends SimpleComp { var children = new ListBoxViewComp<>(l, l, storeCategoryWrapper -> new StoreCategoryComp(storeCategoryWrapper), false); - var emptyBinding = Bindings.isEmpty(category.getChildren()); - var v = new VerticalComp(List.of(categoryButton, children.hide(emptyBinding))); + var hide = Bindings.createBooleanBinding(() -> { + return !category.getExpanded().get() || category.getChildren().isEmpty(); + }, category.getChildren(), category.getExpanded()); + var v = new VerticalComp(List.of(categoryButton, children.hide(hide))); v.styleClass("category"); v.apply(struc -> { StoreViewState.get().getActiveCategory().subscribe(val -> { diff --git a/app/src/main/java/io/xpipe/app/storage/DataStorage.java b/app/src/main/java/io/xpipe/app/storage/DataStorage.java index afa5119c4..3a2827e3b 100644 --- a/app/src/main/java/io/xpipe/app/storage/DataStorage.java +++ b/app/src/main/java/io/xpipe/app/storage/DataStorage.java @@ -175,7 +175,8 @@ public abstract class DataStorage { true, ALL_CONNECTIONS_CATEGORY_UUID, StoreSortMode.getDefault(), - false)); + false, + true)); } storeCategories.forEach(dataStoreCategory -> { diff --git a/app/src/main/java/io/xpipe/app/storage/DataStoreCategory.java b/app/src/main/java/io/xpipe/app/storage/DataStoreCategory.java index e2ef999a9..82c8ed230 100644 --- a/app/src/main/java/io/xpipe/app/storage/DataStoreCategory.java +++ b/app/src/main/java/io/xpipe/app/storage/DataStoreCategory.java @@ -41,8 +41,9 @@ public class DataStoreCategory extends StorageElement { boolean dirty, UUID parentCategory, StoreSortMode sortMode, - boolean share) { - super(directory, uuid, name, lastUsed, lastModified, dirty); + boolean share, + boolean expanded) { + super(directory, uuid, name, lastUsed, lastModified, expanded, dirty); this.parentCategory = parentCategory; this.sortMode = sortMode; this.share = share; @@ -58,7 +59,8 @@ public class DataStoreCategory extends StorageElement { true, parentCategory, StoreSortMode.getDefault(), - false); + false, + true); } public static DataStoreCategory createNew(UUID parentCategory, @NonNull UUID uuid, @NonNull String name) { @@ -71,7 +73,8 @@ public class DataStoreCategory extends StorageElement { true, parentCategory, StoreSortMode.getDefault(), - false); + false, + true); } public static Optional fromDirectory(Path dir) throws Exception { @@ -108,9 +111,12 @@ public class DataStoreCategory extends StorageElement { .map(jsonNode -> jsonNode.textValue()) .map(Instant::parse) .orElse(Instant.now()); + var expanded = Optional.ofNullable(stateJson.get("expanded")) + .map(jsonNode -> jsonNode.booleanValue()) + .orElse(true); return Optional.of( - new DataStoreCategory(dir, uuid, name, lastUsed, lastModified, false, parentUuid, sortMode, share)); + new DataStoreCategory(dir, uuid, name, lastUsed, lastModified, false, parentUuid, sortMode, share, expanded)); } public void setSortMode(StoreSortMode sortMode) { @@ -177,6 +183,7 @@ public class DataStoreCategory extends StorageElement { stateObj.put("lastUsed", lastUsed.toString()); stateObj.put("lastModified", lastModified.toString()); stateObj.put("sortMode", sortMode.getId()); + stateObj.put("expanded", expanded); obj.put("parentUuid", parentCategory != null ? parentCategory.toString() : null); var entryString = mapper.writeValueAsString(obj); diff --git a/app/src/main/java/io/xpipe/app/storage/DataStoreEntry.java b/app/src/main/java/io/xpipe/app/storage/DataStoreEntry.java index b339e894f..9bbb81579 100644 --- a/app/src/main/java/io/xpipe/app/storage/DataStoreEntry.java +++ b/app/src/main/java/io/xpipe/app/storage/DataStoreEntry.java @@ -44,9 +44,6 @@ public class DataStoreEntry extends StorageElement { @NonFinal Configuration configuration; - @NonFinal - boolean expanded; - AtomicInteger busyCounter = new AtomicInteger(); @Getter @@ -92,13 +89,12 @@ public class DataStoreEntry extends StorageElement { DataStoreColor color, String notes, Order explicitOrder) { - super(directory, uuid, name, lastUsed, lastModified, dirty); + super(directory, uuid, name, lastUsed, lastModified, expanded, dirty); this.categoryUuid = categoryUuid; this.store = store; this.storeNode = storeNode; this.validity = validity; this.configuration = configuration; - this.expanded = expanded; this.color = color; this.explicitOrder = explicitOrder; this.provider = store != null ? DataStoreProviders.byStore(store) : null; @@ -115,7 +111,7 @@ public class DataStoreEntry extends StorageElement { Instant lastModified, DataStore store, Order explicitOrder) { - super(directory, uuid, name, lastUsed, lastModified, false); + super(directory, uuid, name, lastUsed, lastModified, false,false); this.categoryUuid = categoryUuid; this.store = store; this.explicitOrder = explicitOrder; @@ -401,14 +397,6 @@ public class DataStoreEntry extends StorageElement { dirty = false; } - public void setExpanded(boolean expanded) { - var changed = expanded != this.expanded; - this.expanded = expanded; - if (changed) { - notifyUpdate(false, true); - } - } - public void setNotes(String newNotes) { var changed = !Objects.equals(notes, newNotes); this.notes = newNotes; diff --git a/app/src/main/java/io/xpipe/app/storage/ImpersistentStorage.java b/app/src/main/java/io/xpipe/app/storage/ImpersistentStorage.java index 659d3a7f9..66703e001 100644 --- a/app/src/main/java/io/xpipe/app/storage/ImpersistentStorage.java +++ b/app/src/main/java/io/xpipe/app/storage/ImpersistentStorage.java @@ -33,6 +33,7 @@ public class ImpersistentStorage extends DataStorage { true, ALL_CONNECTIONS_CATEGORY_UUID, StoreSortMode.getDefault(), + true, true); storeCategories.add(cat); selectedCategory = getStoreCategoryIfPresent(DEFAULT_CATEGORY_UUID).orElseThrow(); diff --git a/app/src/main/java/io/xpipe/app/storage/StorageElement.java b/app/src/main/java/io/xpipe/app/storage/StorageElement.java index ad3ad2fa3..10bba2a66 100644 --- a/app/src/main/java/io/xpipe/app/storage/StorageElement.java +++ b/app/src/main/java/io/xpipe/app/storage/StorageElement.java @@ -4,6 +4,7 @@ import lombok.Builder; import lombok.Getter; import lombok.Setter; import lombok.Value; +import lombok.experimental.NonFinal; import lombok.extern.jackson.Jacksonized; import org.apache.commons.io.FileUtils; @@ -37,16 +38,29 @@ public abstract class StorageElement { @Getter protected Instant lastModified; + @NonFinal + @Getter + protected boolean expanded; + public StorageElement( - Path directory, UUID uuid, String name, Instant lastUsed, Instant lastModified, boolean dirty) { + Path directory, UUID uuid, String name, Instant lastUsed, Instant lastModified, boolean expanded, boolean dirty) { this.directory = directory; this.uuid = uuid; this.name = name; this.lastUsed = lastUsed; this.lastModified = lastModified; + this.expanded = expanded; this.dirty = dirty; } + public void setExpanded(boolean expanded) { + var changed = expanded != this.expanded; + this.expanded = expanded; + if (changed) { + notifyUpdate(false, true); + } + } + public abstract Path[] getShareableFiles(); public void notifyUpdate(boolean used, boolean modified) {