Improve store styling

This commit is contained in:
crschnick 2023-07-02 10:09:38 +00:00
parent 1e714e2c4a
commit 1ba5f7cf2a
9 changed files with 90 additions and 59 deletions

View file

@ -36,23 +36,25 @@ public class ListBoxViewComp<T> extends Comp<CompStructure<ScrollPane>> {
public CompStructure<ScrollPane> createBase() {
Map<T, Region> cache = new HashMap<>();
VBox listView = new VBox();
listView.setFocusTraversable(false);
VBox vbox = new VBox();
vbox.getStyleClass().add("content");
vbox.setFocusTraversable(false);
refresh(listView, shown, all, cache, false);
listView.requestLayout();
refresh(vbox, shown, all, cache, false);
vbox.requestLayout();
shown.addListener((ListChangeListener<? super T>) (c) -> {
refresh(listView, c.getList(), all, cache, true);
refresh(vbox, c.getList(), all, cache, true);
});
all.addListener((ListChangeListener<? super T>) c -> {
cache.keySet().retainAll(c.getList());
});
var scroll = new ScrollPane(listView);
var scroll = new ScrollPane(vbox);
scroll.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
scroll.setFitToWidth(true);
scroll.getStyleClass().add("list-box-view-comp");
return new SimpleCompStructure<>(scroll);
}

View file

@ -34,12 +34,12 @@ import java.util.ArrayList;
public abstract class StoreEntryComp extends SimpleComp {
public static Comp<?> customSection(StoreEntryWrapper e) {
var prov = e.getEntry().getProvider();
public static Comp<?> customSection(StoreSection e) {
var prov = e.getWrapper().getEntry().getProvider();
if (prov != null) {
return prov.customDisplay(e);
} else {
return new StandardStoreEntryComp(e, null);
return new StandardStoreEntryComp(e.getWrapper(), null);
}
}

View file

@ -26,8 +26,8 @@ public class StoreEntryListComp extends SimpleComp {
.map(s -> (storeEntrySection -> storeEntrySection.shouldShow(s))));
var content = new ListBoxViewComp<>(filtered, topLevel.getChildren(), (StoreSection e) -> {
var custom = StoreSection.customSection(e).hgrow();
return new HorizontalComp(List.of(Comp.spacer(20), custom, Comp.spacer(20))).styleClass("top");
}).apply(struc -> ((Region) struc.get().getContent()).setPadding(new Insets(20, 0, 20, 0)));
return new HorizontalComp(List.of(Comp.spacer(10), custom, Comp.spacer(10))).styleClass("top");
}).apply(struc -> ((Region) struc.get().getContent()).setPadding(new Insets(10, 0, 10, 0)));
return content.styleClass("store-list-comp");
}

View file

@ -4,6 +4,9 @@ import io.xpipe.app.comp.storage.StorageFilter;
import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.fxcomps.util.BindingsHelper;
import io.xpipe.app.storage.DataStorage;
import javafx.beans.binding.Bindings;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ObservableBooleanValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import lombok.Value;
@ -19,12 +22,30 @@ public class StoreSection implements StorageFilter.Filterable {
if (prov != null) {
return prov.customContainer(e);
} else {
return new StoreEntrySectionComp(e);
return new StoreSectionComp(e);
}
}
StoreEntryWrapper wrapper;
ObservableList<StoreSection> children;
int depth;
ObservableBooleanValue showDetails;
public StoreSection(StoreEntryWrapper wrapper, ObservableList<StoreSection> children, int depth) {
this.wrapper = wrapper;
this.children = children;
this.depth = depth;
if (wrapper != null) {
this.showDetails = Bindings.createBooleanBinding(
() -> {
return wrapper.getExpanded().get() || children.size() == 0;
},
wrapper.getExpanded(),
children);
} else {
this.showDetails = new SimpleBooleanProperty(true);
}
}
private static final Comparator<StoreSection> COMPARATOR = Comparator.<StoreSection, Instant>comparing(
o -> o.wrapper.getEntry().getState().isUsable()
@ -36,19 +57,19 @@ public class StoreSection implements StorageFilter.Filterable {
public static StoreSection createTopLevel() {
var topLevel = BindingsHelper.mappedContentBinding(
StoreViewState.get().getAllEntries(), storeEntryWrapper -> create(storeEntryWrapper));
StoreViewState.get().getAllEntries(), storeEntryWrapper -> create(storeEntryWrapper, 1));
var filtered = BindingsHelper.filteredContentBinding(topLevel, section -> {
return DataStorage.get()
.getParent(section.getWrapper().getEntry(), true)
.isEmpty();
});
var ordered = BindingsHelper.orderedContentBinding(filtered, COMPARATOR);
return new StoreSection(null, ordered);
return new StoreSection(null, ordered, 0);
}
private static StoreSection create(StoreEntryWrapper e) {
private static StoreSection create(StoreEntryWrapper e, int depth) {
if (!e.getEntry().getState().isUsable()) {
return new StoreSection(e, FXCollections.observableArrayList());
return new StoreSection(e, FXCollections.observableArrayList(), depth);
}
var filtered =
@ -58,9 +79,9 @@ public class StoreSection implements StorageFilter.Filterable {
.map(found -> found.equals(e.getEntry()))
.orElse(false);
});
var children = BindingsHelper.mappedContentBinding(filtered, entry1 -> create(entry1));
var children = BindingsHelper.mappedContentBinding(filtered, entry1 -> create(entry1, depth + 1));
var ordered = BindingsHelper.orderedContentBinding(children, COMPARATOR);
return new StoreSection(e, ordered);
return new StoreSection(e, ordered, depth);
}
@Override

View file

@ -1,6 +1,5 @@
package io.xpipe.app.comp.storage.store;
import atlantafx.base.theme.Styles;
import io.xpipe.app.comp.base.ListBoxViewComp;
import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.fxcomps.CompStructure;
@ -12,24 +11,27 @@ import io.xpipe.app.fxcomps.util.BindingsHelper;
import io.xpipe.app.fxcomps.util.SimpleChangeListener;
import javafx.beans.binding.Bindings;
import javafx.css.PseudoClass;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import java.util.List;
public class StoreEntrySectionComp extends Comp<CompStructure<VBox>> {
public class StoreSectionComp extends Comp<CompStructure<VBox>> {
private static final PseudoClass ODD = PseudoClass.getPseudoClass("odd-depth");
private static final PseudoClass EVEN = PseudoClass.getPseudoClass("even-depth");
public static final PseudoClass EXPANDED = PseudoClass.getPseudoClass("expanded");
private final StoreSection section;
public StoreEntrySectionComp(StoreSection section) {
public StoreSectionComp(StoreSection section) {
this.section = section;
}
@Override
public CompStructure<VBox> createBase() {
var root = StandardStoreEntryComp.customSection(section.getWrapper()).apply(struc -> HBox.setHgrow(struc.get(), Priority.ALWAYS));
var root = StandardStoreEntryComp.customSection(section).apply(struc -> HBox.setHgrow(struc.get(), Priority.ALWAYS));
var button = new IconButtonComp(
Bindings.createStringBinding(
() -> section.getWrapper().getExpanded().get()
@ -57,15 +59,7 @@ public class StoreEntrySectionComp extends Comp<CompStructure<VBox>> {
.map(s -> (storeEntrySection -> storeEntrySection.shouldShow(s))));
var content = new ListBoxViewComp<>(shown, all, (StoreSection e) -> {
return StoreSection.customSection(e).apply(GrowAugment.create(true, false));
})
.apply(struc -> HBox.setHgrow(struc.get(), Priority.ALWAYS))
.apply(struc -> struc.get().backgroundProperty().set(Background.fill(Color.color(0, 0, 0, 0.01))));
var spacer = Comp.of(() -> {
var padding = new Region();
padding.setMinWidth(25);
padding.setMaxWidth(25);
return padding;
});
}).hgrow();
var expanded = Bindings.createBooleanBinding(() -> {
return section.getWrapper().getExpanded().get() && section.getChildren().size() > 0;
@ -75,18 +69,20 @@ public class StoreEntrySectionComp extends Comp<CompStructure<VBox>> {
new HorizontalComp(topEntryList)
.apply(struc -> struc.get().setFillHeight(true)),
Comp.separator().visible(expanded),
new HorizontalComp(List.of(spacer, content))
new HorizontalComp(List.of(content))
.styleClass("content")
.apply(struc -> struc.get().setFillHeight(true))
.hide(BindingsHelper.persist(Bindings.or(
Bindings.not(section.getWrapper().getExpanded()),
Bindings.size(section.getChildren()).isEqualTo(0))))))
.styleClass("store-entry-section-comp")
.styleClass(Styles.ELEVATED_1)
.apply(struc -> {
struc.get().setFillWidth(true);
SimpleChangeListener.apply(expanded, val -> {
struc.get().pseudoClassStateChanged(EXPANDED, val);
});
struc.get().pseudoClassStateChanged(EVEN, section.getDepth() % 2 == 0);
struc.get().pseudoClassStateChanged(ODD, section.getDepth() % 2 != 0);
})
.createStructure();
}

View file

@ -1,6 +1,5 @@
package io.xpipe.app.comp.storage.store;
import atlantafx.base.theme.Styles;
import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.fxcomps.SimpleComp;
import io.xpipe.app.fxcomps.impl.VerticalComp;
@ -14,8 +13,8 @@ public class StoreSidebarComp extends SimpleComp {
@Override
protected Region createSimple() {
var sideBar = new VerticalComp(List.of(
new StoreEntryListHeaderComp().styleClass(Styles.ELEVATED_1),
new StoreCreationBarComp().styleClass(Styles.ELEVATED_1),
new StoreEntryListHeaderComp(),
new StoreCreationBarComp(),
Comp.of(() -> new Region()).styleClass("bar").styleClass("filler-bar")));
sideBar.apply(s -> VBox.setVgrow(s.get().getChildren().get(2), Priority.ALWAYS));
sideBar.styleClass("sidebar");

View file

@ -3,7 +3,7 @@ package io.xpipe.app.ext;
import io.xpipe.app.comp.base.MarkdownComp;
import io.xpipe.app.comp.base.SystemStateComp;
import io.xpipe.app.comp.storage.store.StandardStoreEntryComp;
import io.xpipe.app.comp.storage.store.StoreEntrySectionComp;
import io.xpipe.app.comp.storage.store.StoreSectionComp;
import io.xpipe.app.comp.storage.store.StoreEntryWrapper;
import io.xpipe.app.comp.storage.store.StoreSection;
import io.xpipe.app.core.AppI18n;
@ -34,12 +34,12 @@ public interface DataStoreProvider {
}
}
default Comp<?> customDisplay(StoreEntryWrapper w) {
return new StandardStoreEntryComp(w, null);
default Comp<?> customDisplay(StoreSection s) {
return new StandardStoreEntryComp(s.getWrapper(), null);
}
default Comp<?> customContainer(StoreSection section) {
return new StoreEntrySectionComp(section);
return new StoreSectionComp(section);
}
default String failureInfo() {

View file

@ -1,7 +1,8 @@
.bar {
-fx-padding: 0.8em 1.0em 0.8em 1.0em;
-fx-background-color: -color-bg-subtle;
-fx-border-color: -color-neutral-emphasis;
-fx-border-color: -color-border-default;
-fx-effect: dropshadow(three-pass-box, -color-shadow-default, 8px, 0.5, 0, 1);
}
.store-header-bar {
@ -25,7 +26,7 @@
}
.sidebar {
-fx-spacing: 5px;
-fx-spacing: 0.75em;
}
.bar .button-comp {

View file

@ -32,21 +32,19 @@
}
.store-list-comp .top {
-fx-border-width: 0 0 1em 0;
-fx-background-insets: 0 0 1em 0;
-fx-border-width: 0 0 0.7em 0;
-fx-background-insets: 0 0 0.7em 0;
-fx-border-color: transparent;
}
.store-list-comp .top:odd .store-entry-section-comp {
-fx-background-color: -color-bg-subtle;
}
.store-list-comp .top:even .store-entry-section-comp {
-fx-background-color: -color-bg-overlay;
}
.store-list-comp .store-entry-section-comp {
.store-entry-section-comp:expanded:odd-depth {
-fx-background-color: -color-bg-default;
-fx-background-radius: 4px;
}
.store-entry-section-comp:expanded:even-depth {
-fx-background-color: -color-bg-subtle;
-fx-background-radius: 4px;
}
.store-entry-comp:hover {
@ -62,21 +60,35 @@
}
.store-entry-section-comp .separator {
-fx-padding: 0 0.5em 0 0.5em;
-fx-padding: 0 0.75em 0 0.75em;
-fx-border-insets: 0px;
}
.store-entry-section-comp > .content {
-fx-padding: 5px 0 5px 25px;
}
.store-entry-section-comp .separator .line {
-fx-padding: 0;
-fx-border-insets: 0px;
-fx-background-color: -color-border-subtle;
-fx-pref-height: 1;
}
.store-entry-section-comp * {
-fx-spacing: 0.5em;
.top > .store-entry-section-comp {
-fx-effect: dropshadow(three-pass-box, -color-shadow-default, 6px, 0.5, 0, 1);
-fx-background-color: -color-bg-default;
-fx-background-radius: 4px;
}
.store-entry-section-comp:expanded {
-fx-background-color: -color-bg-default;
-fx-border-radius: 4px;
-fx-border-width: 1px;
-fx-border-color: -color-border-default;
}
.store-entry-section-comp .list-box-view-comp .content {
-fx-spacing: 0.2em;
}