Refactor and cleanup

This commit is contained in:
crschnick
2024-11-07 19:26:59 +00:00
parent 9896f5e82e
commit bcdf8e098b
276 changed files with 1464 additions and 2256 deletions

View File

@@ -1,6 +1,6 @@
package io.xpipe.app.beacon.impl;
import io.xpipe.app.browser.session.BrowserSessionModel;
import io.xpipe.app.browser.BrowserFullSessionModel;
import io.xpipe.app.core.AppLayoutModel;
import io.xpipe.app.storage.DataStorage;
import io.xpipe.beacon.BeaconClientException;
@@ -19,7 +19,7 @@ public class ConnectionBrowseExchangeImpl extends ConnectionBrowseExchange {
if (!(e.getStore() instanceof FileSystemStore)) {
throw new BeaconClientException("Not a file system connection");
}
BrowserSessionModel.DEFAULT.openFileSystemSync(
BrowserFullSessionModel.DEFAULT.openFileSystemSync(
e.ref(), msg.getDirectory() != null ? ignored -> msg.getDirectory() : null, null, true);
AppLayoutModel.get().selectBrowser();
return Response.builder().build();

View File

@@ -1,7 +1,7 @@
package io.xpipe.app.beacon.impl;
import io.xpipe.app.core.mode.OperationMode;
import io.xpipe.app.launcher.LauncherInput;
import io.xpipe.app.core.launcher.LauncherInput;
import io.xpipe.app.util.PlatformState;
import io.xpipe.beacon.BeaconServerException;
import io.xpipe.beacon.api.DaemonOpenExchange;

View File

@@ -1,4 +1,4 @@
package io.xpipe.app.browser.session;
package io.xpipe.app.browser;
import io.xpipe.app.util.BooleanScope;
import io.xpipe.app.util.ThreadHelper;

View File

@@ -1,21 +1,21 @@
package io.xpipe.app.browser.session;
package io.xpipe.app.browser;
import io.xpipe.app.browser.BrowserBookmarkComp;
import io.xpipe.app.browser.BrowserBookmarkHeaderComp;
import io.xpipe.app.browser.file.BrowserConnectionListComp;
import io.xpipe.app.browser.file.BrowserConnectionListFilterComp;
import io.xpipe.app.browser.file.BrowserEntry;
import io.xpipe.app.browser.fs.OpenFileSystemComp;
import io.xpipe.app.browser.fs.OpenFileSystemModel;
import io.xpipe.app.browser.file.BrowserFileSystemTabComp;
import io.xpipe.app.browser.file.BrowserFileSystemTabModel;
import io.xpipe.app.comp.base.DialogComp;
import io.xpipe.app.comp.base.LeftSplitPaneComp;
import io.xpipe.app.comp.store.StoreEntryWrapper;
import io.xpipe.app.core.AppFont;
import io.xpipe.app.core.AppLayoutModel;
import io.xpipe.app.ext.ShellStore;
import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.fxcomps.impl.StackComp;
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.comp.Comp;
import io.xpipe.app.comp.base.StackComp;
import io.xpipe.app.comp.base.VerticalComp;
import io.xpipe.app.util.BindingsHelper;
import io.xpipe.app.util.PlatformThread;
import io.xpipe.app.storage.DataStoreEntryRef;
import io.xpipe.app.util.FileReference;
import io.xpipe.app.util.ThreadHelper;
@@ -37,12 +37,12 @@ import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.Supplier;
public class BrowserChooserComp extends DialogComp {
public class BrowserFileChooserSessionComp extends DialogComp {
private final Stage stage;
private final BrowserFileChooserModel model;
private final BrowserFileChooserSessionModel model;
public BrowserChooserComp(Stage stage, BrowserFileChooserModel model) {
public BrowserFileChooserSessionComp(Stage stage, BrowserFileChooserSessionModel model) {
this.stage = stage;
this.model = model;
}
@@ -50,9 +50,9 @@ public class BrowserChooserComp extends DialogComp {
public static void openSingleFile(
Supplier<DataStoreEntryRef<? extends FileSystemStore>> store, Consumer<FileReference> file, boolean save) {
PlatformThread.runLaterIfNeeded(() -> {
var model = new BrowserFileChooserModel(OpenFileSystemModel.SelectionMode.SINGLE_FILE);
var model = new BrowserFileChooserSessionModel(BrowserFileSystemTabModel.SelectionMode.SINGLE_FILE);
DialogComp.showWindow(save ? "saveFileTitle" : "openFileTitle", stage -> {
var comp = new BrowserChooserComp(stage, model);
var comp = new BrowserFileChooserSessionComp(stage, model);
comp.apply(struc -> struc.get().setPrefSize(1200, 700))
.apply(struc -> AppFont.normal(struc.get()))
.styleClass("browser")
@@ -114,8 +114,8 @@ public class BrowserChooserComp extends DialogComp {
});
};
var bookmarkTopBar = new BrowserBookmarkHeaderComp();
var bookmarksList = new BrowserBookmarkComp(
var bookmarkTopBar = new BrowserConnectionListFilterComp();
var bookmarksList = new BrowserConnectionListComp(
BindingsHelper.map(model.getSelectedEntry(), v -> v.getEntry().get()),
applicable,
action,
@@ -138,7 +138,7 @@ public class BrowserChooserComp extends DialogComp {
model.getSelectedEntry().subscribe(selected -> {
PlatformThread.runLaterIfNeeded(() -> {
if (selected != null) {
s.getChildren().setAll(new OpenFileSystemComp(selected, false).createRegion());
s.getChildren().setAll(new BrowserFileSystemTabComp(selected, false).createRegion());
} else {
s.getChildren().clear();
}

View File

@@ -1,8 +1,8 @@
package io.xpipe.app.browser.session;
package io.xpipe.app.browser;
import io.xpipe.app.browser.file.BrowserEntry;
import io.xpipe.app.browser.fs.OpenFileSystemModel;
import io.xpipe.app.fxcomps.util.DerivedObservableList;
import io.xpipe.app.browser.file.BrowserFileSystemTabModel;
import io.xpipe.app.util.DerivedObservableList;
import io.xpipe.app.storage.DataStoreEntryRef;
import io.xpipe.app.util.BooleanScope;
import io.xpipe.app.util.FileReference;
@@ -24,15 +24,15 @@ import java.util.List;
import java.util.function.Consumer;
@Getter
public class BrowserFileChooserModel extends BrowserAbstractSessionModel<OpenFileSystemModel> {
public class BrowserFileChooserSessionModel extends BrowserAbstractSessionModel<BrowserFileSystemTabModel> {
private final OpenFileSystemModel.SelectionMode selectionMode;
private final BrowserFileSystemTabModel.SelectionMode selectionMode;
private final ObservableList<BrowserEntry> fileSelection = FXCollections.observableArrayList();
@Setter
private Consumer<List<FileReference>> onFinish;
public BrowserFileChooserModel(OpenFileSystemModel.SelectionMode selectionMode) {
public BrowserFileChooserSessionModel(BrowserFileSystemTabModel.SelectionMode selectionMode) {
this.selectionMode = selectionMode;
selectedEntry.addListener((observable, oldValue, newValue) -> {
if (newValue == null) {
@@ -48,7 +48,7 @@ public class BrowserFileChooserModel extends BrowserAbstractSessionModel<OpenFil
public void finishChooser() {
var chosen = new ArrayList<>(fileSelection);
synchronized (BrowserFileChooserModel.this) {
synchronized (BrowserFileChooserSessionModel.this) {
var open = selectedEntry.getValue();
if (open != null) {
ThreadHelper.runAsync(() -> {
@@ -66,7 +66,7 @@ public class BrowserFileChooserModel extends BrowserAbstractSessionModel<OpenFil
}
public void finishWithoutChoice() {
synchronized (BrowserFileChooserModel.this) {
synchronized (BrowserFileChooserSessionModel.this) {
var open = selectedEntry.getValue();
if (open != null) {
ThreadHelper.runAsync(() -> {
@@ -78,20 +78,20 @@ public class BrowserFileChooserModel extends BrowserAbstractSessionModel<OpenFil
public void openFileSystemAsync(
DataStoreEntryRef<? extends FileSystemStore> store,
FailableFunction<OpenFileSystemModel, String, Exception> path,
FailableFunction<BrowserFileSystemTabModel, String, Exception> path,
BooleanProperty externalBusy) {
if (store == null) {
return;
}
ThreadHelper.runFailableAsync(() -> {
OpenFileSystemModel model;
BrowserFileSystemTabModel model;
try (var b = new BooleanScope(externalBusy != null ? externalBusy : new SimpleBooleanProperty()).start()) {
model = new OpenFileSystemModel(this, store, selectionMode);
model = new BrowserFileSystemTabModel(this, store, selectionMode);
model.init();
// Prevent multiple calls from interfering with each other
synchronized (BrowserFileChooserModel.this) {
synchronized (BrowserFileChooserSessionModel.this) {
selectedEntry.setValue(model);
sessionEntries.add(model);
}

View File

@@ -1,21 +1,21 @@
package io.xpipe.app.browser.session;
package io.xpipe.app.browser;
import io.xpipe.app.browser.BrowserBookmarkComp;
import io.xpipe.app.browser.BrowserBookmarkHeaderComp;
import io.xpipe.app.browser.BrowserTransferComp;
import io.xpipe.app.browser.file.BrowserConnectionListComp;
import io.xpipe.app.browser.file.BrowserConnectionListFilterComp;
import io.xpipe.app.browser.file.BrowserTransferComp;
import io.xpipe.app.comp.base.LoadingOverlayComp;
import io.xpipe.app.comp.base.LeftSplitPaneComp;
import io.xpipe.app.comp.store.StoreEntryWrapper;
import io.xpipe.app.core.AppLayoutModel;
import io.xpipe.app.ext.ShellStore;
import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.fxcomps.CompStructure;
import io.xpipe.app.fxcomps.SimpleComp;
import io.xpipe.app.fxcomps.impl.AnchorComp;
import io.xpipe.app.fxcomps.impl.StackComp;
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.comp.Comp;
import io.xpipe.app.comp.CompStructure;
import io.xpipe.app.comp.SimpleComp;
import io.xpipe.app.comp.base.AnchorComp;
import io.xpipe.app.comp.base.StackComp;
import io.xpipe.app.comp.base.VerticalComp;
import io.xpipe.app.util.BindingsHelper;
import io.xpipe.app.util.PlatformThread;
import io.xpipe.app.util.ThreadHelper;
import javafx.application.Platform;
@@ -33,11 +33,11 @@ import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Predicate;
public class BrowserSessionComp extends SimpleComp {
public class BrowserFullSessionComp extends SimpleComp {
private final BrowserSessionModel model;
private final BrowserFullSessionModel model;
public BrowserSessionComp(BrowserSessionModel model) {
public BrowserFullSessionComp(BrowserFullSessionModel model) {
this.model = model;
}
@@ -129,8 +129,8 @@ public class BrowserSessionComp extends SimpleComp {
});
};
var bookmarkTopBar = new BrowserBookmarkHeaderComp();
var bookmarksList = new BrowserBookmarkComp(
var bookmarkTopBar = new BrowserConnectionListFilterComp();
var bookmarksList = new BrowserConnectionListComp(
BindingsHelper.map(
model.getSelectedEntry(),
v -> v instanceof BrowserStoreSessionTab<?> st

View File

@@ -1,11 +1,10 @@
package io.xpipe.app.browser.session;
package io.xpipe.app.browser;
import io.xpipe.app.browser.BrowserHomeTabModel;
import io.xpipe.app.browser.BrowserSavedState;
import io.xpipe.app.browser.BrowserSavedStateImpl;
import io.xpipe.app.browser.BrowserTransferModel;
import io.xpipe.app.browser.fs.OpenFileSystemModel;
import io.xpipe.app.fxcomps.util.BindingsHelper;
import io.xpipe.app.browser.file.BrowserHistoryTabModel;
import io.xpipe.app.browser.file.BrowserHistorySavedState;
import io.xpipe.app.browser.file.BrowserHistorySavedStateImpl;
import io.xpipe.app.browser.file.BrowserTransferModel;
import io.xpipe.app.browser.file.BrowserFileSystemTabModel;
import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.storage.DataStoreEntryRef;
import io.xpipe.app.util.BooleanScope;
@@ -27,12 +26,12 @@ import lombok.Getter;
import java.util.*;
@Getter
public class BrowserSessionModel extends BrowserAbstractSessionModel<BrowserSessionTab> {
public class BrowserFullSessionModel extends BrowserAbstractSessionModel<BrowserSessionTab> {
public static final BrowserSessionModel DEFAULT = new BrowserSessionModel();
public static final BrowserFullSessionModel DEFAULT = new BrowserFullSessionModel();
static {
DEFAULT.getSessionEntries().add(new BrowserHomeTabModel(DEFAULT));
DEFAULT.getSessionEntries().add(new BrowserHistoryTabModel(DEFAULT));
}
private final BrowserTransferModel localTransfersStage = new BrowserTransferModel(this);
@@ -66,7 +65,7 @@ public class BrowserSessionModel extends BrowserAbstractSessionModel<BrowserSess
}, globalPinnedTab, selectedEntry, splits);
}
public BrowserSessionModel() {
public BrowserFullSessionModel() {
sessionEntries.addListener((ListChangeListener<? super BrowserSessionTab>) c -> {
var v = globalPinnedTab.getValue();
if (v != null && !c.getList().contains(v)) {
@@ -125,7 +124,7 @@ public class BrowserSessionModel extends BrowserAbstractSessionModel<BrowserSess
});
}
public void restoreState(BrowserSavedState state) {
public void restoreState(BrowserHistorySavedState state) {
ThreadHelper.runAsync(() -> {
var l = new ArrayList<>(state.getEntries());
l.forEach(e -> {
@@ -136,7 +135,7 @@ public class BrowserSessionModel extends BrowserAbstractSessionModel<BrowserSess
});
}
public void restoreStateAsync(BrowserSavedState.Entry e, BooleanProperty busy) {
public void restoreStateAsync(BrowserHistorySavedState.Entry e, BooleanProperty busy) {
var storageEntry = DataStorage.get().getStoreEntryIfPresent(e.getUuid());
storageEntry.ifPresent(entry -> {
openFileSystemAsync(entry.ref(), model -> e.getPath(), busy);
@@ -144,7 +143,7 @@ public class BrowserSessionModel extends BrowserAbstractSessionModel<BrowserSess
}
public void reset() {
synchronized (BrowserSessionModel.this) {
synchronized (BrowserFullSessionModel.this) {
var all = new ArrayList<>(sessionEntries);
for (var o : all) {
// Don't close busy connections gracefully
@@ -156,7 +155,7 @@ public class BrowserSessionModel extends BrowserAbstractSessionModel<BrowserSess
// Prevent blocking of shutdown
closeAsync(o);
}
BrowserSavedStateImpl.get().save();
BrowserHistorySavedStateImpl.get().save();
}
// Delete all files
@@ -165,7 +164,7 @@ public class BrowserSessionModel extends BrowserAbstractSessionModel<BrowserSess
public void openFileSystemAsync(
DataStoreEntryRef<? extends FileSystemStore> store,
FailableFunction<OpenFileSystemModel, String, Exception> path,
FailableFunction<BrowserFileSystemTabModel, String, Exception> path,
BooleanProperty externalBusy) {
if (store == null) {
return;
@@ -176,19 +175,19 @@ public class BrowserSessionModel extends BrowserAbstractSessionModel<BrowserSess
});
}
public OpenFileSystemModel openFileSystemSync(
public BrowserFileSystemTabModel openFileSystemSync(
DataStoreEntryRef<? extends FileSystemStore> store,
FailableFunction<OpenFileSystemModel, String, Exception> path,
FailableFunction<BrowserFileSystemTabModel, String, Exception> path,
BooleanProperty externalBusy,
boolean select)
throws Exception {
OpenFileSystemModel model;
BrowserFileSystemTabModel model;
try (var b = new BooleanScope(externalBusy != null ? externalBusy : new SimpleBooleanProperty()).start()) {
try (var sessionBusy = new BooleanScope(busy).exclusive().start()) {
model = new OpenFileSystemModel(this, store, OpenFileSystemModel.SelectionMode.ALL);
model = new BrowserFileSystemTabModel(this, store, BrowserFileSystemTabModel.SelectionMode.ALL);
model.init();
// Prevent multiple calls from interfering with each other
synchronized (BrowserSessionModel.this) {
synchronized (BrowserFullSessionModel.this) {
sessionEntries.add(model);
if (select) {
// The tab pane doesn't automatically select new tabs

View File

@@ -1,6 +1,6 @@
package io.xpipe.app.browser.session;
package io.xpipe.app.browser;
import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.storage.DataColor;
import javafx.beans.property.BooleanProperty;
@@ -8,8 +8,6 @@ import javafx.beans.property.Property;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ObservableDoubleValue;
import javafx.beans.value.ObservableValue;
import lombok.Getter;
@Getter

View File

@@ -1,12 +1,11 @@
package io.xpipe.app.browser.session;
package io.xpipe.app.browser;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.fxcomps.SimpleComp;
import io.xpipe.app.fxcomps.impl.PrettyImageHelper;
import io.xpipe.app.fxcomps.impl.TooltipAugment;
import io.xpipe.app.fxcomps.util.LabelGraphic;
import io.xpipe.app.fxcomps.util.PlatformThread;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.SimpleComp;
import io.xpipe.app.comp.base.PrettyImageHelper;
import io.xpipe.app.util.LabelGraphic;
import io.xpipe.app.util.PlatformThread;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.app.util.BooleanScope;
import io.xpipe.app.util.ContextMenuHelper;
@@ -16,9 +15,7 @@ import javafx.beans.binding.Bindings;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ObservableDoubleValue;
import javafx.beans.value.ObservableValue;
import javafx.collections.ListChangeListener;
import javafx.css.PseudoClass;
import javafx.geometry.Insets;
@@ -34,7 +31,6 @@ import atlantafx.base.theme.Styles;
import lombok.Getter;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import static atlantafx.base.theme.Styles.DENSE;
import static atlantafx.base.theme.Styles.toggleStyleClass;
@@ -42,14 +38,14 @@ import static javafx.scene.control.TabPane.TabClosingPolicy.ALL_TABS;
public class BrowserSessionTabsComp extends SimpleComp {
private final BrowserSessionModel model;
private final BrowserFullSessionModel model;
private final ObservableDoubleValue leftPadding;
private final DoubleProperty rightPadding;
@Getter
private final DoubleProperty headerHeight;
public BrowserSessionTabsComp(BrowserSessionModel model, ObservableDoubleValue leftPadding, DoubleProperty rightPadding) {
public BrowserSessionTabsComp(BrowserFullSessionModel model, ObservableDoubleValue leftPadding, DoubleProperty rightPadding) {
this.model = model;
this.leftPadding = leftPadding;
this.rightPadding = rightPadding;
@@ -398,7 +394,7 @@ public class BrowserSessionTabsComp extends SimpleComp {
PlatformThread.sync(tabModel.getBusy())));
}
if (tabModel.getBrowserModel() instanceof BrowserSessionModel sessionModel) {
if (tabModel.getBrowserModel() instanceof BrowserFullSessionModel sessionModel) {
var global = PlatformThread.sync(sessionModel.getGlobalPinnedTab());
tab.textProperty().bind(Bindings.createStringBinding(() -> {
return tabModel.getName() + (global.getValue() == tabModel ? " (" + AppI18n.get("pinned") + ")" : "");

View File

@@ -1,6 +1,6 @@
package io.xpipe.app.browser.session;
package io.xpipe.app.browser;
import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.storage.DataColor;
import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.storage.DataStoreEntryRef;

View File

@@ -1,7 +1,7 @@
package io.xpipe.app.browser.action;
import io.xpipe.app.browser.file.BrowserEntry;
import io.xpipe.app.browser.fs.OpenFileSystemModel;
import io.xpipe.app.browser.file.BrowserFileSystemTabModel;
import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.core.util.ModuleLayerLoader;
@@ -18,25 +18,25 @@ public interface BrowserAction {
List<BrowserAction> ALL = new ArrayList<>();
static List<LeafAction> getFlattened(OpenFileSystemModel model, List<BrowserEntry> entries) {
static List<BrowserLeafAction> getFlattened(BrowserFileSystemTabModel model, List<BrowserEntry> entries) {
return ALL.stream()
.map(browserAction -> getFlattened(browserAction, model, entries))
.flatMap(List::stream)
.toList();
}
static List<LeafAction> getFlattened(
BrowserAction browserAction, OpenFileSystemModel model, List<BrowserEntry> entries) {
return browserAction instanceof LeafAction
? List.of((LeafAction) browserAction)
: ((BranchAction) browserAction)
static List<BrowserLeafAction> getFlattened(
BrowserAction browserAction, BrowserFileSystemTabModel model, List<BrowserEntry> entries) {
return browserAction instanceof BrowserLeafAction
? List.of((BrowserLeafAction) browserAction)
: ((BrowserBranchAction) browserAction)
.getBranchingActions(model, entries).stream()
.map(action -> getFlattened(action, model, entries))
.flatMap(List::stream)
.toList();
}
static LeafAction byId(String id, OpenFileSystemModel model, List<BrowserEntry> entries) {
static BrowserLeafAction byId(String id, BrowserFileSystemTabModel model, List<BrowserEntry> entries) {
return getFlattened(model, entries).stream()
.filter(browserAction -> id.equals(browserAction.getId()))
.findAny()
@@ -52,15 +52,15 @@ public interface BrowserAction {
: selected;
}
MenuItem toMenuItem(OpenFileSystemModel model, List<BrowserEntry> selected);
MenuItem toMenuItem(BrowserFileSystemTabModel model, List<BrowserEntry> selected);
default void init(OpenFileSystemModel model) throws Exception {}
default void init(BrowserFileSystemTabModel model) throws Exception {}
default String getProFeatureId() {
return null;
}
default Node getIcon(OpenFileSystemModel model, List<BrowserEntry> entries) {
default Node getIcon(BrowserFileSystemTabModel model, List<BrowserEntry> entries) {
return null;
}
@@ -76,9 +76,9 @@ public interface BrowserAction {
return false;
}
ObservableValue<String> getName(OpenFileSystemModel model, List<BrowserEntry> entries);
ObservableValue<String> getName(BrowserFileSystemTabModel model, List<BrowserEntry> entries);
default boolean isApplicable(OpenFileSystemModel model, List<BrowserEntry> entries) {
default boolean isApplicable(BrowserFileSystemTabModel model, List<BrowserEntry> entries) {
return true;
}
@@ -86,7 +86,7 @@ public interface BrowserAction {
return true;
}
default boolean isActive(OpenFileSystemModel model, List<BrowserEntry> entries) {
default boolean isActive(BrowserFileSystemTabModel model, List<BrowserEntry> entries) {
return true;
}

View File

@@ -1,22 +1,22 @@
package io.xpipe.app.browser.action;
import io.xpipe.app.browser.file.BrowserEntry;
import io.xpipe.app.browser.fs.OpenFileSystemModel;
import io.xpipe.app.browser.file.BrowserFileSystemTabModel;
import java.util.List;
public interface ApplicationPathAction extends BrowserAction {
public interface BrowserApplicationPathAction extends BrowserAction {
String getExecutable();
@Override
default void init(OpenFileSystemModel model) {
default void init(BrowserFileSystemTabModel model) {
// Cache result for later calls
model.getCache().isApplicationInPath(getExecutable());
}
@Override
default boolean isActive(OpenFileSystemModel model, List<BrowserEntry> entries) {
default boolean isActive(BrowserFileSystemTabModel model, List<BrowserEntry> entries) {
return model.getCache().isApplicationInPath(getExecutable());
}
}

View File

@@ -1,7 +1,7 @@
package io.xpipe.app.browser.action;
import io.xpipe.app.browser.file.BrowserEntry;
import io.xpipe.app.browser.fs.OpenFileSystemModel;
import io.xpipe.app.browser.file.BrowserFileSystemTabModel;
import io.xpipe.app.util.LicenseProvider;
import javafx.scene.control.Menu;
@@ -11,9 +11,9 @@ import org.kordamp.ikonli.javafx.FontIcon;
import java.util.List;
public interface BranchAction extends BrowserAction {
public interface BrowserBranchAction extends BrowserAction {
default MenuItem toMenuItem(OpenFileSystemModel model, List<BrowserEntry> selected) {
default MenuItem toMenuItem(BrowserFileSystemTabModel model, List<BrowserEntry> selected) {
var m = new Menu(getName(model, selected).getValue() + " ...");
for (var sub : getBranchingActions(model, selected)) {
var subselected = resolveFilesIfNeeded(selected);
@@ -37,5 +37,5 @@ public interface BranchAction extends BrowserAction {
return m;
}
List<? extends BrowserAction> getBranchingActions(OpenFileSystemModel model, List<BrowserEntry> entries);
List<? extends BrowserAction> getBranchingActions(BrowserFileSystemTabModel model, List<BrowserEntry> entries);
}

View File

@@ -1,9 +1,9 @@
package io.xpipe.app.browser.action;
import io.xpipe.app.browser.file.BrowserEntry;
import io.xpipe.app.browser.fs.OpenFileSystemModel;
import io.xpipe.app.fxcomps.impl.TooltipAugment;
import io.xpipe.app.fxcomps.util.BindingsHelper;
import io.xpipe.app.browser.file.BrowserFileSystemTabModel;
import io.xpipe.app.comp.base.TooltipAugment;
import io.xpipe.app.util.BindingsHelper;
import io.xpipe.app.util.BooleanScope;
import io.xpipe.app.util.LicenseProvider;
import io.xpipe.app.util.ThreadHelper;
@@ -17,11 +17,11 @@ import org.kordamp.ikonli.javafx.FontIcon;
import java.util.List;
public interface LeafAction extends BrowserAction {
public interface BrowserLeafAction extends BrowserAction {
void execute(OpenFileSystemModel model, List<BrowserEntry> entries) throws Exception;
void execute(BrowserFileSystemTabModel model, List<BrowserEntry> entries) throws Exception;
default Button toButton(Region root, OpenFileSystemModel model, List<BrowserEntry> selected) {
default Button toButton(Region root, BrowserFileSystemTabModel model, List<BrowserEntry> selected) {
var b = new Button();
b.setOnAction(event -> {
ThreadHelper.runFailableAsync(() -> {
@@ -66,7 +66,7 @@ public interface LeafAction extends BrowserAction {
return b;
}
default MenuItem toMenuItem(OpenFileSystemModel model, List<BrowserEntry> selected) {
default MenuItem toMenuItem(BrowserFileSystemTabModel model, List<BrowserEntry> selected) {
var name = getName(model, selected);
var mi = new MenuItem();
mi.textProperty().bind(BindingsHelper.map(name, s -> {

View File

@@ -1,8 +1,7 @@
package io.xpipe.app.browser;
package io.xpipe.app.browser.file;
import io.xpipe.app.browser.fs.OpenFileSystemModel;
import io.xpipe.app.fxcomps.SimpleComp;
import io.xpipe.app.fxcomps.util.PlatformThread;
import io.xpipe.app.comp.SimpleComp;
import io.xpipe.app.util.PlatformThread;
import io.xpipe.core.store.FileNames;
import javafx.scene.Node;
@@ -18,9 +17,9 @@ import java.util.ArrayList;
public class BrowserBreadcrumbBar extends SimpleComp {
private final OpenFileSystemModel model;
private final BrowserFileSystemTabModel model;
public BrowserBreadcrumbBar(OpenFileSystemModel model) {
public BrowserBreadcrumbBar(BrowserFileSystemTabModel model) {
this.model = model;
}

View File

@@ -1,8 +1,5 @@
package io.xpipe.app.browser;
package io.xpipe.app.browser.file;
import io.xpipe.app.browser.file.BrowserEntry;
import io.xpipe.app.browser.file.BrowserFileTransferMode;
import io.xpipe.app.browser.file.LocalFileSystem;
import io.xpipe.app.ext.ProcessControlProvider;
import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.app.util.ThreadHelper;
@@ -55,7 +52,7 @@ public class BrowserClipboard {
var entries = new ArrayList<BrowserEntry>();
for (Path file : files) {
entries.add(LocalFileSystem.getLocalBrowserEntry(file));
entries.add(BrowserLocalFileSystem.getLocalBrowserEntry(file));
}
currentCopyClipboard.setValue(

View File

@@ -1,10 +1,10 @@
package io.xpipe.app.browser;
package io.xpipe.app.browser.file;
import io.xpipe.app.comp.store.*;
import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.fxcomps.CompStructure;
import io.xpipe.app.fxcomps.SimpleComp;
import io.xpipe.app.fxcomps.util.PlatformThread;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.CompStructure;
import io.xpipe.app.comp.SimpleComp;
import io.xpipe.app.util.PlatformThread;
import io.xpipe.app.storage.DataStoreEntry;
import javafx.beans.binding.Bindings;
@@ -19,7 +19,7 @@ import java.util.HashSet;
import java.util.function.BiConsumer;
import java.util.function.Predicate;
public final class BrowserBookmarkComp extends SimpleComp {
public final class BrowserConnectionListComp extends SimpleComp {
private static final PseudoClass SELECTED = PseudoClass.getPseudoClass("selected");
private final ObservableValue<DataStoreEntry> selected;
@@ -28,7 +28,7 @@ public final class BrowserBookmarkComp extends SimpleComp {
private final Property<StoreCategoryWrapper> category;
private final Property<String> filter;
public BrowserBookmarkComp(
public BrowserConnectionListComp(
ObservableValue<DataStoreEntry> selected,
Predicate<StoreEntryWrapper> applicable,
BiConsumer<StoreEntryWrapper, BooleanProperty> action,

View File

@@ -1,11 +1,11 @@
package io.xpipe.app.browser;
package io.xpipe.app.browser.file;
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.comp.SimpleComp;
import io.xpipe.app.comp.base.FilterComp;
import io.xpipe.app.comp.base.HorizontalComp;
import io.xpipe.app.util.DataStoreCategoryChoiceComp;
import javafx.beans.property.Property;
@@ -19,7 +19,7 @@ import lombok.Getter;
import java.util.List;
@Getter
public final class BrowserBookmarkHeaderComp extends SimpleComp {
public final class BrowserConnectionListFilterComp extends SimpleComp {
private final Property<StoreCategoryWrapper> category =
new SimpleObjectProperty<>(StoreViewState.get().getActiveCategory().getValue());

View File

@@ -1,7 +1,6 @@
package io.xpipe.app.browser.file;
import io.xpipe.app.browser.action.BrowserAction;
import io.xpipe.app.browser.fs.OpenFileSystemModel;
import io.xpipe.app.core.AppFont;
import io.xpipe.app.util.InputHelper;
@@ -13,11 +12,11 @@ import java.util.List;
public final class BrowserContextMenu extends ContextMenu {
private final OpenFileSystemModel model;
private final BrowserFileSystemTabModel model;
private final BrowserEntry source;
private final boolean quickAccess;
public BrowserContextMenu(OpenFileSystemModel model, BrowserEntry source, boolean quickAccess) {
public BrowserContextMenu(BrowserFileSystemTabModel model, BrowserEntry source, boolean quickAccess) {
this.model = model;
this.source = source;
this.quickAccess = quickAccess;

View File

@@ -1,11 +1,9 @@
package io.xpipe.app.browser.file;
import io.xpipe.app.browser.action.BrowserAction;
import io.xpipe.app.comp.base.LazyTextFieldComp;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.fxcomps.SimpleComp;
import io.xpipe.app.fxcomps.impl.PrettyImageHelper;
import io.xpipe.app.fxcomps.util.PlatformThread;
import io.xpipe.app.comp.SimpleComp;
import io.xpipe.app.util.PlatformThread;
import io.xpipe.app.util.*;
import io.xpipe.core.process.OsType;
import io.xpipe.core.store.FileEntry;
@@ -16,24 +14,16 @@ import io.xpipe.core.store.FileNames;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.beans.property.*;
import javafx.beans.value.ChangeListener;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.css.PseudoClass;
import javafx.geometry.Bounds;
import javafx.geometry.Pos;
import javafx.geometry.Side;
import javafx.scene.AccessibleRole;
import javafx.scene.Node;
import javafx.scene.control.*;
import javafx.scene.control.skin.TableViewSkin;
import javafx.scene.control.skin.VirtualFlow;
import javafx.scene.input.*;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.Region;
import atlantafx.base.controls.Spacer;
import atlantafx.base.theme.Styles;
import java.time.Duration;
@@ -82,7 +72,7 @@ public final class BrowserFileListComp extends SimpleComp {
: null));
filenameCol.setComparator(Comparator.comparing(String::toLowerCase));
filenameCol.setSortType(ASCENDING);
filenameCol.setCellFactory(col -> new FilenameCell(fileList.getEditing(), col.getTableView()));
filenameCol.setCellFactory(col -> new BrowserFileListNameCell(fileList, typedSelection, fileList.getEditing(), col.getTableView()));
filenameCol.setReorderable(false);
filenameCol.setResizable(false);
@@ -139,6 +129,31 @@ public final class BrowserFileListComp extends SimpleComp {
return true;
});
table.setFixedCellSize(32.0);
prepareColumnVisibility(table, ownerCol, filenameCol);
prepareTableScrollFix(table);
prepareTableSelectionModel(table);
prepareTableShortcuts(table);
prepareTableEntries(table);
prepareTableChanges(table, filenameCol, mtimeCol, modeCol, ownerCol);
prepareTypedSelectionModel(table);
return table;
}
private static void prepareTableScrollFix(TableView<BrowserEntry> table) {
table.lookupAll(".scroll-bar").stream()
.filter(node -> node.getPseudoClassStates().contains(PseudoClass.getPseudoClass("horizontal")))
.findFirst()
.ifPresent(node -> {
Region region = (Region) node;
region.setMinHeight(0);
region.setPrefHeight(0);
region.setMaxHeight(0);
});
}
private void prepareColumnVisibility(TableView<BrowserEntry> table, TableColumn<BrowserEntry, String> ownerCol, TableColumn<BrowserEntry, String> filenameCol) {
var os = fileList.getFileSystemModel()
.getFileSystem()
.getShell()
@@ -151,24 +166,6 @@ public final class BrowserFileListComp extends SimpleComp {
var width = getFilenameWidth(table);
filenameCol.setPrefWidth(width);
});
table.lookupAll(".scroll-bar").stream()
.filter(node -> node.getPseudoClassStates().contains(PseudoClass.getPseudoClass("horizontal")))
.findFirst()
.ifPresent(node -> {
Region region = (Region) node;
region.setMinHeight(0);
region.setPrefHeight(0);
region.setMaxHeight(0);
});
prepareTableSelectionModel(table);
prepareTableShortcuts(table);
prepareTableEntries(table);
prepareTableChanges(table, filenameCol, mtimeCol, modeCol, ownerCol);
prepareTypedSelectionModel(table);
return table;
}
private double getFilenameWidth(TableView<?> tableView) {
@@ -632,156 +629,4 @@ public final class BrowserFileListComp extends SimpleComp {
}
}
private class FilenameCell extends TableCell<BrowserEntry, String> {
private final StringProperty img = new SimpleStringProperty();
private final StringProperty text = new SimpleStringProperty();
private final BooleanProperty updating = new SimpleBooleanProperty();
public FilenameCell(Property<BrowserEntry> editing, TableView<BrowserEntry> tableView) {
accessibleTextProperty()
.bind(Bindings.createStringBinding(
() -> {
return getItem() != null ? getItem() : null;
},
itemProperty()));
setAccessibleRole(AccessibleRole.TEXT);
var textField = new LazyTextFieldComp(text)
.minWidth(USE_PREF_SIZE)
.createStructure()
.get();
var quickAccess = new BrowserQuickAccessButtonComp(
() -> getTableRow().getItem(), fileList.getFileSystemModel())
.hide(Bindings.createBooleanBinding(
() -> {
if (getTableRow() == null) {
return true;
}
var item = getTableRow().getItem();
var notDir = item.getRawFileEntry().resolved().getKind() != FileKind.DIRECTORY;
var isParentLink = item.getRawFileEntry()
.equals(fileList.getFileSystemModel().getCurrentParentDirectory());
return notDir || isParentLink;
},
itemProperty()))
.focusTraversable(false)
.createRegion();
editing.addListener((observable, oldValue, newValue) -> {
if (getTableRow().getItem() != null && getTableRow().getItem().equals(newValue)) {
PlatformThread.runLaterIfNeeded(() -> {
textField.setDisable(false);
textField.requestFocus();
});
}
});
ChangeListener<String> listener = (observable, oldValue, newValue) -> {
if (updating.get()) {
return;
}
getTableRow().requestFocus();
var it = getTableRow().getItem();
editing.setValue(null);
ThreadHelper.runAsync(() -> {
if (it == null) {
return;
}
var r = fileList.rename(it, newValue);
Platform.runLater(() -> {
updateItem(getItem(), isEmpty());
fileList.getSelection().setAll(r);
getTableView().scrollTo(r);
});
});
};
text.addListener(listener);
Node imageView = PrettyImageHelper.ofFixedSize(img, 24, 24).createRegion();
HBox graphic = new HBox(imageView, new Spacer(5), quickAccess, new Spacer(1), textField);
quickAccess.prefHeightProperty().bind(graphic.heightProperty());
graphic.setAlignment(Pos.CENTER_LEFT);
graphic.setPrefHeight(34);
HBox.setHgrow(textField, Priority.ALWAYS);
graphic.setAlignment(Pos.CENTER_LEFT);
setGraphic(graphic);
InputHelper.onExactKeyCode(tableView, KeyCode.RIGHT, false, event -> {
var selected = fileList.getSelection();
if (selected.size() == 1 && selected.getFirst() == getTableRow().getItem()) {
((ButtonBase) quickAccess).fire();
event.consume();
}
});
InputHelper.onExactKeyCode(tableView, KeyCode.SPACE, true, event -> {
var selection = typedSelection.get() + " ";
var found = fileList.getShown().getValue().stream()
.filter(browserEntry ->
browserEntry.getFileName().toLowerCase().startsWith(selection))
.findFirst();
// Ugly fix to prevent space from showing the menu when there is a file matching
// Due to the table view input map, these events always get sent and consumed, not allowing us to
// differentiate between these cases
if (found.isPresent()) {
return;
}
var selected = fileList.getSelection();
// Only show one menu across all selected entries
if (selected.size() > 0 && selected.getLast() == getTableRow().getItem()) {
var cm = new BrowserContextMenu(
fileList.getFileSystemModel(), getTableRow().getItem(), false);
ContextMenuHelper.toggleShow(cm, this, Side.RIGHT);
event.consume();
}
});
}
@Override
protected void updateItem(String newName, boolean empty) {
if (updating.get()) {
super.updateItem(newName, empty);
return;
}
try (var ignored = new BooleanScope(updating).start()) {
super.updateItem(newName, empty);
if (empty || newName == null || getTableRow().getItem() == null) {
// Don't set image as that would trigger image comp update
// and cells are emptied on each change, leading to unnecessary changes
// img.set(null);
// Visibility seems to be bugged, so use opacity
setOpacity(0.0);
} else {
img.set(getTableRow().getItem().getIcon());
var isDirectory = getTableRow().getItem().getRawFileEntry().getKind() == FileKind.DIRECTORY;
pseudoClassStateChanged(FOLDER, isDirectory);
var normalName = getTableRow().getItem().getRawFileEntry().getKind() == FileKind.LINK
? getTableRow().getItem().getFileName() + " -> "
+ getTableRow()
.getItem()
.getRawFileEntry()
.resolved()
.getPath()
: getTableRow().getItem().getFileName();
var fileName = normalName;
var hidden =
getTableRow().getItem().getRawFileEntry().getInfo().explicitlyHidden()
|| fileName.startsWith(".");
getTableRow().pseudoClassStateChanged(HIDDEN, hidden);
text.set(fileName);
// Visibility seems to be bugged, so use opacity
setOpacity(1.0);
}
}
}
}
}

View File

@@ -1,8 +1,6 @@
package io.xpipe.app.browser.file;
import io.xpipe.app.browser.BrowserClipboard;
import io.xpipe.app.browser.BrowserSelectionListComp;
import io.xpipe.app.browser.session.BrowserSessionModel;
import io.xpipe.app.browser.BrowserFullSessionModel;
import io.xpipe.core.store.FileKind;
import javafx.geometry.Point2D;
@@ -219,7 +217,7 @@ public class BrowserFileListCompEntry {
return;
}
if (model.getFileSystemModel().getBrowserModel() instanceof BrowserSessionModel sessionModel) {
if (model.getFileSystemModel().getBrowserModel() instanceof BrowserFullSessionModel sessionModel) {
sessionModel.getDraggingFiles().setValue(true);
}
var selected = model.getSelection();
@@ -229,7 +227,7 @@ public class BrowserFileListCompEntry {
selected,
event.isAltDown() ? BrowserFileTransferMode.MOVE : BrowserFileTransferMode.NORMAL));
Image image = BrowserSelectionListComp.snapshot(selected);
Image image = BrowserFileSelectionListComp.snapshot(selected);
db.setDragView(image, -20, 15);
event.setDragDetect(true);
@@ -237,7 +235,7 @@ public class BrowserFileListCompEntry {
}
public void onDragDone(DragEvent event) {
if (model.getFileSystemModel().getBrowserModel() instanceof BrowserSessionModel sessionModel) {
if (model.getFileSystemModel().getBrowserModel() instanceof BrowserFullSessionModel sessionModel) {
sessionModel.getDraggingFiles().setValue(false);
event.consume();
}

View File

@@ -1,10 +1,9 @@
package io.xpipe.app.browser;
package io.xpipe.app.browser.file;
import io.xpipe.app.browser.fs.OpenFileSystemModel;
import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.fxcomps.CompStructure;
import io.xpipe.app.fxcomps.impl.TextFieldComp;
import io.xpipe.app.fxcomps.impl.TooltipAugment;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.CompStructure;
import io.xpipe.app.comp.base.TextFieldComp;
import io.xpipe.app.comp.base.TooltipAugment;
import io.xpipe.app.util.InputHelper;
import javafx.beans.property.Property;
@@ -20,12 +19,12 @@ import javafx.scene.layout.HBox;
import atlantafx.base.theme.Styles;
import org.kordamp.ikonli.javafx.FontIcon;
public class BrowserFilterComp extends Comp<BrowserFilterComp.Structure> {
public class BrowserFileListFilterComp extends Comp<BrowserFileListFilterComp.Structure> {
private final OpenFileSystemModel model;
private final BrowserFileSystemTabModel model;
private final Property<String> filterString;
public BrowserFilterComp(OpenFileSystemModel model, Property<String> filterString) {
public BrowserFileListFilterComp(BrowserFileSystemTabModel model, Property<String> filterString) {
this.model = model;
this.filterString = filterString;
}

View File

@@ -1,6 +1,5 @@
package io.xpipe.app.browser.file;
import io.xpipe.app.browser.fs.OpenFileSystemModel;
import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.core.process.OsType;
import io.xpipe.core.store.FileEntry;
@@ -27,9 +26,9 @@ public final class BrowserFileListModel {
static final Comparator<BrowserEntry> FILE_TYPE_COMPARATOR =
Comparator.comparing(path -> path.getRawFileEntry().resolved().getKind() != FileKind.DIRECTORY);
private final OpenFileSystemModel.SelectionMode selectionMode;
private final BrowserFileSystemTabModel.SelectionMode selectionMode;
private final OpenFileSystemModel fileSystemModel;
private final BrowserFileSystemTabModel fileSystemModel;
private final Property<Comparator<BrowserEntry>> comparatorProperty =
new SimpleObjectProperty<>(FILE_TYPE_COMPARATOR);
private final Property<List<BrowserEntry>> all = new SimpleObjectProperty<>(new ArrayList<>());
@@ -40,7 +39,7 @@ public final class BrowserFileListModel {
private final Property<Boolean> draggedOverEmpty = new SimpleBooleanProperty();
private final Property<BrowserEntry> editing = new SimpleObjectProperty<>();
public BrowserFileListModel(OpenFileSystemModel.SelectionMode selectionMode, OpenFileSystemModel fileSystemModel) {
public BrowserFileListModel(BrowserFileSystemTabModel.SelectionMode selectionMode, BrowserFileSystemTabModel fileSystemModel) {
this.selectionMode = selectionMode;
this.fileSystemModel = fileSystemModel;

View File

@@ -0,0 +1,174 @@
package io.xpipe.app.browser.file;
import atlantafx.base.controls.Spacer;
import io.xpipe.app.comp.base.LazyTextFieldComp;
import io.xpipe.app.comp.base.PrettyImageHelper;
import io.xpipe.app.util.PlatformThread;
import io.xpipe.app.util.BooleanScope;
import io.xpipe.app.util.ContextMenuHelper;
import io.xpipe.app.util.InputHelper;
import io.xpipe.app.util.ThreadHelper;
import io.xpipe.core.store.FileKind;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.beans.property.*;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableStringValue;
import javafx.css.PseudoClass;
import javafx.geometry.Pos;
import javafx.geometry.Side;
import javafx.scene.AccessibleRole;
import javafx.scene.Node;
import javafx.scene.control.ButtonBase;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.Region;
class BrowserFileListNameCell extends TableCell<BrowserEntry, String> {
private final BrowserFileListModel fileList;
private final ObservableStringValue typedSelection;
private final StringProperty img = new SimpleStringProperty();
private final StringProperty text = new SimpleStringProperty();
private final BooleanProperty updating = new SimpleBooleanProperty();
public BrowserFileListNameCell(BrowserFileListModel fileList, ObservableStringValue typedSelection, Property<BrowserEntry> editing, TableView<BrowserEntry> tableView) {
this.fileList = fileList;
this.typedSelection = typedSelection;
accessibleTextProperty().bind(Bindings.createStringBinding(() -> {
return getItem() != null ? getItem() : null;
}, itemProperty()));
setAccessibleRole(AccessibleRole.TEXT);
var textField = new LazyTextFieldComp(text).minWidth(USE_PREF_SIZE).createStructure().get();
var quickAccess = createQuickAccessButton();
setupShortcuts(tableView, (ButtonBase) quickAccess);
setupRename(fileList, textField, editing);
Node imageView = PrettyImageHelper.ofFixedSize(img, 24, 24).createRegion();
HBox graphic = new HBox(imageView, new Spacer(5), quickAccess, new Spacer(1), textField);
quickAccess.prefHeightProperty().bind(graphic.heightProperty());
graphic.setAlignment(Pos.CENTER_LEFT);
graphic.setPrefHeight(34);
HBox.setHgrow(textField, Priority.ALWAYS);
graphic.setAlignment(Pos.CENTER_LEFT);
setGraphic(graphic);
}
private Region createQuickAccessButton() {
var quickAccess = new BrowserQuickAccessButtonComp(() -> getTableRow().getItem(), fileList.getFileSystemModel()).hide(Bindings.createBooleanBinding(() -> {
if (getTableRow() == null) {
return true;
}
var item = getTableRow().getItem();
var notDir = item.getRawFileEntry().resolved().getKind() != FileKind.DIRECTORY;
var isParentLink = item.getRawFileEntry().equals(fileList.getFileSystemModel().getCurrentParentDirectory());
return notDir || isParentLink;
}, itemProperty())).focusTraversable(false).createRegion();
return quickAccess;
}
private void setupShortcuts(TableView<BrowserEntry> tableView, ButtonBase quickAccess) {
InputHelper.onExactKeyCode(tableView, KeyCode.RIGHT, false, event -> {
var selected = fileList.getSelection();
if (selected.size() == 1 && selected.getFirst() == getTableRow().getItem()) {
quickAccess.fire();
event.consume();
}
});
InputHelper.onExactKeyCode(tableView, KeyCode.SPACE, true, event -> {
var selection = typedSelection.get() + " ";
var found = fileList.getShown().getValue().stream().filter(browserEntry -> browserEntry.getFileName().toLowerCase().startsWith(selection)).findFirst();
// Ugly fix to prevent space from showing the menu when there is a file matching
// Due to the table view input map, these events always get sent and consumed, not allowing us to
// differentiate between these cases
if (found.isPresent()) {
return;
}
var selected = fileList.getSelection();
// Only show one menu across all selected entries
if (selected.size() > 0 && selected.getLast() == getTableRow().getItem()) {
var cm = new BrowserContextMenu(fileList.getFileSystemModel(), getTableRow().getItem(), false);
ContextMenuHelper.toggleShow(cm, this, Side.RIGHT);
event.consume();
}
});
}
private void setupRename(BrowserFileListModel fileList, TextField textField, Property<BrowserEntry> editing) {
ChangeListener<String> listener = (observable, oldValue, newValue) -> {
if (updating.get()) {
return;
}
getTableRow().requestFocus();
var it = getTableRow().getItem();
editing.setValue(null);
ThreadHelper.runAsync(() -> {
if (it == null) {
return;
}
var r = fileList.rename(it, newValue);
Platform.runLater(() -> {
updateItem(getItem(), isEmpty());
fileList.getSelection().setAll(r);
getTableView().scrollTo(r);
});
});
};
text.addListener(listener);
editing.addListener((observable, oldValue, newValue) -> {
if (getTableRow().getItem() != null && getTableRow().getItem().equals(newValue)) {
PlatformThread.runLaterIfNeeded(() -> {
textField.setDisable(false);
textField.requestFocus();
});
}
});
}
@Override
protected void updateItem(String newName, boolean empty) {
if (updating.get()) {
super.updateItem(newName, empty);
return;
}
try (var ignored = new BooleanScope(updating).start()) {
super.updateItem(newName, empty);
if (empty || newName == null || getTableRow().getItem() == null) {
// Don't set image as that would trigger image comp update
// and cells are emptied on each change, leading to unnecessary changes
// img.set(null);
// Visibility seems to be bugged, so use opacity
setOpacity(0.0);
} else {
img.set(getTableRow().getItem().getIcon());
var isDirectory = getTableRow().getItem().getRawFileEntry().getKind() == FileKind.DIRECTORY;
pseudoClassStateChanged(PseudoClass.getPseudoClass("folder"), isDirectory);
var normalName = getTableRow().getItem().getRawFileEntry().getKind() == FileKind.LINK ?
getTableRow().getItem().getFileName() + " -> " + getTableRow().getItem().getRawFileEntry().resolved().getPath() :
getTableRow().getItem().getFileName();
var fileName = normalName;
var hidden = getTableRow().getItem().getRawFileEntry().getInfo().explicitlyHidden() || fileName.startsWith(".");
getTableRow().pseudoClassStateChanged(PseudoClass.getPseudoClass("hidden"), hidden);
text.set(fileName);
// Visibility seems to be bugged, so use opacity
setOpacity(1.0);
}
}
}
}

View File

@@ -1,6 +1,5 @@
package io.xpipe.app.browser;
package io.xpipe.app.browser.file;
import io.xpipe.app.browser.fs.OpenFileSystemModel;
import io.xpipe.app.core.window.AppWindowHelper;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.app.util.BooleanScope;
@@ -20,7 +19,7 @@ import java.util.Objects;
public class BrowserFileOpener {
private static OutputStream openFileOutput(OpenFileSystemModel model, FileEntry file, long totalBytes)
private static OutputStream openFileOutput(BrowserFileSystemTabModel model, FileEntry file, long totalBytes)
throws Exception {
var fileSystem = model.getFileSystem();
if (model.isClosed() || fileSystem.getShell().isEmpty()) {
@@ -68,7 +67,7 @@ public class BrowserFileOpener {
return Objects.hash(entry.getPath(), entry.getFileSystem(), entry.getKind(), entry.getInfo());
}
public static void openWithAnyApplication(OpenFileSystemModel model, FileEntry entry) {
public static void openWithAnyApplication(BrowserFileSystemTabModel model, FileEntry entry) {
var file = entry.getPath();
var key = calculateKey(entry);
FileBridge.get()
@@ -89,7 +88,7 @@ public class BrowserFileOpener {
s -> FileOpener.openWithAnyApplication(s));
}
public static void openInDefaultApplication(OpenFileSystemModel model, FileEntry entry) {
public static void openInDefaultApplication(BrowserFileSystemTabModel model, FileEntry entry) {
var file = entry.getPath();
var key = calculateKey(entry);
FileBridge.get()
@@ -110,7 +109,7 @@ public class BrowserFileOpener {
s -> FileOpener.openInDefaultApplication(s));
}
public static void openInTextEditor(OpenFileSystemModel model, FileEntry entry) {
public static void openInTextEditor(BrowserFileSystemTabModel model, FileEntry entry) {
var editor = AppPrefs.get().externalEditor().getValue();
if (editor == null) {
return;

View File

@@ -1,13 +1,12 @@
package io.xpipe.app.browser.file;
import io.xpipe.app.browser.fs.OpenFileSystemModel;
import io.xpipe.app.browser.icon.BrowserIcons;
import io.xpipe.app.comp.base.ListBoxViewComp;
import io.xpipe.app.comp.base.VBoxViewComp;
import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.fxcomps.SimpleComp;
import io.xpipe.app.fxcomps.augment.GrowAugment;
import io.xpipe.app.fxcomps.impl.HorizontalComp;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.SimpleComp;
import io.xpipe.app.comp.augment.GrowAugment;
import io.xpipe.app.comp.base.HorizontalComp;
import io.xpipe.core.store.FileEntry;
import javafx.collections.ObservableList;
@@ -25,7 +24,7 @@ import java.util.function.Function;
@EqualsAndHashCode(callSuper = true)
public class BrowserFileOverviewComp extends SimpleComp {
OpenFileSystemModel model;
BrowserFileSystemTabModel model;
ObservableList<FileEntry> list;
boolean grow;

View File

@@ -1,14 +1,13 @@
package io.xpipe.app.browser;
package io.xpipe.app.browser.file;
import io.xpipe.app.browser.file.BrowserEntry;
import io.xpipe.app.comp.base.ListBoxViewComp;
import io.xpipe.app.core.AppStyle;
import io.xpipe.app.core.window.AppWindowHelper;
import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.fxcomps.SimpleComp;
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.comp.Comp;
import io.xpipe.app.comp.SimpleComp;
import io.xpipe.app.comp.base.PrettyImageHelper;
import io.xpipe.app.util.BindingsHelper;
import io.xpipe.app.util.PlatformThread;
import javafx.beans.binding.Bindings;
import javafx.beans.property.SimpleStringProperty;
@@ -31,17 +30,17 @@ import java.util.function.Function;
@Value
@EqualsAndHashCode(callSuper = true)
@AllArgsConstructor
public class BrowserSelectionListComp extends SimpleComp {
public class BrowserFileSelectionListComp extends SimpleComp {
ObservableList<BrowserEntry> list;
Function<BrowserEntry, ObservableValue<String>> nameTransformation;
public BrowserSelectionListComp(ObservableList<BrowserEntry> list) {
public BrowserFileSelectionListComp(ObservableList<BrowserEntry> list) {
this(list, entry -> new SimpleStringProperty(entry.getFileName()));
}
public static Image snapshot(ObservableList<BrowserEntry> list) {
var r = new BrowserSelectionListComp(list).styleClass("drag").createRegion();
var r = new BrowserFileSelectionListComp(list).styleClass("drag").createRegion();
var scene = new Scene(r);
AppWindowHelper.setupStylesheets(scene);
AppStyle.addStylesheets(scene);

View File

@@ -1,4 +1,4 @@
package io.xpipe.app.browser.fs;
package io.xpipe.app.browser.file;
import io.xpipe.app.util.ShellControlCache;
import io.xpipe.core.process.CommandBuilder;
@@ -12,14 +12,14 @@ import java.util.LinkedHashMap;
import java.util.Map;
@Getter
public class OpenFileSystemCache extends ShellControlCache {
public class BrowserFileSystemCache extends ShellControlCache {
private final OpenFileSystemModel model;
private final BrowserFileSystemTabModel model;
private final String username;
private final Map<Integer, String> users = new LinkedHashMap<>();
private final Map<Integer, String> groups = new LinkedHashMap<>();
public OpenFileSystemCache(OpenFileSystemModel model) throws Exception {
public BrowserFileSystemCache(BrowserFileSystemTabModel model) throws Exception {
super(model.getFileSystem().getShell().orElseThrow());
this.model = model;

View File

@@ -1,6 +1,5 @@
package io.xpipe.app.browser.file;
import io.xpipe.app.browser.fs.OpenFileSystemModel;
import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.core.process.OsType;
import io.xpipe.core.store.FileEntry;
@@ -11,9 +10,9 @@ import io.xpipe.core.store.FileSystem;
import java.time.Instant;
import java.util.List;
public class FileSystemHelper {
public class BrowserFileSystemHelper {
public static String adjustPath(OpenFileSystemModel model, String path) {
public static String adjustPath(BrowserFileSystemTabModel model, String path) {
if (path == null) {
return null;
}
@@ -46,7 +45,7 @@ public class FileSystemHelper {
return path;
}
public static String evaluatePath(OpenFileSystemModel model, String path) throws Exception {
public static String evaluatePath(BrowserFileSystemTabModel model, String path) throws Exception {
if (path == null) {
return null;
}
@@ -67,7 +66,7 @@ public class FileSystemHelper {
}
}
public static String resolveDirectoryPath(OpenFileSystemModel model, String path, boolean allowRewrite)
public static String resolveDirectoryPath(BrowserFileSystemTabModel model, String path, boolean allowRewrite)
throws Exception {
if (path == null) {
return null;
@@ -98,7 +97,7 @@ public class FileSystemHelper {
return FileNames.toDirectory(resolved);
}
public static void validateDirectoryPath(OpenFileSystemModel model, String path, boolean verifyExists)
public static void validateDirectoryPath(BrowserFileSystemTabModel model, String path, boolean verifyExists)
throws Exception {
if (path == null) {
return;

View File

@@ -1,4 +1,4 @@
package io.xpipe.app.browser.fs;
package io.xpipe.app.browser.file;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.BooleanBinding;
@@ -9,7 +9,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public final class OpenFileSystemHistory {
public final class BrowserFileSystemHistory {
private final IntegerProperty cursor = new SimpleIntegerProperty(-1);
private final List<String> history = new ArrayList<>();

View File

@@ -1,4 +1,4 @@
package io.xpipe.app.browser.fs;
package io.xpipe.app.browser.file;
import io.xpipe.app.core.AppCache;
import io.xpipe.core.store.FileNames;
@@ -31,35 +31,35 @@ import java.util.stream.Collectors;
@AllArgsConstructor
@Getter
@JsonSerialize(using = OpenFileSystemSavedState.Serializer.class)
@JsonDeserialize(using = OpenFileSystemSavedState.Deserializer.class)
public class OpenFileSystemSavedState {
@JsonSerialize(using = BrowserFileSystemSavedState.Serializer.class)
@JsonDeserialize(using = BrowserFileSystemSavedState.Deserializer.class)
public class BrowserFileSystemSavedState {
private static final Timer TIMEOUT_TIMER = new Timer(true);
private static final int STORED = 15;
@Setter
private OpenFileSystemModel model;
private BrowserFileSystemTabModel model;
private String lastDirectory;
@NonNull
private ObservableList<RecentEntry> recentDirectories;
public OpenFileSystemSavedState(String lastDirectory, @NonNull ObservableList<RecentEntry> recentDirectories) {
public BrowserFileSystemSavedState(String lastDirectory, @NonNull ObservableList<RecentEntry> recentDirectories) {
this.lastDirectory = lastDirectory;
this.recentDirectories = recentDirectories;
}
public OpenFileSystemSavedState() {
public BrowserFileSystemSavedState() {
lastDirectory = null;
recentDirectories = FXCollections.observableList(new ArrayList<>(STORED));
}
static OpenFileSystemSavedState loadForStore(OpenFileSystemModel model) {
static BrowserFileSystemSavedState loadForStore(BrowserFileSystemTabModel model) {
var state = AppCache.getNonNull(
"fs-state-" + model.getEntry().get().getUuid(), OpenFileSystemSavedState.class, () -> {
return new OpenFileSystemSavedState();
"fs-state-" + model.getEntry().get().getUuid(), BrowserFileSystemSavedState.class, () -> {
return new BrowserFileSystemSavedState();
});
state.setModel(model);
return state;
@@ -122,14 +122,14 @@ public class OpenFileSystemSavedState {
}
}
public static class Serializer extends StdSerializer<OpenFileSystemSavedState> {
public static class Serializer extends StdSerializer<BrowserFileSystemSavedState> {
protected Serializer() {
super(OpenFileSystemSavedState.class);
super(BrowserFileSystemSavedState.class);
}
@Override
public void serialize(OpenFileSystemSavedState value, JsonGenerator gen, SerializerProvider provider)
public void serialize(BrowserFileSystemSavedState value, JsonGenerator gen, SerializerProvider provider)
throws IOException {
var node = JsonNodeFactory.instance.objectNode();
node.set("recentDirectories", JacksonMapper.getDefault().valueToTree(value.getRecentDirectories()));
@@ -137,10 +137,10 @@ public class OpenFileSystemSavedState {
}
}
public static class Deserializer extends StdDeserializer<OpenFileSystemSavedState> {
public static class Deserializer extends StdDeserializer<BrowserFileSystemSavedState> {
protected Deserializer() {
super(OpenFileSystemSavedState.class);
super(BrowserFileSystemSavedState.class);
}
private static <T> Predicate<T> distinctBy(Function<? super T, ?> f) {
@@ -150,7 +150,7 @@ public class OpenFileSystemSavedState {
@Override
@SneakyThrows
public OpenFileSystemSavedState deserialize(JsonParser p, DeserializationContext ctxt) {
public BrowserFileSystemSavedState deserialize(JsonParser p, DeserializationContext ctxt) {
var tree = (ObjectNode) JacksonMapper.getDefault().readTree(p);
JavaType javaType = JacksonMapper.getDefault()
.getTypeFactory()
@@ -164,7 +164,7 @@ public class OpenFileSystemSavedState {
.map(recentEntry -> new RecentEntry(FileNames.toDirectory(recentEntry.directory), recentEntry.time))
.filter(distinctBy(recentEntry -> recentEntry.getDirectory()))
.collect(Collectors.toCollection(ArrayList::new));
return new OpenFileSystemSavedState(null, FXCollections.observableList(cleaned));
return new BrowserFileSystemSavedState(null, FXCollections.observableList(cleaned));
}
}

View File

@@ -1,21 +1,15 @@
package io.xpipe.app.browser.fs;
package io.xpipe.app.browser.file;
import io.xpipe.app.browser.BrowserFilterComp;
import io.xpipe.app.browser.BrowserNavBar;
import io.xpipe.app.browser.BrowserOverviewComp;
import io.xpipe.app.browser.BrowserStatusBarComp;
import io.xpipe.app.browser.action.BrowserAction;
import io.xpipe.app.browser.file.BrowserContextMenu;
import io.xpipe.app.browser.file.BrowserFileListComp;
import io.xpipe.app.comp.base.ModalOverlayComp;
import io.xpipe.app.comp.base.MultiContentComp;
import io.xpipe.app.core.AppFont;
import io.xpipe.app.fxcomps.Comp;
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.TooltipAugment;
import io.xpipe.app.fxcomps.impl.VerticalComp;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.SimpleComp;
import io.xpipe.app.comp.SimpleCompStructure;
import io.xpipe.app.comp.augment.ContextMenuAugment;
import io.xpipe.app.comp.base.TooltipAugment;
import io.xpipe.app.comp.base.VerticalComp;
import io.xpipe.app.util.InputHelper;
import javafx.geometry.Pos;
@@ -37,12 +31,12 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class OpenFileSystemComp extends SimpleComp {
public class BrowserFileSystemTabComp extends SimpleComp {
private final OpenFileSystemModel model;
private final BrowserFileSystemTabModel model;
private final boolean showStatusBar;
public OpenFileSystemComp(OpenFileSystemModel model, boolean showStatusBar) {
public BrowserFileSystemTabComp(BrowserFileSystemTabModel model, boolean showStatusBar) {
this.model = model;
this.showStatusBar = showStatusBar;
}
@@ -82,12 +76,12 @@ public class OpenFileSystemComp extends SimpleComp {
menuButton.disableProperty().bind(model.getInOverview());
menuButton.setAccessibleText("Directory options");
var filter = new BrowserFilterComp(model, model.getFilter()).createStructure();
var filter = new BrowserFileListFilterComp(model, model.getFilter()).createStructure();
var topBar = new HBox();
topBar.setAlignment(Pos.CENTER);
topBar.getStyleClass().add("top-bar");
var navBar = new BrowserNavBar(model).createStructure();
var navBar = new BrowserNavBarComp(model).createStructure();
filter.textField().prefHeightProperty().bind(navBar.get().heightProperty());
AppFont.medium(navBar.get());
topBar.getChildren()

View File

@@ -1,19 +1,12 @@
package io.xpipe.app.browser.fs;
package io.xpipe.app.browser.file;
import io.xpipe.app.browser.BrowserSavedState;
import io.xpipe.app.browser.BrowserSavedStateImpl;
import io.xpipe.app.browser.BrowserTransferProgress;
import io.xpipe.app.browser.action.BrowserAction;
import io.xpipe.app.browser.file.BrowserFileListModel;
import io.xpipe.app.browser.file.BrowserFileTransferMode;
import io.xpipe.app.browser.file.BrowserFileTransferOperation;
import io.xpipe.app.browser.file.FileSystemHelper;
import io.xpipe.app.browser.session.BrowserAbstractSessionModel;
import io.xpipe.app.browser.session.BrowserStoreSessionTab;
import io.xpipe.app.browser.BrowserAbstractSessionModel;
import io.xpipe.app.browser.BrowserStoreSessionTab;
import io.xpipe.app.comp.base.ModalOverlayComp;
import io.xpipe.app.ext.ProcessControlProvider;
import io.xpipe.app.ext.ShellStore;
import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.storage.DataStoreEntryRef;
@@ -28,7 +21,6 @@ import io.xpipe.core.store.*;
import io.xpipe.core.util.FailableConsumer;
import io.xpipe.core.util.FailableRunnable;
import javafx.beans.Observable;
import javafx.beans.binding.Bindings;
import javafx.beans.property.*;
@@ -46,21 +38,21 @@ import java.util.UUID;
import java.util.stream.Stream;
@Getter
public final class OpenFileSystemModel extends BrowserStoreSessionTab<FileSystemStore> {
public final class BrowserFileSystemTabModel extends BrowserStoreSessionTab<FileSystemStore> {
private final Property<String> filter = new SimpleStringProperty();
private final BrowserFileListModel fileList;
private final ReadOnlyObjectWrapper<String> currentPath = new ReadOnlyObjectWrapper<>();
private final OpenFileSystemHistory history = new OpenFileSystemHistory();
private final BrowserFileSystemHistory history = new BrowserFileSystemHistory();
private final Property<ModalOverlayComp.OverlayContent> overlay = new SimpleObjectProperty<>();
private final BooleanProperty inOverview = new SimpleBooleanProperty();
private final Property<BrowserTransferProgress> progress = new SimpleObjectProperty<>();
private final ObservableList<UUID> terminalRequests = FXCollections.observableArrayList();
private FileSystem fileSystem;
private OpenFileSystemSavedState savedState;
private OpenFileSystemCache cache;
private BrowserFileSystemSavedState savedState;
private BrowserFileSystemCache cache;
public OpenFileSystemModel(
public BrowserFileSystemTabModel(
BrowserAbstractSessionModel<?> model,
DataStoreEntryRef<? extends FileSystemStore> entry,
SelectionMode selectionMode) {
@@ -75,7 +67,7 @@ public final class OpenFileSystemModel extends BrowserStoreSessionTab<FileSystem
@Override
public Comp<?> comp() {
return new OpenFileSystemComp(this, true);
return new BrowserFileSystemTabComp(this, true);
}
@Override
@@ -105,12 +97,12 @@ public final class OpenFileSystemModel extends BrowserStoreSessionTab<FileSystem
}
this.fileSystem = fs;
this.cache = new OpenFileSystemCache(this);
this.cache = new BrowserFileSystemCache(this);
for (BrowserAction b : BrowserAction.ALL) {
b.init(this);
}
});
this.savedState = OpenFileSystemSavedState.loadForStore(this);
this.savedState = BrowserFileSystemSavedState.loadForStore(this);
}
@Override
@@ -125,8 +117,8 @@ public final class OpenFileSystemModel extends BrowserStoreSessionTab<FileSystem
&& savedState != null
&& current != null) {
savedState.cd(current.getPath(), false);
BrowserSavedStateImpl.get()
.add(new BrowserSavedState.Entry(getEntry().get().getUuid(), current.getPath()));
BrowserHistorySavedStateImpl.get()
.add(new BrowserHistorySavedState.Entry(getEntry().get().getUuid(), current.getPath()));
}
try {
fileSystem.close();
@@ -232,7 +224,7 @@ public final class OpenFileSystemModel extends BrowserStoreSessionTab<FileSystem
}
// Fix common issues with paths
var adjustedPath = FileSystemHelper.adjustPath(this, path);
var adjustedPath = BrowserFileSystemHelper.adjustPath(this, path);
if (!Objects.equals(path, adjustedPath)) {
return Optional.of(adjustedPath);
}
@@ -240,7 +232,7 @@ public final class OpenFileSystemModel extends BrowserStoreSessionTab<FileSystem
// Evaluate optional expressions
String evaluatedPath;
try {
evaluatedPath = FileSystemHelper.evaluatePath(this, adjustedPath);
evaluatedPath = BrowserFileSystemHelper.evaluatePath(this, adjustedPath);
} catch (Exception ex) {
ErrorEvent.fromThrowable(ex).handle();
return Optional.ofNullable(currentPath.get());
@@ -287,7 +279,7 @@ public final class OpenFileSystemModel extends BrowserStoreSessionTab<FileSystem
// Evaluate optional links
String resolvedPath;
try {
resolvedPath = FileSystemHelper.resolveDirectoryPath(this, evaluatedPath, customInput);
resolvedPath = BrowserFileSystemHelper.resolveDirectoryPath(this, evaluatedPath, customInput);
} catch (Exception ex) {
ErrorEvent.fromThrowable(ex).handle();
return Optional.ofNullable(currentPath.get());
@@ -298,7 +290,7 @@ public final class OpenFileSystemModel extends BrowserStoreSessionTab<FileSystem
}
try {
FileSystemHelper.validateDirectoryPath(this, resolvedPath, customInput);
BrowserFileSystemHelper.validateDirectoryPath(this, resolvedPath, customInput);
cdSyncWithoutCheck(path);
} catch (Exception ex) {
ErrorEvent.fromThrowable(ex).handle();

View File

@@ -1,6 +1,5 @@
package io.xpipe.app.browser.file;
import io.xpipe.app.browser.BrowserTransferProgress;
import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.core.store.*;
@@ -50,7 +49,7 @@ public class BrowserFileTransferOperation {
}
try {
return LocalFileSystem.getLocalFileEntry(path);
return BrowserLocalFileSystem.getLocalFileEntry(path);
} catch (Exception e) {
throw new RuntimeException(e);
}

View File

@@ -1,10 +1,10 @@
package io.xpipe.app.browser;
package io.xpipe.app.browser.file;
import io.xpipe.app.core.AppFont;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.core.AppLayoutModel;
import io.xpipe.app.fxcomps.SimpleComp;
import io.xpipe.app.fxcomps.util.PlatformThread;
import io.xpipe.app.comp.SimpleComp;
import io.xpipe.app.util.PlatformThread;
import io.xpipe.core.process.OsType;
import javafx.scene.control.Label;

View File

@@ -1,4 +1,4 @@
package io.xpipe.app.browser;
package io.xpipe.app.browser.file;
import javafx.collections.ObservableList;
@@ -9,7 +9,7 @@ import lombok.extern.jackson.Jacksonized;
import java.util.UUID;
public interface BrowserSavedState {
public interface BrowserHistorySavedState {
void add(Entry entry);

View File

@@ -1,4 +1,4 @@
package io.xpipe.app.browser;
package io.xpipe.app.browser.file;
import io.xpipe.app.core.AppCache;
import io.xpipe.core.util.JacksonMapper;
@@ -19,33 +19,33 @@ import lombok.Value;
import java.util.List;
@Value
@JsonDeserialize(using = BrowserSavedStateImpl.Deserializer.class)
public class BrowserSavedStateImpl implements BrowserSavedState {
@JsonDeserialize(using = BrowserHistorySavedStateImpl.Deserializer.class)
public class BrowserHistorySavedStateImpl implements BrowserHistorySavedState {
@JsonSerialize(as = List.class)
ObservableList<Entry> lastSystems;
public BrowserSavedStateImpl(List<Entry> lastSystems) {
public BrowserHistorySavedStateImpl(List<Entry> lastSystems) {
this.lastSystems = FXCollections.observableArrayList(lastSystems);
}
private static BrowserSavedStateImpl INSTANCE;
private static BrowserHistorySavedStateImpl INSTANCE;
public static BrowserSavedState get() {
public static BrowserHistorySavedState get() {
if (INSTANCE == null) {
INSTANCE = load();
}
return INSTANCE;
}
private static BrowserSavedStateImpl load() {
return AppCache.getNonNull("browser-state", BrowserSavedStateImpl.class, () -> {
return new BrowserSavedStateImpl(FXCollections.observableArrayList());
private static BrowserHistorySavedStateImpl load() {
return AppCache.getNonNull("browser-state", BrowserHistorySavedStateImpl.class, () -> {
return new BrowserHistorySavedStateImpl(FXCollections.observableArrayList());
});
}
@Override
public synchronized void add(BrowserSavedState.Entry entry) {
public synchronized void add(BrowserHistorySavedState.Entry entry) {
lastSystems.removeIf(s -> s.getUuid().equals(entry.getUuid()));
lastSystems.addFirst(entry);
if (lastSystems.size() > 15) {
@@ -63,15 +63,15 @@ public class BrowserSavedStateImpl implements BrowserSavedState {
return lastSystems;
}
public static class Deserializer extends StdDeserializer<BrowserSavedStateImpl> {
public static class Deserializer extends StdDeserializer<BrowserHistorySavedStateImpl> {
protected Deserializer() {
super(BrowserSavedStateImpl.class);
super(BrowserHistorySavedStateImpl.class);
}
@Override
@SneakyThrows
public BrowserSavedStateImpl deserialize(JsonParser p, DeserializationContext ctxt) {
public BrowserHistorySavedStateImpl deserialize(JsonParser p, DeserializationContext ctxt) {
var tree = (ObjectNode) JacksonMapper.getDefault().readTree(p);
JavaType javaType =
JacksonMapper.getDefault().getTypeFactory().constructCollectionLikeType(List.class, Entry.class);
@@ -79,7 +79,7 @@ public class BrowserSavedStateImpl implements BrowserSavedState {
if (ls == null) {
ls = List.of();
}
return new BrowserSavedStateImpl(ls);
return new BrowserHistorySavedStateImpl(ls);
}
}
}

View File

@@ -1,19 +1,19 @@
package io.xpipe.app.browser;
package io.xpipe.app.browser.file;
import io.xpipe.app.browser.session.BrowserSessionModel;
import io.xpipe.app.browser.BrowserFullSessionModel;
import io.xpipe.app.comp.base.ButtonComp;
import io.xpipe.app.comp.base.ListBoxViewComp;
import io.xpipe.app.comp.base.TileButtonComp;
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.HorizontalComp;
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.DerivedObservableList;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.SimpleComp;
import io.xpipe.app.comp.base.HorizontalComp;
import io.xpipe.app.comp.base.LabelComp;
import io.xpipe.app.comp.base.PrettyImageHelper;
import io.xpipe.app.comp.base.PrettySvgComp;
import io.xpipe.app.util.BindingsHelper;
import io.xpipe.app.util.DerivedObservableList;
import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.util.ThreadHelper;
@@ -35,17 +35,17 @@ import atlantafx.base.theme.Styles;
import java.util.List;
public class BrowserWelcomeComp extends SimpleComp {
public class BrowserHistoryTabComp extends SimpleComp {
private final BrowserSessionModel model;
private final BrowserFullSessionModel model;
public BrowserWelcomeComp(BrowserSessionModel model) {
public BrowserHistoryTabComp(BrowserFullSessionModel model) {
this.model = model;
}
@Override
protected Region createSimple() {
var state = BrowserSavedStateImpl.get();
var state = BrowserHistorySavedStateImpl.get();
var welcome = new BrowserGreetingComp().createSimple();
@@ -144,7 +144,7 @@ public class BrowserWelcomeComp extends SimpleComp {
return layout;
}
private Comp<?> entryButton(BrowserSavedState.Entry e, BooleanProperty disable) {
private Comp<?> entryButton(BrowserHistorySavedState.Entry e, BooleanProperty disable) {
var entry = DataStorage.get().getStoreEntryIfPresent(e.getUuid());
var graphic = entry.get().getEffectiveIconFile();
var view = PrettyImageHelper.ofFixedSize(graphic, 22, 16);
@@ -167,7 +167,7 @@ public class BrowserWelcomeComp extends SimpleComp {
.apply(struc -> struc.get().setAlignment(Pos.CENTER_LEFT));
}
private Comp<?> dirButton(BrowserSavedState.Entry e, BooleanProperty disable) {
private Comp<?> dirButton(BrowserHistorySavedState.Entry e, BooleanProperty disable) {
return new ButtonComp(new SimpleStringProperty(e.getPath()), null, () -> {
ThreadHelper.runAsync(() -> {
model.restoreStateAsync(e, disable);

View File

@@ -1,21 +1,21 @@
package io.xpipe.app.browser;
package io.xpipe.app.browser.file;
import io.xpipe.app.browser.session.BrowserAbstractSessionModel;
import io.xpipe.app.browser.session.BrowserSessionModel;
import io.xpipe.app.browser.session.BrowserSessionTab;
import io.xpipe.app.browser.BrowserAbstractSessionModel;
import io.xpipe.app.browser.BrowserFullSessionModel;
import io.xpipe.app.browser.BrowserSessionTab;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.storage.DataColor;
public final class BrowserHomeTabModel extends BrowserSessionTab {
public final class BrowserHistoryTabModel extends BrowserSessionTab {
public BrowserHomeTabModel(BrowserAbstractSessionModel<?> browserModel) {
super(browserModel, AppI18n.get("overview"));
public BrowserHistoryTabModel(BrowserAbstractSessionModel<?> browserModel) {
super(browserModel, AppI18n.get("history"));
}
@Override
public Comp<?> comp() {
return new BrowserWelcomeComp((BrowserSessionModel) browserModel);
return new BrowserHistoryTabComp((BrowserFullSessionModel) browserModel);
}
@Override

View File

@@ -8,7 +8,7 @@ import io.xpipe.core.store.FileSystem;
import java.nio.file.Files;
import java.nio.file.Path;
public class LocalFileSystem {
public class BrowserLocalFileSystem {
private static FileSystem localFileSystem;

View File

@@ -1,15 +1,13 @@
package io.xpipe.app.browser;
package io.xpipe.app.browser.file;
import io.xpipe.app.browser.file.BrowserContextMenu;
import io.xpipe.app.browser.fs.OpenFileSystemModel;
import io.xpipe.app.browser.icon.FileIconManager;
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.impl.PrettyImageHelper;
import io.xpipe.app.fxcomps.impl.TextFieldComp;
import io.xpipe.app.fxcomps.impl.TooltipAugment;
import io.xpipe.app.browser.icon.BrowserIconManager;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.CompStructure;
import io.xpipe.app.comp.SimpleCompStructure;
import io.xpipe.app.comp.augment.ContextMenuAugment;
import io.xpipe.app.comp.base.PrettyImageHelper;
import io.xpipe.app.comp.base.TextFieldComp;
import io.xpipe.app.comp.base.TooltipAugment;
import io.xpipe.app.util.BooleanScope;
import io.xpipe.app.util.ThreadHelper;
@@ -33,58 +31,16 @@ import javafx.scene.shape.Rectangle;
import atlantafx.base.theme.Styles;
import org.kordamp.ikonli.javafx.FontIcon;
public class BrowserNavBar extends Comp<BrowserNavBar.Structure> {
public class BrowserNavBarComp extends Comp<BrowserNavBarComp.Structure> {
@Override
public Structure createBase() {
var path = new SimpleStringProperty(model.getCurrentPath().get());
model.getCurrentPath().subscribe((newValue) -> {
path.set(newValue);
});
path.addListener((observable, oldValue, newValue) -> {
ThreadHelper.runFailableAsync(() -> {
BooleanScope.executeExclusive(model.getBusy(), () -> {
var changed = model.cdSyncOrRetry(newValue, true);
changed.ifPresent(s -> Platform.runLater(() -> path.set(s)));
});
});
});
var pathBar = new TextFieldComp(path, true)
.styleClass(Styles.CENTER_PILL)
.styleClass("path-text")
.apply(struc -> {
struc.get().focusedProperty().subscribe(val -> {
struc.get()
.pseudoClassStateChanged(
INVISIBLE,
!val && !model.getInOverview().get());
if (val) {
Platform.runLater(() -> {
struc.get().end();
});
}
});
model.getInOverview().subscribe(val -> {
// Pseudo classes do not apply if set instantly before shown
// If we start a new tab with a directory set, we have to set the pseudo class one pulse later
Platform.runLater(() -> {
struc.get()
.pseudoClassStateChanged(
INVISIBLE, !val && !struc.get().isFocused());
});
});
struc.get().setPromptText("Overview of " + model.getName());
})
.accessibleText("Current path");
var pathBar = createPathBar();
var graphic = Bindings.createStringBinding(
() -> {
return model.getCurrentDirectory() != null
? FileIconManager.getFileIcon(model.getCurrentDirectory())
? BrowserIconManager.getFileIcon(model.getCurrentDirectory())
: null;
},
model.getCurrentPath());
@@ -154,6 +110,52 @@ public class BrowserNavBar extends Comp<BrowserNavBar.Structure> {
return new Structure(topBox, pathRegion, historyButton);
}
private Comp<CompStructure<TextField>> createPathBar() {
var path = new SimpleStringProperty(model.getCurrentPath().get());
model.getCurrentPath().subscribe((newValue) -> {
path.set(newValue);
});
path.addListener((observable, oldValue, newValue) -> {
ThreadHelper.runFailableAsync(() -> {
BooleanScope.executeExclusive(model.getBusy(), () -> {
var changed = model.cdSyncOrRetry(newValue, true);
changed.ifPresent(s -> Platform.runLater(() -> path.set(s)));
});
});
});
var pathBar = new TextFieldComp(path, true)
.styleClass(Styles.CENTER_PILL)
.styleClass("path-text");
pathBar.apply(struc -> {
struc.get().focusedProperty().subscribe(val -> {
struc.get()
.pseudoClassStateChanged(
INVISIBLE,
!val && !model.getInOverview().get());
if (val) {
Platform.runLater(() -> {
struc.get().end();
});
}
});
model.getInOverview().subscribe(val -> {
// Pseudo classes do not apply if set instantly before shown
// If we start a new tab with a directory set, we have to set the pseudo class one pulse later
Platform.runLater(() -> {
struc.get()
.pseudoClassStateChanged(
INVISIBLE, !val && !struc.get().isFocused());
});
});
struc.get().setPromptText("Overview of " + model.getName());
})
.accessibleText("Current path");
return pathBar;
}
public record Structure(HBox box, TextField textField, Button historyButton) implements CompStructure<HBox> {
@Override
@@ -164,9 +166,9 @@ public class BrowserNavBar extends Comp<BrowserNavBar.Structure> {
private static final PseudoClass INVISIBLE = PseudoClass.getPseudoClass("invisible");
private final OpenFileSystemModel model;
private final BrowserFileSystemTabModel model;
public BrowserNavBar(OpenFileSystemModel model) {
public BrowserNavBarComp(BrowserFileSystemTabModel model) {
this.model = model;
}

View File

@@ -1,13 +1,11 @@
package io.xpipe.app.browser;
package io.xpipe.app.browser.file;
import io.xpipe.app.browser.file.BrowserFileOverviewComp;
import io.xpipe.app.browser.fs.OpenFileSystemModel;
import io.xpipe.app.comp.base.SimpleTitledPaneComp;
import io.xpipe.app.core.AppFont;
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.DerivedObservableList;
import io.xpipe.app.comp.SimpleComp;
import io.xpipe.app.comp.base.VerticalComp;
import io.xpipe.app.util.DerivedObservableList;
import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.app.util.ThreadHelper;
import io.xpipe.core.process.ShellControl;
@@ -25,9 +23,9 @@ import java.util.List;
public class BrowserOverviewComp extends SimpleComp {
private final OpenFileSystemModel model;
private final BrowserFileSystemTabModel model;
public BrowserOverviewComp(OpenFileSystemModel model) {
public BrowserOverviewComp(BrowserFileSystemTabModel model) {
this.model = model;
}

View File

@@ -1,8 +1,7 @@
package io.xpipe.app.browser.file;
import io.xpipe.app.browser.fs.OpenFileSystemModel;
import io.xpipe.app.fxcomps.SimpleComp;
import io.xpipe.app.fxcomps.impl.IconButtonComp;
import io.xpipe.app.comp.SimpleComp;
import io.xpipe.app.comp.base.IconButtonComp;
import io.xpipe.app.util.InputHelper;
import javafx.scene.layout.Region;
@@ -12,9 +11,9 @@ import java.util.function.Supplier;
public class BrowserQuickAccessButtonComp extends SimpleComp {
private final Supplier<BrowserEntry> base;
private final OpenFileSystemModel model;
private final BrowserFileSystemTabModel model;
public BrowserQuickAccessButtonComp(Supplier<BrowserEntry> base, OpenFileSystemModel model) {
public BrowserQuickAccessButtonComp(Supplier<BrowserEntry> base, BrowserFileSystemTabModel model) {
this.base = base;
this.model = model;
}

View File

@@ -1,8 +1,7 @@
package io.xpipe.app.browser.file;
import io.xpipe.app.browser.fs.OpenFileSystemModel;
import io.xpipe.app.browser.icon.FileIconManager;
import io.xpipe.app.fxcomps.impl.PrettyImageHelper;
import io.xpipe.app.browser.icon.BrowserIconManager;
import io.xpipe.app.comp.base.PrettyImageHelper;
import io.xpipe.app.util.BooleanAnimationTimer;
import io.xpipe.app.util.InputHelper;
import io.xpipe.app.util.ThreadHelper;
@@ -32,13 +31,13 @@ import java.util.stream.Collectors;
public class BrowserQuickAccessContextMenu extends ContextMenu {
private final Supplier<BrowserEntry> base;
private final OpenFileSystemModel model;
private final BrowserFileSystemTabModel model;
private ContextMenu shownBrowserActionsMenu;
private boolean expandBrowserActionMenuKey;
private boolean keyBasedNavigation;
private boolean closeBrowserActionMenuKey;
public BrowserQuickAccessContextMenu(Supplier<BrowserEntry> base, OpenFileSystemModel model) {
public BrowserQuickAccessContextMenu(Supplier<BrowserEntry> base, BrowserFileSystemTabModel model) {
this.base = base;
this.model = model;
@@ -142,7 +141,7 @@ public class BrowserQuickAccessContextMenu extends ContextMenu {
this.menu = new Menu(
// Use original name, not the link target
browserEntry.getRawFileEntry().getName(),
PrettyImageHelper.ofFixedSize(FileIconManager.getFileIcon(browserEntry.getRawFileEntry()), 24, 24)
PrettyImageHelper.ofFixedSize(BrowserIconManager.getFileIcon(browserEntry.getRawFileEntry()), 24, 24)
.createRegion());
createMenu();
addInputListeners();

View File

@@ -1,16 +1,13 @@
package io.xpipe.app.browser;
package io.xpipe.app.browser.file;
import io.xpipe.app.browser.file.BrowserContextMenu;
import io.xpipe.app.browser.file.BrowserFileListCompEntry;
import io.xpipe.app.browser.fs.OpenFileSystemModel;
import io.xpipe.app.core.AppFont;
import io.xpipe.app.fxcomps.Comp;
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.HorizontalComp;
import io.xpipe.app.fxcomps.impl.LabelComp;
import io.xpipe.app.fxcomps.util.BindingsHelper;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.SimpleComp;
import io.xpipe.app.comp.SimpleCompStructure;
import io.xpipe.app.comp.augment.ContextMenuAugment;
import io.xpipe.app.comp.base.HorizontalComp;
import io.xpipe.app.comp.base.LabelComp;
import io.xpipe.app.util.BindingsHelper;
import io.xpipe.app.util.HumanReadableFormat;
import javafx.beans.binding.Bindings;
@@ -29,7 +26,7 @@ import java.util.List;
@EqualsAndHashCode(callSuper = true)
public class BrowserStatusBarComp extends SimpleComp {
OpenFileSystemModel model;
BrowserFileSystemTabModel model;
@Override
protected Region createSimple() {

View File

@@ -1,11 +1,11 @@
package io.xpipe.app.browser;
package io.xpipe.app.browser.file;
import io.xpipe.app.browser.session.BrowserAbstractSessionModel;
import io.xpipe.app.browser.session.BrowserSessionModel;
import io.xpipe.app.browser.session.BrowserSessionTab;
import io.xpipe.app.browser.BrowserAbstractSessionModel;
import io.xpipe.app.browser.BrowserFullSessionModel;
import io.xpipe.app.browser.BrowserSessionTab;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.core.AppLayoutModel;
import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.storage.DataColor;
import io.xpipe.app.terminal.TerminalDockComp;
import io.xpipe.app.terminal.TerminalDockModel;
@@ -14,7 +14,6 @@ import io.xpipe.app.terminal.TerminalViewInstance;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.beans.value.ObservableBooleanValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import java.util.ArrayList;
@@ -83,7 +82,7 @@ public final class BrowserTerminalDockTabModel extends BrowserSessionTab {
public void onTerminalClosed(TerminalViewInstance instance) {
terminals.remove(instance);
if (terminals.isEmpty()) {
((BrowserSessionModel) browserModel).unsplitTab(BrowserTerminalDockTabModel.this);
((BrowserFullSessionModel) browserModel).unsplitTab(BrowserTerminalDockTabModel.this);
}
}
};

View File

@@ -1,13 +1,11 @@
package io.xpipe.app.browser;
package io.xpipe.app.browser.file;
import io.xpipe.app.browser.fs.OpenFileSystemModel;
import io.xpipe.app.comp.base.*;
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.augment.DragOverPseudoClassAugment;
import io.xpipe.app.fxcomps.impl.*;
import io.xpipe.app.fxcomps.util.DerivedObservableList;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.SimpleComp;
import io.xpipe.app.util.DerivedObservableList;
import io.xpipe.app.util.ThreadHelper;
import javafx.beans.binding.Bindings;
@@ -17,6 +15,7 @@ import javafx.css.PseudoClass;
import javafx.geometry.Insets;
import javafx.scene.image.Image;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.DragEvent;
import javafx.scene.input.Dragboard;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.Region;
@@ -52,7 +51,7 @@ public class BrowserTransferComp extends SimpleComp {
var binding = new DerivedObservableList<>(model.getItems(), true)
.mapped(item -> item.getBrowserEntry())
.getList();
var list = new BrowserSelectionListComp(binding, entry -> {
var list = new BrowserFileSelectionListComp(binding, entry -> {
var sourceItem = model.getCurrentItems().stream()
.filter(item -> item.getBrowserEntry() == entry)
.findAny();
@@ -106,8 +105,12 @@ public class BrowserTransferComp extends SimpleComp {
.apply(struc -> struc.get().setMinHeight(200))
.apply(struc -> struc.get().setMaxHeight(200));
var stack = new StackComp(List.of(backgroundStack, listBox))
.apply(DragOverPseudoClassAugment.create())
.apply(struc -> {
struc.get().addEventFilter(DragEvent.DRAG_ENTERED, event -> {
struc.get().pseudoClassStateChanged(PseudoClass.getPseudoClass("drag-over"), true);
});
struc.get().addEventFilter(DragEvent.DRAG_EXITED, event -> struc.get()
.pseudoClassStateChanged(PseudoClass.getPseudoClass("drag-over"), false));
struc.get().setOnDragOver(event -> {
// Accept drops from inside the app window
if (event.getGestureSource() != null && event.getGestureSource() != struc.get()) {
@@ -126,7 +129,7 @@ public class BrowserTransferComp extends SimpleComp {
if (!(model.getBrowserSessionModel()
.getSelectedEntry()
.getValue()
instanceof OpenFileSystemModel fileSystemModel)) {
instanceof BrowserFileSystemTabModel fileSystemModel)) {
return;
}
@@ -166,7 +169,7 @@ public class BrowserTransferComp extends SimpleComp {
Dragboard db = struc.get().startDragAndDrop(TransferMode.COPY);
db.setContent(cc);
Image image = BrowserSelectionListComp.snapshot(FXCollections.observableList(selected));
Image image = BrowserFileSelectionListComp.snapshot(FXCollections.observableList(selected));
db.setDragView(image, -20, 15);
event.setDragDetect(true);

View File

@@ -1,11 +1,6 @@
package io.xpipe.app.browser;
package io.xpipe.app.browser.file;
import io.xpipe.app.browser.file.BrowserEntry;
import io.xpipe.app.browser.file.BrowserFileTransferMode;
import io.xpipe.app.browser.file.BrowserFileTransferOperation;
import io.xpipe.app.browser.file.LocalFileSystem;
import io.xpipe.app.browser.fs.OpenFileSystemModel;
import io.xpipe.app.browser.session.BrowserSessionModel;
import io.xpipe.app.browser.BrowserFullSessionModel;
import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.app.util.DesktopHelper;
import io.xpipe.app.util.ShellTemp;
@@ -34,11 +29,11 @@ public class BrowserTransferModel {
private static final Path TEMP = ShellTemp.getLocalTempDataDirectory("download");
BrowserSessionModel browserSessionModel;
BrowserFullSessionModel browserSessionModel;
ObservableList<Item> items = FXCollections.observableArrayList();
ObservableBooleanValue empty = Bindings.createBooleanBinding(() -> items.isEmpty(), items);
public BrowserTransferModel(BrowserSessionModel browserSessionModel) {
public BrowserTransferModel(BrowserFullSessionModel browserSessionModel) {
this.browserSessionModel = browserSessionModel;
var thread = ThreadHelper.createPlatformThread("file downloader", true, () -> {
while (true) {
@@ -96,7 +91,7 @@ public class BrowserTransferModel {
}
}
public void drop(OpenFileSystemModel model, List<BrowserEntry> entries) {
public void drop(BrowserFileSystemTabModel model, List<BrowserEntry> entries) {
synchronized (items) {
entries.forEach(entry -> {
var name = entry.getFileName();
@@ -130,7 +125,7 @@ public class BrowserTransferModel {
try {
var op = new BrowserFileTransferOperation(
LocalFileSystem.getLocalFileEntry(TEMP),
BrowserLocalFileSystem.getLocalFileEntry(TEMP),
List.of(item.getBrowserEntry().getRawFileEntry()),
BrowserFileTransferMode.COPY,
false,
@@ -190,13 +185,13 @@ public class BrowserTransferModel {
@Value
public static class Item {
OpenFileSystemModel openFileSystemModel;
BrowserFileSystemTabModel openFileSystemModel;
String name;
BrowserEntry browserEntry;
Path localFile;
Property<BrowserTransferProgress> progress;
public Item(OpenFileSystemModel openFileSystemModel, String name, BrowserEntry browserEntry, Path localFile) {
public Item(BrowserFileSystemTabModel openFileSystemModel, String name, BrowserEntry browserEntry, Path localFile) {
this.openFileSystemModel = openFileSystemModel;
this.name = name;
this.browserEntry = browserEntry;

View File

@@ -1,4 +1,4 @@
package io.xpipe.app.browser;
package io.xpipe.app.browser.file;
import lombok.Value;

View File

@@ -63,7 +63,7 @@ public abstract class BrowserIconDirectoryType {
var closedIcon = "browser/" + split[2].trim();
var lightClosedIcon = split.length > 4 ? "browser/" + split[4].trim() : closedIcon;
ALL.add(new Simple(id, new IconVariant(lightClosedIcon, closedIcon), filter));
ALL.add(new Simple(id, new BrowserIconVariant(lightClosedIcon, closedIcon), filter));
}
}
});
@@ -84,10 +84,10 @@ public abstract class BrowserIconDirectoryType {
@Getter
private final String id;
private final IconVariant closed;
private final BrowserIconVariant closed;
private final Set<String> names;
public Simple(String id, IconVariant closed, Set<String> names) {
public Simple(String id, BrowserIconVariant closed, Set<String> names) {
this.id = id;
this.closed = closed;
this.names = names;

View File

@@ -69,11 +69,11 @@ public abstract class BrowserIconFileType {
public static class Simple extends BrowserIconFileType {
private final String id;
private final IconVariant icon;
private final BrowserIconVariant icon;
private final Set<String> endings;
public Simple(String id, String lightIcon, String darkIcon, Set<String> endings) {
this.icon = new IconVariant(lightIcon, darkIcon);
this.icon = new BrowserIconVariant(lightIcon, darkIcon);
this.id = id;
this.endings = endings;
}

View File

@@ -3,7 +3,7 @@ package io.xpipe.app.browser.icon;
import io.xpipe.core.store.FileEntry;
import io.xpipe.core.store.FileKind;
public class FileIconManager {
public class BrowserIconManager {
private static boolean loaded;

View File

@@ -2,16 +2,16 @@ package io.xpipe.app.browser.icon;
import io.xpipe.app.prefs.AppPrefs;
public class IconVariant {
public class BrowserIconVariant {
private final String lightIcon;
private final String darkIcon;
public IconVariant(String icon) {
public BrowserIconVariant(String icon) {
this(icon, icon);
}
public IconVariant(String lightIcon, String darkIcon) {
public BrowserIconVariant(String lightIcon, String darkIcon) {
this.lightIcon = lightIcon;
this.darkIcon = darkIcon;
}

View File

@@ -1,7 +1,7 @@
package io.xpipe.app.browser.icon;
import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.fxcomps.impl.PrettyImageHelper;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.base.PrettyImageHelper;
import io.xpipe.core.store.FileEntry;
public class BrowserIcons {
@@ -19,6 +19,6 @@ public class BrowserIcons {
}
public static Comp<?> createIcon(FileEntry entry) {
return PrettyImageHelper.ofFixedSizeSquare(FileIconManager.getFileIcon(entry), 24);
return PrettyImageHelper.ofFixedSizeSquare(BrowserIconManager.getFileIcon(entry), 24);
}
}

View File

@@ -1,11 +1,11 @@
package io.xpipe.app.fxcomps;
package io.xpipe.app.comp;
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.TooltipAugment;
import io.xpipe.app.fxcomps.util.BindingsHelper;
import io.xpipe.app.fxcomps.util.PlatformThread;
import io.xpipe.app.comp.augment.Augment;
import io.xpipe.app.comp.augment.GrowAugment;
import io.xpipe.app.comp.base.TooltipAugment;
import io.xpipe.app.util.BindingsHelper;
import io.xpipe.app.util.PlatformThread;
import javafx.application.Platform;
import javafx.beans.value.ObservableValue;

View File

@@ -1,4 +1,4 @@
package io.xpipe.app.fxcomps;
package io.xpipe.app.comp;
import javafx.scene.layout.Region;

View File

@@ -1,59 +0,0 @@
package io.xpipe.app.comp;
import io.xpipe.app.comp.base.ButtonComp;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.core.mode.OperationMode;
import io.xpipe.app.fxcomps.SimpleComp;
import io.xpipe.app.issue.ErrorEvent;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Region;
import java.nio.file.Path;
public class DeveloperTabComp extends SimpleComp {
@Override
protected Region createSimple() {
var button = new ButtonComp(AppI18n.observable("Throw exception"), null, () -> {
throw new IllegalStateException();
});
var button2 = new ButtonComp(AppI18n.observable("Throw exception with file"), null, () -> {
try {
throw new IllegalStateException();
} catch (Exception ex) {
ErrorEvent.fromThrowable(ex)
.attachment(Path.of("extensions.txt"))
.build()
.handle();
}
});
var button3 = new ButtonComp(AppI18n.observable("Exit"), null, () -> {
System.exit(0);
});
var button6 = new ButtonComp(AppI18n.observable("Restart"), null, () -> {
OperationMode.restart();
});
var button4 = new ButtonComp(AppI18n.observable("Throw terminal exception"), null, () -> {
try {
throw new IllegalStateException();
} catch (Exception ex) {
ErrorEvent.fromThrowable(ex).terminal(true).build().handle();
}
});
var button5 = new ButtonComp(AppI18n.observable("Operation mode null"), null, OperationMode::close);
return new HBox(
button.createRegion(),
button2.createRegion(),
button3.createRegion(),
button4.createRegion(),
button5.createRegion(),
button6.createRegion());
}
}

View File

@@ -1,4 +1,4 @@
package io.xpipe.app.fxcomps;
package io.xpipe.app.comp;
import javafx.scene.layout.Region;

View File

@@ -1,4 +1,4 @@
package io.xpipe.app.fxcomps;
package io.xpipe.app.comp;
import javafx.scene.layout.Region;

View File

@@ -1,7 +1,7 @@
package io.xpipe.app.fxcomps.augment;
package io.xpipe.app.comp.augment;
import io.xpipe.app.fxcomps.CompStructure;
import io.xpipe.app.fxcomps.SimpleCompStructure;
import io.xpipe.app.comp.CompStructure;
import io.xpipe.app.comp.SimpleCompStructure;
import javafx.scene.Node;
import javafx.scene.layout.Region;

View File

@@ -1,6 +1,6 @@
package io.xpipe.app.fxcomps.augment;
package io.xpipe.app.comp.augment;
import io.xpipe.app.fxcomps.CompStructure;
import io.xpipe.app.comp.CompStructure;
import javafx.event.ActionEvent;
import javafx.geometry.Side;

View File

@@ -1,6 +1,6 @@
package io.xpipe.app.fxcomps.augment;
package io.xpipe.app.comp.augment;
import io.xpipe.app.fxcomps.CompStructure;
import io.xpipe.app.comp.CompStructure;
import javafx.beans.binding.Bindings;
import javafx.scene.Node;

View File

@@ -1,8 +1,8 @@
package io.xpipe.app.fxcomps.impl;
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.comp.Comp;
import io.xpipe.app.comp.CompStructure;
import io.xpipe.app.comp.SimpleCompStructure;
import javafx.scene.layout.AnchorPane;

View File

@@ -1,17 +1,14 @@
package io.xpipe.app.comp;
package io.xpipe.app.comp.base;
import io.xpipe.app.comp.base.MultiContentComp;
import io.xpipe.app.comp.base.SideMenuBarComp;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.CompStructure;
import io.xpipe.app.comp.SimpleCompStructure;
import io.xpipe.app.comp.store.StoreViewState;
import io.xpipe.app.core.AppFont;
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.prefs.AppPrefs;
import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.terminal.TerminalView;
import javafx.beans.binding.Bindings;
import javafx.beans.value.ObservableValue;
import javafx.scene.Parent;

View File

@@ -1,62 +0,0 @@
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 javafx.beans.value.ChangeListener;
import javafx.geometry.Rectangle2D;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Pane;
public class BackgroundImageComp extends Comp<CompStructure<Pane>> {
private final Image image;
public BackgroundImageComp(Image image) {
this.image = image;
}
@Override
public CompStructure<Pane> createBase() {
ImageView v = new ImageView(image);
Pane pane = new Pane(v);
v.fitWidthProperty().bind(pane.widthProperty());
v.fitHeightProperty().bind(pane.heightProperty());
if (image == null) {
return new SimpleCompStructure<>(pane);
}
double imageAspect = image.getWidth() / image.getHeight();
ChangeListener<? super Number> cl = (c, o, n) -> {
double paneAspect = pane.getWidth() / pane.getHeight();
double relViewportWidth;
double relViewportHeight;
// Pane width too big for image
if (paneAspect > imageAspect) {
relViewportWidth = 1;
double newImageHeight = pane.getWidth() / imageAspect;
relViewportHeight = Math.min(1, pane.getHeight() / newImageHeight);
}
// Height too big
else {
relViewportHeight = 1;
double newImageWidth = pane.getHeight() * imageAspect;
relViewportWidth = Math.min(1, pane.getWidth() / newImageWidth);
}
v.setViewport(new Rectangle2D(
((1 - relViewportWidth) / 2.0) * image.getWidth(),
((1 - relViewportHeight) / 2.0) * image.getHeight(),
image.getWidth() * relViewportWidth,
image.getHeight() * relViewportHeight));
};
pane.widthProperty().addListener(cl);
pane.heightProperty().addListener(cl);
return new SimpleCompStructure<>(pane);
}
}

View File

@@ -1,66 +0,0 @@
package io.xpipe.app.comp.base;
import io.xpipe.app.fxcomps.CompStructure;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import lombok.Builder;
import lombok.Value;
public class BigIconButton extends ButtonComp {
public BigIconButton(ObservableValue<String> name, Node graphic, Runnable listener) {
super(name, graphic, listener);
}
@Override
public Structure createBase() {
var vbox = new VBox();
vbox.getStyleClass().add("vbox");
vbox.setAlignment(Pos.CENTER);
var icon = new StackPane(getGraphic());
icon.setAlignment(Pos.CENTER);
icon.getStyleClass().add("icon");
vbox.getChildren().add(icon);
var label = new Label();
label.textProperty().bind(getName());
label.getStyleClass().add("name");
vbox.getChildren().add(label);
var b = new Button(null);
b.accessibleTextProperty().bind(getName());
b.setGraphic(vbox);
b.setOnAction(e -> getListener().run());
b.getStyleClass().add("big-icon-button-comp");
return Structure.builder()
.stack(vbox)
.graphic(getGraphic())
.graphicPane(icon)
.text(label)
.button(b)
.build();
}
@Value
@Builder
public static class Structure implements CompStructure<Button> {
Button button;
VBox stack;
Node graphic;
StackPane graphicPane;
Label text;
@Override
public Button get() {
return button;
}
}
}

View File

@@ -1,9 +1,9 @@
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.PlatformThread;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.CompStructure;
import io.xpipe.app.comp.SimpleCompStructure;
import io.xpipe.app.util.PlatformThread;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;

View File

@@ -1,10 +1,10 @@
package io.xpipe.app.fxcomps.impl;
package io.xpipe.app.comp.base;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.fxcomps.CompStructure;
import io.xpipe.app.fxcomps.SimpleCompStructure;
import io.xpipe.app.fxcomps.util.PlatformThread;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.CompStructure;
import io.xpipe.app.comp.SimpleCompStructure;
import io.xpipe.app.util.PlatformThread;
import io.xpipe.app.util.Translatable;
import javafx.beans.property.Property;

View File

@@ -1,9 +1,9 @@
package io.xpipe.app.fxcomps.impl;
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.PlatformThread;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.CompStructure;
import io.xpipe.app.comp.SimpleCompStructure;
import io.xpipe.app.util.PlatformThread;
import javafx.beans.property.Property;
import javafx.beans.value.ObservableValue;

View File

@@ -1,9 +1,9 @@
package io.xpipe.app.fxcomps.impl;
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.PlatformThread;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.CompStructure;
import io.xpipe.app.comp.SimpleCompStructure;
import io.xpipe.app.util.PlatformThread;
import javafx.beans.property.Property;
import javafx.collections.FXCollections;

View File

@@ -1,12 +1,11 @@
package io.xpipe.app.fxcomps.impl;
package io.xpipe.app.comp.base;
import io.xpipe.app.browser.session.BrowserChooserComp;
import io.xpipe.app.comp.base.ButtonComp;
import io.xpipe.app.browser.BrowserFileChooserSessionComp;
import io.xpipe.app.core.AppLayoutModel;
import io.xpipe.app.core.window.AppWindowHelper;
import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.fxcomps.CompStructure;
import io.xpipe.app.fxcomps.SimpleCompStructure;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.CompStructure;
import io.xpipe.app.comp.SimpleCompStructure;
import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.app.storage.ContextualFileReference;
@@ -67,7 +66,7 @@ public class ContextualFileReferenceChoiceComp extends Comp<CompStructure<HBox>>
public CompStructure<HBox> createBase() {
var path = previousFileReferences.isEmpty() ? createTextField() : createComboBox();
var fileBrowseButton = new ButtonComp(null, new FontIcon("mdi2f-folder-open-outline"), () -> {
BrowserChooserComp.openSingleFile(
BrowserFileChooserSessionComp.openSingleFile(
() -> fileSystem.getValue(),
fileStore -> {
if (fileStore == null) {

View File

@@ -1,9 +1,9 @@
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.PlatformThread;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.CompStructure;
import io.xpipe.app.comp.SimpleCompStructure;
import io.xpipe.app.util.PlatformThread;
import javafx.beans.binding.Bindings;
import javafx.collections.ObservableList;

View File

@@ -2,9 +2,9 @@ package io.xpipe.app.comp.base;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.core.window.AppWindowHelper;
import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.fxcomps.CompStructure;
import io.xpipe.app.fxcomps.SimpleCompStructure;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.CompStructure;
import io.xpipe.app.comp.SimpleCompStructure;
import javafx.application.Platform;
import javafx.beans.property.SimpleBooleanProperty;

View File

@@ -1,9 +1,9 @@
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.augment.ContextMenuAugment;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.CompStructure;
import io.xpipe.app.comp.SimpleCompStructure;
import io.xpipe.app.comp.augment.ContextMenuAugment;
import javafx.beans.binding.Bindings;
import javafx.beans.value.ObservableValue;

View File

@@ -1,8 +1,8 @@
package io.xpipe.app.comp.base;
import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.fxcomps.SimpleComp;
import io.xpipe.app.fxcomps.util.PlatformThread;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.SimpleComp;
import io.xpipe.app.util.PlatformThread;
import javafx.beans.property.Property;
import javafx.beans.property.SimpleObjectProperty;

View File

@@ -1,7 +1,7 @@
package io.xpipe.app.comp.base;
import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.fxcomps.CompStructure;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.CompStructure;
import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.core.util.FailableConsumer;

View File

@@ -1,11 +1,11 @@
package io.xpipe.app.fxcomps.impl;
package io.xpipe.app.comp.base;
import io.xpipe.app.core.AppActionLinkDetector;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.fxcomps.CompStructure;
import io.xpipe.app.fxcomps.SimpleCompStructure;
import io.xpipe.app.fxcomps.util.PlatformThread;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.CompStructure;
import io.xpipe.app.comp.SimpleCompStructure;
import io.xpipe.app.util.PlatformThread;
import javafx.beans.binding.Bindings;
import javafx.beans.property.Property;

View File

@@ -1,8 +1,8 @@
package io.xpipe.app.comp.base;
import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.fxcomps.CompStructure;
import io.xpipe.app.fxcomps.util.PlatformThread;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.CompStructure;
import io.xpipe.app.util.PlatformThread;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ObservableValue;

View File

@@ -1,8 +1,8 @@
package io.xpipe.app.fxcomps.impl;
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.comp.Comp;
import io.xpipe.app.comp.CompStructure;
import io.xpipe.app.comp.SimpleCompStructure;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;

View File

@@ -1,8 +1,8 @@
package io.xpipe.app.fxcomps.impl;
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.comp.Comp;
import io.xpipe.app.comp.CompStructure;
import io.xpipe.app.comp.SimpleCompStructure;
import javafx.geometry.Pos;
import javafx.scene.layout.HBox;

View File

@@ -1,10 +1,10 @@
package io.xpipe.app.fxcomps.impl;
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.LabelGraphic;
import io.xpipe.app.fxcomps.util.PlatformThread;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.CompStructure;
import io.xpipe.app.comp.SimpleCompStructure;
import io.xpipe.app.util.LabelGraphic;
import io.xpipe.app.util.PlatformThread;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ObservableValue;

View File

@@ -1,9 +1,9 @@
package io.xpipe.app.fxcomps.impl;
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.PlatformThread;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.CompStructure;
import io.xpipe.app.comp.SimpleCompStructure;
import io.xpipe.app.util.PlatformThread;
import javafx.beans.property.Property;
import javafx.beans.value.ChangeListener;

View File

@@ -1,9 +1,9 @@
package io.xpipe.app.fxcomps.impl;
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.PlatformThread;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.CompStructure;
import io.xpipe.app.comp.SimpleCompStructure;
import io.xpipe.app.util.PlatformThread;
import javafx.beans.property.Property;
import javafx.beans.value.ChangeListener;

View File

@@ -1,9 +1,7 @@
package io.xpipe.app.comp.base;
import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.fxcomps.CompStructure;
import io.xpipe.app.fxcomps.impl.IconButtonComp;
import io.xpipe.app.fxcomps.impl.TextAreaComp;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.CompStructure;
import io.xpipe.app.util.FileOpener;
import javafx.application.Platform;

View File

@@ -1,9 +1,9 @@
package io.xpipe.app.fxcomps.impl;
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.PlatformThread;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.CompStructure;
import io.xpipe.app.comp.SimpleCompStructure;
import io.xpipe.app.util.PlatformThread;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ObservableValue;

View File

@@ -1,9 +1,9 @@
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.PlatformThread;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.CompStructure;
import io.xpipe.app.comp.SimpleCompStructure;
import io.xpipe.app.util.PlatformThread;
import javafx.beans.property.Property;
import javafx.beans.property.SimpleStringProperty;

View File

@@ -1,7 +1,7 @@
package io.xpipe.app.comp.base;
import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.fxcomps.CompStructure;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.CompStructure;
import javafx.scene.control.SplitPane;
import javafx.scene.layout.Region;

View File

@@ -1,10 +1,10 @@
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.DerivedObservableList;
import io.xpipe.app.fxcomps.util.PlatformThread;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.CompStructure;
import io.xpipe.app.comp.SimpleCompStructure;
import io.xpipe.app.util.DerivedObservableList;
import io.xpipe.app.util.PlatformThread;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;

View File

@@ -1,7 +1,7 @@
package io.xpipe.app.comp.base;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.fxcomps.SimpleComp;
import io.xpipe.app.comp.SimpleComp;
import javafx.beans.property.ListProperty;
import javafx.geometry.Orientation;

View File

@@ -1,9 +1,9 @@
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.PlatformThread;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.CompStructure;
import io.xpipe.app.comp.SimpleCompStructure;
import io.xpipe.app.util.PlatformThread;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.app.util.ThreadHelper;

View File

@@ -1,10 +1,10 @@
package io.xpipe.app.comp.base;
import io.xpipe.app.core.AppProperties;
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.comp.Comp;
import io.xpipe.app.comp.CompStructure;
import io.xpipe.app.comp.SimpleCompStructure;
import io.xpipe.app.util.PlatformThread;
import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.app.resources.AppResources;

View File

@@ -1,8 +1,7 @@
package io.xpipe.app.comp.base;
import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.fxcomps.CompStructure;
import io.xpipe.app.fxcomps.impl.IconButtonComp;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.CompStructure;
import io.xpipe.app.util.FileOpener;
import javafx.application.Platform;

View File

@@ -2,9 +2,9 @@ package io.xpipe.app.comp.base;
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.util.PlatformThread;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.SimpleComp;
import io.xpipe.app.util.PlatformThread;
import javafx.application.Platform;
import javafx.beans.property.Property;

View File

@@ -1,8 +1,8 @@
package io.xpipe.app.comp.base;
import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.fxcomps.SimpleComp;
import io.xpipe.app.fxcomps.util.PlatformThread;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.SimpleComp;
import io.xpipe.app.util.PlatformThread;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;

View File

@@ -1,11 +1,10 @@
package io.xpipe.app.fxcomps.impl;
package io.xpipe.app.comp.base;
import io.xpipe.app.comp.base.MarkdownComp;
import io.xpipe.app.core.AppFont;
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.comp.Comp;
import io.xpipe.app.comp.CompStructure;
import io.xpipe.app.comp.SimpleCompStructure;
import io.xpipe.app.util.PlatformThread;
import javafx.beans.Observable;
import javafx.beans.binding.Bindings;

View File

@@ -1,8 +1,8 @@
package io.xpipe.app.comp.base;
import io.xpipe.app.core.AppFont;
import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.fxcomps.SimpleComp;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.comp.SimpleComp;
import javafx.beans.value.ObservableValue;
import javafx.scene.control.Button;

View File

@@ -1,7 +1,7 @@
package io.xpipe.app.fxcomps.impl;
package io.xpipe.app.comp.base;
import io.xpipe.app.fxcomps.SimpleComp;
import io.xpipe.app.fxcomps.util.PlatformThread;
import io.xpipe.app.comp.SimpleComp;
import io.xpipe.app.util.PlatformThread;
import io.xpipe.app.issue.TrackEvent;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.app.resources.AppImages;

View File

@@ -1,8 +1,8 @@
package io.xpipe.app.fxcomps.impl;
package io.xpipe.app.comp.base;
import io.xpipe.app.core.App;
import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.fxcomps.util.BindingsHelper;
import io.xpipe.app.comp.Comp;
import io.xpipe.app.util.BindingsHelper;
import io.xpipe.app.resources.AppImages;
import io.xpipe.core.store.FileNames;

View File

@@ -1,7 +1,7 @@
package io.xpipe.app.fxcomps.impl;
package io.xpipe.app.comp.base;
import io.xpipe.app.fxcomps.SimpleComp;
import io.xpipe.app.fxcomps.util.PlatformThread;
import io.xpipe.app.comp.SimpleComp;
import io.xpipe.app.util.PlatformThread;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.app.resources.AppImages;
import io.xpipe.core.store.FileNames;

Some files were not shown because too many files have changed in this diff Show More