mirror of
https://github.com/xpipe-io/xpipe.git
synced 2024-11-22 15:40:23 +00:00
Browser UI rework
This commit is contained in:
parent
93eb1075ac
commit
6cc7fa180c
12 changed files with 252 additions and 92 deletions
|
@ -1,33 +1,18 @@
|
||||||
package io.xpipe.app.browser;
|
package io.xpipe.app.browser;
|
||||||
|
|
||||||
import io.xpipe.app.comp.store.StoreEntryWrapper;
|
import io.xpipe.app.comp.store.*;
|
||||||
import io.xpipe.app.comp.store.StoreSection;
|
|
||||||
import io.xpipe.app.comp.store.StoreSectionMiniComp;
|
|
||||||
import io.xpipe.app.comp.store.StoreViewState;
|
|
||||||
import io.xpipe.app.core.AppFont;
|
|
||||||
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.SimpleComp;
|
import io.xpipe.app.fxcomps.SimpleComp;
|
||||||
import io.xpipe.app.fxcomps.impl.FilterComp;
|
|
||||||
import io.xpipe.app.fxcomps.impl.HorizontalComp;
|
|
||||||
import io.xpipe.app.fxcomps.util.PlatformThread;
|
import io.xpipe.app.fxcomps.util.PlatformThread;
|
||||||
import io.xpipe.app.storage.DataStoreEntry;
|
import io.xpipe.app.storage.DataStoreEntry;
|
||||||
import io.xpipe.app.util.DataStoreCategoryChoiceComp;
|
|
||||||
|
|
||||||
import javafx.beans.binding.Bindings;
|
import javafx.beans.binding.Bindings;
|
||||||
import javafx.beans.property.BooleanProperty;
|
import javafx.beans.property.*;
|
||||||
import javafx.beans.property.SimpleBooleanProperty;
|
|
||||||
import javafx.beans.property.SimpleObjectProperty;
|
|
||||||
import javafx.beans.property.SimpleStringProperty;
|
|
||||||
import javafx.beans.value.ObservableValue;
|
import javafx.beans.value.ObservableValue;
|
||||||
import javafx.css.PseudoClass;
|
import javafx.css.PseudoClass;
|
||||||
import javafx.scene.control.Button;
|
import javafx.scene.control.Button;
|
||||||
import javafx.scene.layout.Region;
|
import javafx.scene.layout.Region;
|
||||||
import javafx.scene.layout.VBox;
|
|
||||||
|
|
||||||
import atlantafx.base.theme.Styles;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
@ -37,22 +22,23 @@ public final class BrowserBookmarkComp extends SimpleComp {
|
||||||
private final ObservableValue<DataStoreEntry> selected;
|
private final ObservableValue<DataStoreEntry> selected;
|
||||||
private final Predicate<StoreEntryWrapper> applicable;
|
private final Predicate<StoreEntryWrapper> applicable;
|
||||||
private final BiConsumer<StoreEntryWrapper, BooleanProperty> action;
|
private final BiConsumer<StoreEntryWrapper, BooleanProperty> action;
|
||||||
|
private final Property<StoreCategoryWrapper> category;
|
||||||
|
private final Property<String> filter ;
|
||||||
|
|
||||||
public BrowserBookmarkComp(
|
public BrowserBookmarkComp(
|
||||||
ObservableValue<DataStoreEntry> selected,
|
ObservableValue<DataStoreEntry> selected,
|
||||||
Predicate<StoreEntryWrapper> applicable,
|
Predicate<StoreEntryWrapper> applicable,
|
||||||
BiConsumer<StoreEntryWrapper, BooleanProperty> action) {
|
BiConsumer<StoreEntryWrapper, BooleanProperty> action, Property<StoreCategoryWrapper> category, Property<String> filter
|
||||||
|
) {
|
||||||
this.selected = selected;
|
this.selected = selected;
|
||||||
this.applicable = applicable;
|
this.applicable = applicable;
|
||||||
this.action = action;
|
this.action = action;
|
||||||
|
this.category = category;
|
||||||
|
this.filter = filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Region createSimple() {
|
protected Region createSimple() {
|
||||||
var filterText = new SimpleStringProperty();
|
|
||||||
var selectedCategory = new SimpleObjectProperty<>(
|
|
||||||
StoreViewState.get().getActiveCategory().getValue());
|
|
||||||
|
|
||||||
BooleanProperty busy = new SimpleBooleanProperty(false);
|
BooleanProperty busy = new SimpleBooleanProperty(false);
|
||||||
BiConsumer<StoreSection, Comp<CompStructure<Button>>> augment = (s, comp) -> {
|
BiConsumer<StoreSection, Comp<CompStructure<Button>>> augment = (s, comp) -> {
|
||||||
comp.disable(Bindings.createBooleanBinding(
|
comp.disable(Bindings.createBooleanBinding(
|
||||||
|
@ -76,31 +62,14 @@ public final class BrowserBookmarkComp extends SimpleComp {
|
||||||
|
|
||||||
var section = new StoreSectionMiniComp(
|
var section = new StoreSectionMiniComp(
|
||||||
StoreSection.createTopLevel(
|
StoreSection.createTopLevel(
|
||||||
StoreViewState.get().getAllEntries(), this::filter, filterText, selectedCategory, StoreViewState.get().getEntriesListUpdateObservable()),
|
StoreViewState.get().getAllEntries(), this::filter, filter, category, StoreViewState.get().getEntriesListUpdateObservable()),
|
||||||
augment,
|
augment,
|
||||||
entryWrapper -> action.accept(entryWrapper, busy),
|
entryWrapper -> action.accept(entryWrapper, busy),
|
||||||
true);
|
true);
|
||||||
var category = new DataStoreCategoryChoiceComp(
|
|
||||||
StoreViewState.get().getAllConnectionsCategory(),
|
|
||||||
StoreViewState.get().getActiveCategory(),
|
|
||||||
selectedCategory)
|
|
||||||
.styleClass(Styles.LEFT_PILL)
|
|
||||||
.minWidth(Region.USE_PREF_SIZE);
|
|
||||||
var filter = new FilterComp(filterText).hgrow();
|
|
||||||
|
|
||||||
var top = new HorizontalComp(List.of(category, filter))
|
|
||||||
.styleClass("categories")
|
|
||||||
.apply(struc -> {
|
|
||||||
AppFont.medium(struc.get());
|
|
||||||
struc.get().setFillHeight(true);
|
|
||||||
})
|
|
||||||
.createRegion();
|
|
||||||
var r = section.vgrow().createRegion();
|
var r = section.vgrow().createRegion();
|
||||||
var content = new VBox(top, r);
|
r.getStyleClass().add("bookmark-list");
|
||||||
content.setFillWidth(true);
|
return r;
|
||||||
|
|
||||||
content.getStyleClass().add("bookmark-list");
|
|
||||||
return content;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean filter(StoreEntryWrapper w) {
|
private boolean filter(StoreEntryWrapper w) {
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
package io.xpipe.app.browser;
|
||||||
|
|
||||||
|
import atlantafx.base.theme.Styles;
|
||||||
|
import io.xpipe.app.comp.store.StoreCategoryWrapper;
|
||||||
|
import io.xpipe.app.comp.store.StoreViewState;
|
||||||
|
import io.xpipe.app.core.AppFont;
|
||||||
|
import io.xpipe.app.fxcomps.SimpleComp;
|
||||||
|
import io.xpipe.app.fxcomps.impl.FilterComp;
|
||||||
|
import io.xpipe.app.fxcomps.impl.HorizontalComp;
|
||||||
|
import io.xpipe.app.util.DataStoreCategoryChoiceComp;
|
||||||
|
import javafx.beans.property.Property;
|
||||||
|
import javafx.beans.property.SimpleObjectProperty;
|
||||||
|
import javafx.beans.property.SimpleStringProperty;
|
||||||
|
import javafx.scene.layout.Region;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public final class BrowserBookmarkHeaderComp extends SimpleComp {
|
||||||
|
|
||||||
|
private final Property<StoreCategoryWrapper> category = new SimpleObjectProperty<>(StoreViewState.get().getActiveCategory().getValue());
|
||||||
|
private final Property<String> filter = new SimpleStringProperty();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Region createSimple() {
|
||||||
|
var category = new DataStoreCategoryChoiceComp(
|
||||||
|
StoreViewState.get().getAllConnectionsCategory(),
|
||||||
|
StoreViewState.get().getActiveCategory(),
|
||||||
|
this.category)
|
||||||
|
.styleClass(Styles.LEFT_PILL)
|
||||||
|
.apply(struc -> AppFont.medium(struc.get()));
|
||||||
|
var filter = new FilterComp(this.filter).styleClass(Styles.RIGHT_PILL).apply(struc -> AppFont.medium(struc.get())).hgrow();
|
||||||
|
|
||||||
|
var top = new HorizontalComp(List.of(category, filter))
|
||||||
|
.apply(struc -> struc.get().setFillHeight(true))
|
||||||
|
.apply(struc -> {
|
||||||
|
((Region) struc.get().getChildren().get(0)).prefHeightProperty().bind(
|
||||||
|
((Region) struc.get().getChildren().get(1)).heightProperty());
|
||||||
|
})
|
||||||
|
.styleClass("bookmarks-header")
|
||||||
|
.createRegion();
|
||||||
|
return top;
|
||||||
|
}
|
||||||
|
}
|
|
@ -71,7 +71,6 @@ public class BrowserTransferComp extends SimpleComp {
|
||||||
return entry.getFileName() + " (" + name + ")";
|
return entry.getFileName() + " (" + name + ")";
|
||||||
},
|
},
|
||||||
syncAllDownloaded))
|
syncAllDownloaded))
|
||||||
.apply(struc -> struc.get().setMinHeight(150))
|
|
||||||
.grow(false, true);
|
.grow(false, true);
|
||||||
var dragNotice = new LabelComp(syncAllDownloaded.flatMap(
|
var dragNotice = new LabelComp(syncAllDownloaded.flatMap(
|
||||||
aBoolean -> aBoolean ? AppI18n.observable("dragLocalFiles") : AppI18n.observable("dragFiles")))
|
aBoolean -> aBoolean ? AppI18n.observable("dragLocalFiles") : AppI18n.observable("dragFiles")))
|
||||||
|
@ -101,7 +100,9 @@ public class BrowserTransferComp extends SimpleComp {
|
||||||
return p;
|
return p;
|
||||||
});
|
});
|
||||||
|
|
||||||
var listBox = new VerticalComp(List.of(list, dragNotice)).padding(new Insets(10, 10, 5, 10));
|
var listBox = new VerticalComp(List.of(list, dragNotice)).padding(new Insets(10, 10, 5, 10))
|
||||||
|
.apply(struc -> struc.get().setMinHeight(200))
|
||||||
|
.apply(struc -> struc.get().setMaxHeight(200));
|
||||||
var stack = LoadingOverlayComp.noProgress(
|
var stack = LoadingOverlayComp.noProgress(
|
||||||
new StackComp(List.of(backgroundStack, listBox, clearPane))
|
new StackComp(List.of(backgroundStack, listBox, clearPane))
|
||||||
.apply(DragOverPseudoClassAugment.create())
|
.apply(DragOverPseudoClassAugment.create())
|
||||||
|
|
|
@ -162,7 +162,7 @@ public class OpenFileSystemComp extends SimpleComp {
|
||||||
var statusBar = new BrowserStatusBarComp(model);
|
var statusBar = new BrowserStatusBarComp(model);
|
||||||
fileListElements.add(statusBar);
|
fileListElements.add(statusBar);
|
||||||
}
|
}
|
||||||
var fileList = new VerticalComp(fileListElements).apply(struc -> {
|
var fileList = new VerticalComp(fileListElements).styleClass("browser-content").apply(struc -> {
|
||||||
struc.get().focusedProperty().addListener((observable, oldValue, newValue) -> {
|
struc.get().focusedProperty().addListener((observable, oldValue, newValue) -> {
|
||||||
if (newValue) {
|
if (newValue) {
|
||||||
struc.get().getChildren().getFirst().requestFocus();
|
struc.get().getChildren().getFirst().requestFocus();
|
||||||
|
@ -170,7 +170,7 @@ public class OpenFileSystemComp extends SimpleComp {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
var home = new BrowserOverviewComp(model);
|
var home = new BrowserOverviewComp(model).styleClass("browser-content");
|
||||||
var stack = new MultiContentComp(Map.of(
|
var stack = new MultiContentComp(Map.of(
|
||||||
home,
|
home,
|
||||||
model.getCurrentPath().isNull(),
|
model.getCurrentPath().isNull(),
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package io.xpipe.app.browser.session;
|
package io.xpipe.app.browser.session;
|
||||||
|
|
||||||
import io.xpipe.app.browser.BrowserBookmarkComp;
|
import io.xpipe.app.browser.BrowserBookmarkComp;
|
||||||
|
import io.xpipe.app.browser.BrowserBookmarkHeaderComp;
|
||||||
import io.xpipe.app.browser.file.BrowserEntry;
|
import io.xpipe.app.browser.file.BrowserEntry;
|
||||||
import io.xpipe.app.browser.fs.OpenFileSystemComp;
|
import io.xpipe.app.browser.fs.OpenFileSystemComp;
|
||||||
import io.xpipe.app.browser.fs.OpenFileSystemModel;
|
import io.xpipe.app.browser.fs.OpenFileSystemModel;
|
||||||
|
@ -13,6 +14,7 @@ import io.xpipe.app.core.AppLayoutModel;
|
||||||
import io.xpipe.app.core.window.AppWindowHelper;
|
import io.xpipe.app.core.window.AppWindowHelper;
|
||||||
import io.xpipe.app.fxcomps.Comp;
|
import io.xpipe.app.fxcomps.Comp;
|
||||||
import io.xpipe.app.fxcomps.SimpleComp;
|
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.BindingsHelper;
|
||||||
import io.xpipe.app.fxcomps.util.PlatformThread;
|
import io.xpipe.app.fxcomps.util.PlatformThread;
|
||||||
import io.xpipe.app.storage.DataStoreEntryRef;
|
import io.xpipe.app.storage.DataStoreEntryRef;
|
||||||
|
@ -30,6 +32,7 @@ import javafx.scene.layout.Priority;
|
||||||
import javafx.scene.layout.Region;
|
import javafx.scene.layout.Region;
|
||||||
import javafx.scene.layout.StackPane;
|
import javafx.scene.layout.StackPane;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
@ -93,12 +96,15 @@ public class BrowserChooserComp extends SimpleComp {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var bookmarkTopBar = new BrowserBookmarkHeaderComp();
|
||||||
var bookmarksList = new BrowserBookmarkComp(
|
var bookmarksList = new BrowserBookmarkComp(
|
||||||
BindingsHelper.map(
|
BindingsHelper.map(
|
||||||
model.getSelectedEntry(), v -> v.getEntry().get()),
|
model.getSelectedEntry(), v -> v.getEntry().get()),
|
||||||
applicable,
|
applicable,
|
||||||
action)
|
action,
|
||||||
.vgrow();
|
bookmarkTopBar.getCategory(),
|
||||||
|
bookmarkTopBar.getFilter());
|
||||||
|
|
||||||
var stack = Comp.of(() -> {
|
var stack = Comp.of(() -> {
|
||||||
var s = new StackPane();
|
var s = new StackPane();
|
||||||
model.getSelectedEntry().subscribe(selected -> {
|
model.getSelectedEntry().subscribe(selected -> {
|
||||||
|
@ -112,7 +118,9 @@ public class BrowserChooserComp extends SimpleComp {
|
||||||
});
|
});
|
||||||
return s;
|
return s;
|
||||||
});
|
});
|
||||||
var splitPane = new SideSplitPaneComp(bookmarksList, stack)
|
|
||||||
|
var vertical = new VerticalComp(List.of(bookmarkTopBar, bookmarksList)).styleClass("left");
|
||||||
|
var splitPane = new SideSplitPaneComp(vertical, stack)
|
||||||
.withInitialWidth(AppLayoutModel.get().getSavedState().getBrowserConnectionsWidth())
|
.withInitialWidth(AppLayoutModel.get().getSavedState().getBrowserConnectionsWidth())
|
||||||
.withOnDividerChange(AppLayoutModel.get().getSavedState()::setBrowserConnectionsWidth)
|
.withOnDividerChange(AppLayoutModel.get().getSavedState()::setBrowserConnectionsWidth)
|
||||||
.styleClass("background")
|
.styleClass("background")
|
||||||
|
@ -172,6 +180,7 @@ public class BrowserChooserComp extends SimpleComp {
|
||||||
|
|
||||||
var r = dialogPane.createRegion();
|
var r = dialogPane.createRegion();
|
||||||
r.getStyleClass().add("browser");
|
r.getStyleClass().add("browser");
|
||||||
|
r.getStyleClass().add("chooser");
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,24 @@
|
||||||
package io.xpipe.app.browser.session;
|
package io.xpipe.app.browser.session;
|
||||||
|
|
||||||
import io.xpipe.app.browser.BrowserBookmarkComp;
|
import io.xpipe.app.browser.BrowserBookmarkComp;
|
||||||
|
import io.xpipe.app.browser.BrowserBookmarkHeaderComp;
|
||||||
import io.xpipe.app.browser.BrowserTransferComp;
|
import io.xpipe.app.browser.BrowserTransferComp;
|
||||||
import io.xpipe.app.comp.base.SideSplitPaneComp;
|
import io.xpipe.app.comp.base.SideSplitPaneComp;
|
||||||
import io.xpipe.app.comp.store.StoreEntryWrapper;
|
import io.xpipe.app.comp.store.StoreEntryWrapper;
|
||||||
import io.xpipe.app.core.AppLayoutModel;
|
import io.xpipe.app.core.AppLayoutModel;
|
||||||
import io.xpipe.app.fxcomps.SimpleComp;
|
import io.xpipe.app.fxcomps.SimpleComp;
|
||||||
|
import io.xpipe.app.fxcomps.impl.StackComp;
|
||||||
import io.xpipe.app.fxcomps.impl.VerticalComp;
|
import io.xpipe.app.fxcomps.impl.VerticalComp;
|
||||||
import io.xpipe.app.fxcomps.util.BindingsHelper;
|
import io.xpipe.app.fxcomps.util.BindingsHelper;
|
||||||
import io.xpipe.app.fxcomps.util.PlatformThread;
|
import io.xpipe.app.fxcomps.util.PlatformThread;
|
||||||
import io.xpipe.app.util.ThreadHelper;
|
import io.xpipe.app.util.ThreadHelper;
|
||||||
import io.xpipe.core.store.ShellStore;
|
import io.xpipe.core.store.ShellStore;
|
||||||
|
import javafx.application.Platform;
|
||||||
import javafx.beans.binding.Bindings;
|
import javafx.beans.binding.Bindings;
|
||||||
import javafx.beans.property.BooleanProperty;
|
import javafx.beans.property.BooleanProperty;
|
||||||
|
import javafx.beans.property.SimpleDoubleProperty;
|
||||||
import javafx.scene.layout.Region;
|
import javafx.scene.layout.Region;
|
||||||
|
import javafx.scene.shape.Rectangle;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
|
@ -60,12 +64,23 @@ public class BrowserSessionComp extends SimpleComp {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var bookmarkTopBar = new BrowserBookmarkHeaderComp();
|
||||||
var bookmarksList = new BrowserBookmarkComp(
|
var bookmarksList = new BrowserBookmarkComp(
|
||||||
BindingsHelper.map(
|
BindingsHelper.map(
|
||||||
model.getSelectedEntry(), v -> v.getEntry().get()),
|
model.getSelectedEntry(), v -> v.getEntry().get()),
|
||||||
applicable,
|
applicable,
|
||||||
action)
|
action,
|
||||||
.vgrow();
|
bookmarkTopBar.getCategory(),
|
||||||
|
bookmarkTopBar.getFilter());
|
||||||
|
var bookmarksContainer = new StackComp(List.of(bookmarksList)).styleClass("bookmarks-container");
|
||||||
|
bookmarksContainer.apply(struc -> {
|
||||||
|
var rec = new Rectangle();
|
||||||
|
rec.widthProperty().bind(struc.get().widthProperty());
|
||||||
|
rec.heightProperty().bind(struc.get().heightProperty());
|
||||||
|
rec.setArcHeight(7);
|
||||||
|
rec.setArcWidth(7);
|
||||||
|
struc.get().getChildren().getFirst().setClip(rec);
|
||||||
|
}).vgrow();
|
||||||
var localDownloadStage = new BrowserTransferComp(model.getLocalTransfersStage())
|
var localDownloadStage = new BrowserTransferComp(model.getLocalTransfersStage())
|
||||||
.hide(PlatformThread.sync(Bindings.createBooleanBinding(
|
.hide(PlatformThread.sync(Bindings.createBooleanBinding(
|
||||||
() -> {
|
() -> {
|
||||||
|
@ -79,19 +94,39 @@ public class BrowserSessionComp extends SimpleComp {
|
||||||
model.getSelectedEntry())));
|
model.getSelectedEntry())));
|
||||||
localDownloadStage.prefHeight(200);
|
localDownloadStage.prefHeight(200);
|
||||||
localDownloadStage.maxHeight(200);
|
localDownloadStage.maxHeight(200);
|
||||||
var vertical = new VerticalComp(List.of(bookmarksList, localDownloadStage));
|
var vertical = new VerticalComp(List.of(bookmarkTopBar, bookmarksContainer, localDownloadStage)).styleClass("left");
|
||||||
|
|
||||||
var tabs = new BrowserSessionTabsComp(model);
|
var split = new SimpleDoubleProperty();
|
||||||
|
var tabs = new BrowserSessionTabsComp(model, split).apply(struc -> struc.get().setViewOrder(1))
|
||||||
|
.apply(struc -> struc.get().setPickOnBounds(false));
|
||||||
var splitPane = new SideSplitPaneComp(vertical, tabs)
|
var splitPane = new SideSplitPaneComp(vertical, tabs)
|
||||||
.withInitialWidth(AppLayoutModel.get().getSavedState().getBrowserConnectionsWidth())
|
.withInitialWidth(AppLayoutModel.get().getSavedState().getBrowserConnectionsWidth())
|
||||||
.withOnDividerChange(AppLayoutModel.get().getSavedState()::setBrowserConnectionsWidth)
|
.withOnDividerChange(d -> {
|
||||||
|
AppLayoutModel.get().getSavedState().setBrowserConnectionsWidth(d);
|
||||||
|
split.set(d);
|
||||||
|
})
|
||||||
.apply(struc -> {
|
.apply(struc -> {
|
||||||
struc.getLeft().setMinWidth(200);
|
struc.getLeft().setMinWidth(200);
|
||||||
struc.getLeft().setMaxWidth(500);
|
struc.getLeft().setMaxWidth(500);
|
||||||
|
struc.get().setPickOnBounds(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
splitPane.apply(struc -> {
|
||||||
|
struc.get().skinProperty().subscribe(newValue -> {
|
||||||
|
if (newValue != null) {
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
struc.get().getChildrenUnmodifiable().forEach(node -> {
|
||||||
|
node.setClip(null);
|
||||||
|
node.setPickOnBounds(false);
|
||||||
|
});
|
||||||
|
struc.get().lookupAll(".split-pane-divider").forEach(node -> node.setViewOrder(1));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
var r = splitPane.createRegion();
|
var r = splitPane.createRegion();
|
||||||
r.getStyleClass().add("browser");
|
r.getStyleClass().add("browser");
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,10 @@ import javafx.application.Platform;
|
||||||
import javafx.beans.binding.Bindings;
|
import javafx.beans.binding.Bindings;
|
||||||
import javafx.beans.property.SimpleBooleanProperty;
|
import javafx.beans.property.SimpleBooleanProperty;
|
||||||
import javafx.beans.property.SimpleStringProperty;
|
import javafx.beans.property.SimpleStringProperty;
|
||||||
|
import javafx.beans.value.ObservableDoubleValue;
|
||||||
import javafx.beans.value.ObservableValue;
|
import javafx.beans.value.ObservableValue;
|
||||||
import javafx.collections.ListChangeListener;
|
import javafx.collections.ListChangeListener;
|
||||||
|
import javafx.geometry.Insets;
|
||||||
import javafx.geometry.Pos;
|
import javafx.geometry.Pos;
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
import javafx.scene.control.Tab;
|
import javafx.scene.control.Tab;
|
||||||
|
@ -40,9 +42,11 @@ import static javafx.scene.control.TabPane.TabClosingPolicy.ALL_TABS;
|
||||||
public class BrowserSessionTabsComp extends SimpleComp {
|
public class BrowserSessionTabsComp extends SimpleComp {
|
||||||
|
|
||||||
private final BrowserSessionModel model;
|
private final BrowserSessionModel model;
|
||||||
|
private final ObservableDoubleValue leftPadding;
|
||||||
|
|
||||||
public BrowserSessionTabsComp(BrowserSessionModel model) {
|
public BrowserSessionTabsComp(BrowserSessionModel model, ObservableDoubleValue leftPadding) {
|
||||||
this.model = model;
|
this.model = model;
|
||||||
|
this.leftPadding = leftPadding;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Region createSimple() {
|
public Region createSimple() {
|
||||||
|
@ -67,7 +71,28 @@ public class BrowserSessionTabsComp extends SimpleComp {
|
||||||
Styles.toggleStyleClass(tabs, TabPane.STYLE_CLASS_FLOATING);
|
Styles.toggleStyleClass(tabs, TabPane.STYLE_CLASS_FLOATING);
|
||||||
toggleStyleClass(tabs, DENSE);
|
toggleStyleClass(tabs, DENSE);
|
||||||
|
|
||||||
var map = new HashMap<BrowserSessionTab<?>, Tab>();
|
|
||||||
|
tabs.skinProperty().subscribe(newValue -> {
|
||||||
|
if (newValue != null) {
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
tabs.setClip(null);
|
||||||
|
tabs.setPickOnBounds(false);
|
||||||
|
tabs.lookupAll(".tab-header-area").forEach(node -> {
|
||||||
|
node.setClip(null);
|
||||||
|
node.setPickOnBounds(false);
|
||||||
|
});
|
||||||
|
tabs.lookupAll(".headers-region").forEach(node -> {
|
||||||
|
node.setClip(null);
|
||||||
|
node.setPickOnBounds(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
Region headerArea = (Region) tabs.lookup(".tab-header-area");
|
||||||
|
headerArea.paddingProperty().bind(Bindings.createObjectBinding(() -> new Insets(0, 0, 0, -leftPadding.get() + 2), leftPadding));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var map = new HashMap<BrowserSessionTab<?>, Tab>();
|
||||||
|
|
||||||
// Restore state
|
// Restore state
|
||||||
model.getSessionEntries().forEach(v -> {
|
model.getSessionEntries().forEach(v -> {
|
||||||
|
@ -215,7 +240,8 @@ public class BrowserSessionTabsComp extends SimpleComp {
|
||||||
PlatformThread.sync(model.getBusy())));
|
PlatformThread.sync(model.getBusy())));
|
||||||
tab.setText(model.getName());
|
tab.setText(model.getName());
|
||||||
|
|
||||||
tab.setContent(model.comp().createRegion());
|
Comp<?> comp = model.comp();
|
||||||
|
tab.setContent(comp.createRegion());
|
||||||
|
|
||||||
var id = UUID.randomUUID().toString();
|
var id = UUID.randomUUID().toString();
|
||||||
tab.setId(id);
|
tab.setId(id);
|
||||||
|
|
|
@ -6,18 +6,17 @@ import io.xpipe.app.fxcomps.util.DerivedObservableList;
|
||||||
import io.xpipe.app.prefs.AppPrefs;
|
import io.xpipe.app.prefs.AppPrefs;
|
||||||
import io.xpipe.app.storage.DataStorage;
|
import io.xpipe.app.storage.DataStorage;
|
||||||
import io.xpipe.app.storage.DataStoreEntry;
|
import io.xpipe.app.storage.DataStoreEntry;
|
||||||
|
|
||||||
import javafx.beans.binding.Bindings;
|
import javafx.beans.binding.Bindings;
|
||||||
import javafx.beans.property.SimpleBooleanProperty;
|
import javafx.beans.property.SimpleBooleanProperty;
|
||||||
import javafx.beans.value.ObservableBooleanValue;
|
import javafx.beans.value.ObservableBooleanValue;
|
||||||
import javafx.beans.value.ObservableIntegerValue;
|
import javafx.beans.value.ObservableIntegerValue;
|
||||||
import javafx.beans.value.ObservableStringValue;
|
|
||||||
import javafx.beans.value.ObservableValue;
|
import javafx.beans.value.ObservableValue;
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
|
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.function.ToIntFunction;
|
import java.util.function.ToIntFunction;
|
||||||
|
|
||||||
|
@ -111,7 +110,7 @@ public class StoreSection {
|
||||||
public static StoreSection createTopLevel(
|
public static StoreSection createTopLevel(
|
||||||
DerivedObservableList<StoreEntryWrapper> all,
|
DerivedObservableList<StoreEntryWrapper> all,
|
||||||
Predicate<StoreEntryWrapper> entryFilter,
|
Predicate<StoreEntryWrapper> entryFilter,
|
||||||
ObservableStringValue filterString,
|
ObservableValue<String> filterString,
|
||||||
ObservableValue<StoreCategoryWrapper> category,
|
ObservableValue<StoreCategoryWrapper> category,
|
||||||
ObservableIntegerValue updateObservable
|
ObservableIntegerValue updateObservable
|
||||||
) {
|
) {
|
||||||
|
@ -127,7 +126,7 @@ public class StoreSection {
|
||||||
var shown = ordered.filtered(
|
var shown = ordered.filtered(
|
||||||
section -> {
|
section -> {
|
||||||
// matches filter
|
// matches filter
|
||||||
return (filterString == null || section.matchesFilter(filterString.get()))
|
return (filterString == null || section.matchesFilter(filterString.getValue()))
|
||||||
&&
|
&&
|
||||||
// matches selector
|
// matches selector
|
||||||
(section.anyMatches(entryFilter))
|
(section.anyMatches(entryFilter))
|
||||||
|
@ -148,7 +147,7 @@ public class StoreSection {
|
||||||
int depth,
|
int depth,
|
||||||
DerivedObservableList<StoreEntryWrapper> all,
|
DerivedObservableList<StoreEntryWrapper> all,
|
||||||
Predicate<StoreEntryWrapper> entryFilter,
|
Predicate<StoreEntryWrapper> entryFilter,
|
||||||
ObservableStringValue filterString,
|
ObservableValue<String> filterString,
|
||||||
ObservableValue<StoreCategoryWrapper> category,
|
ObservableValue<StoreCategoryWrapper> category,
|
||||||
ObservableIntegerValue updateObservable) {
|
ObservableIntegerValue updateObservable) {
|
||||||
if (e.getEntry().getValidity() == DataStoreEntry.Validity.LOAD_FAILED) {
|
if (e.getEntry().getValidity() == DataStoreEntry.Validity.LOAD_FAILED) {
|
||||||
|
@ -185,8 +184,8 @@ public class StoreSection {
|
||||||
section -> {
|
section -> {
|
||||||
// matches filter
|
// matches filter
|
||||||
return (filterString == null
|
return (filterString == null
|
||||||
|| section.matchesFilter(filterString.get())
|
|| section.matchesFilter(filterString.getValue())
|
||||||
|| l.stream().anyMatch(p -> p.matchesFilter(filterString.get())))
|
|| l.stream().anyMatch(p -> p.matchesFilter(filterString.getValue())))
|
||||||
&&
|
&&
|
||||||
// matches selector
|
// matches selector
|
||||||
section.anyMatches(entryFilter)
|
section.anyMatches(entryFilter)
|
||||||
|
|
|
@ -1,18 +1,11 @@
|
||||||
|
|
||||||
.bookmark-list > .categories {
|
|
||||||
-fx-padding: 1em;
|
|
||||||
-fx-background-color: -color-bg-default;
|
|
||||||
-fx-border-color: -color-border-default;
|
|
||||||
-fx-border-width: 0 0 1 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.root.nord .bookmark-list .filter-comp {
|
.root.nord .bookmarks-header .filter-comp {
|
||||||
-fx-border-radius: 0;
|
-fx-border-radius: 0;
|
||||||
-fx-background-radius: 0;
|
-fx-background-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bookmark-list .filter-comp {
|
.bookmarks-header .filter-comp {
|
||||||
-fx-border-width: 1;
|
-fx-border-width: 1;
|
||||||
-fx-border-radius: 0 4px 4px 0;
|
-fx-border-radius: 0 4px 4px 0;
|
||||||
-fx-background-radius: 0 4px 4px 0;
|
-fx-background-radius: 0 4px 4px 0;
|
||||||
|
@ -24,3 +17,20 @@
|
||||||
-fx-font-weight: BOLD;
|
-fx-font-weight: BOLD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bookmark-list .store-section-mini-comp:top {
|
||||||
|
-fx-padding: 0 0 0 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bookmarks-container {
|
||||||
|
-fx-background-color: -color-border-default, -color-bg-default;
|
||||||
|
-fx-background-radius: 4 0 0 4;
|
||||||
|
-fx-background-insets: 0 8 0 6, 1 9 1 7;
|
||||||
|
-fx-padding: 1 1 1 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bookmarks-header {
|
||||||
|
-fx-min-height: 3.5em;
|
||||||
|
-fx-pref-height: 3.5em;
|
||||||
|
-fx-max-height: 3.5em;
|
||||||
|
-fx-padding: 9 6;
|
||||||
|
}
|
|
@ -8,10 +8,18 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.download-background {
|
.download-background {
|
||||||
-fx-border-color: -color-border-default;
|
|
||||||
-fx-border-width: 1px 0 0 0;
|
|
||||||
-fx-padding: 1em;
|
-fx-padding: 1em;
|
||||||
-fx-background-color: -color-bg-default;
|
}
|
||||||
|
|
||||||
|
.transfer {
|
||||||
|
-fx-padding: 9px 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transfer > * {
|
||||||
|
-fx-border-radius: 4;
|
||||||
|
-fx-border-color: -color-border-default;
|
||||||
|
-fx-border-width: 1;
|
||||||
|
-fx-background-color: -color-bg-subtle;
|
||||||
}
|
}
|
||||||
|
|
||||||
.transfer .button {
|
.transfer .button {
|
||||||
|
@ -23,11 +31,21 @@
|
||||||
-fx-padding: 0.1em 0.2em;
|
-fx-padding: 0.1em 0.2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.root.nord .transfer > * {
|
||||||
|
-fx-background-radius: 0;
|
||||||
|
-fx-border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.transfer .button:hover {
|
.transfer .button:hover {
|
||||||
-fx-background-color: -color-bg-subtle;
|
-fx-background-color: -color-bg-subtle;
|
||||||
-fx-opacity: 1.0;
|
-fx-opacity: 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.browser .welcome {
|
||||||
|
-fx-border-color: -color-border-default, -color-bg-inset;
|
||||||
|
-fx-border-width: 43 0 0 0, 42 0 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
.browser .welcome .button:hover {
|
.browser .welcome .button:hover {
|
||||||
-fx-background-color: -color-neutral-muted;
|
-fx-background-color: -color-neutral-muted;
|
||||||
}
|
}
|
||||||
|
@ -36,10 +54,9 @@
|
||||||
-fx-padding: 0.6em 0 0.6em 0;
|
-fx-padding: 0.6em 0 0.6em 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.browser .overview {
|
.browser .browser-content.overview {
|
||||||
-fx-spacing: 1.5em;
|
-fx-spacing: 1.5em;
|
||||||
-fx-padding: 1.5em;
|
-fx-padding: 1.5em;
|
||||||
-fx-background-color: -color-bg-default;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.selected-file-list {
|
.selected-file-list {
|
||||||
|
@ -64,8 +81,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.browser .top-bar {
|
.browser .top-bar {
|
||||||
-fx-border-width: 1 0 1 0;
|
-fx-min-height: 3.5em;
|
||||||
-fx-border-color: -color-border-default;
|
-fx-pref-height: 3.5em;
|
||||||
|
-fx-max-height: 3.5em;
|
||||||
-fx-padding: 9px 6px;
|
-fx-padding: 9px 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,7 +164,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.browser .tab-pane {
|
.browser .tab-pane {
|
||||||
-fx-border-width: 0 0 0 1px;
|
-fx-border-width: 0 0 0 0px;
|
||||||
-fx-border-color: -color-border-default;
|
-fx-border-color: -color-border-default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,7 +176,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.browser .tab-content-area {
|
.browser .tab-content-area {
|
||||||
-fx-padding: 0;
|
-fx-border-width: 2 0 0 0;
|
||||||
|
-fx-border-color: -color-border-default;
|
||||||
|
-fx-padding: -1 0 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.browser .singular {
|
.browser .singular {
|
||||||
|
@ -169,6 +189,23 @@
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.browser .tab-header-area {
|
||||||
|
-fx-min-height: 42;
|
||||||
|
-fx-pref-height: 42;
|
||||||
|
-fx-max-height: 42;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.browser .left {
|
||||||
|
-fx-border-color: -color-border-default, -color-bg-inset;
|
||||||
|
-fx-border-width: 43 0 0 0, 42 0 0 0;
|
||||||
|
-fx-background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.browser.chooser .left {
|
||||||
|
-fx-border-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.browser .tab-header-area {
|
.browser .tab-header-area {
|
||||||
-fx-background-color: -color-bg-inset;
|
-fx-background-color: -color-bg-inset;
|
||||||
}
|
}
|
||||||
|
@ -177,7 +214,29 @@
|
||||||
-fx-background-radius: 0 10 0 0;
|
-fx-background-radius: 0 10 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.browser .browser-content {
|
||||||
|
-fx-padding: 10 0 0 0;
|
||||||
|
-fx-border-radius: 10 0 0 0;
|
||||||
|
-fx-background-radius: 10 0 0 0;
|
||||||
|
-fx-background-color: -color-bg-subtle;
|
||||||
|
-fx-border-width: 1 0 0 1;
|
||||||
|
-fx-border-color: -color-border-default;
|
||||||
|
}
|
||||||
|
|
||||||
.browser .table-view {
|
.browser .table-view {
|
||||||
|
-fx-border-width: 0 0 0 0px;
|
||||||
|
-fx-border-color: -color-border-default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.browser .split-pane-divider {
|
||||||
|
-fx-border-color: -color-border-default, -color-bg-inset;
|
||||||
|
-fx-padding: 0 3;
|
||||||
|
-fx-border-width: 43 0 0 0, 42 0 0 0;
|
||||||
|
-fx-opacity: 1.0;
|
||||||
|
-fx-background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.browser.chooser .split-pane-divider {
|
||||||
-fx-border-width: 0;
|
-fx-border-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,7 +246,14 @@
|
||||||
|
|
||||||
.table-view .column-header-background .label {
|
.table-view .column-header-background .label {
|
||||||
-fx-font-size: 0.9em;
|
-fx-font-size: 0.9em;
|
||||||
-fx-font-weight: NORMAL;
|
-fx-font-weight: bolder;
|
||||||
|
-fx-opacity: 0.9;
|
||||||
|
-fx-padding: 0 0 0 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
.browser .table-row-cell {
|
||||||
|
-fx-border-width: 0 0 0 5;
|
||||||
|
-fx-border-color: -color-bg-subtle;
|
||||||
}
|
}
|
||||||
|
|
||||||
.browser .table-row-cell:empty {
|
.browser .table-row-cell:empty {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
.scroll-bar:vertical {
|
.scroll-bar:vertical {
|
||||||
-fx-pref-width: 0.3em;
|
-fx-pref-width: 0.4em;
|
||||||
-fx-padding: 0.4em 0 0.3em 0;
|
-fx-padding: 0.4em 1 0.3em 1;
|
||||||
-fx-background-color: transparent;
|
-fx-background-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Binary file not shown.
Loading…
Reference in a new issue