This commit is contained in:
crschnick 2024-04-07 08:07:05 +00:00
parent 7263214894
commit dfcb90bd16
11 changed files with 80 additions and 62 deletions

View file

@ -35,7 +35,7 @@ import java.util.Optional;
import java.util.stream.Stream;
@Getter
public final class OpenFileSystemModel extends BrowserSessionEntry {
public final class OpenFileSystemModel extends BrowserSessionEntry<FileSystemStore> {
private final Property<String> filter = new SimpleStringProperty();
private final BrowserFileListModel fileList;

View file

@ -1,28 +1,43 @@
package io.xpipe.app.browser.session;
import io.xpipe.app.util.BooleanScope;
import io.xpipe.app.util.ThreadHelper;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.Property;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import lombok.Getter;
@Getter
public class BrowserAbstractSessionModel<T extends BrowserSessionEntry> {
public class BrowserAbstractSessionModel<T extends BrowserSessionEntry<?>> {
protected final ObservableList<T> sessionEntries = FXCollections.observableArrayList();
protected final Property<T> selectedEntry = new SimpleObjectProperty<>();
public void closeAsync(BrowserSessionEntry open) {
public void closeAsync(BrowserSessionEntry<?> e) {
ThreadHelper.runAsync(() -> {
closeSync(open);
closeSync(e);
});
}
void closeSync(BrowserSessionEntry open) {
open.close();
public void openSync(T e, BooleanProperty externalBusy) throws Exception {
try (var b = new BooleanScope(externalBusy != null ? externalBusy : new SimpleBooleanProperty()).start()) {
e.init();
// Prevent multiple calls from interfering with each other
synchronized (this) {
sessionEntries.add(e);
// The tab pane doesn't automatically select new tabs
selectedEntry.setValue(e);
}
}
}
void closeSync(BrowserSessionEntry<?> e) {
e.close();
synchronized (BrowserAbstractSessionModel.this) {
this.sessionEntries.remove(open);
this.sessionEntries.remove(e);
}
}
}

View file

@ -1,7 +1,7 @@
package io.xpipe.app.browser.session;
import atlantafx.base.controls.Spacer;
import io.xpipe.app.browser.*;
import io.xpipe.app.browser.BrowserBookmarkComp;
import io.xpipe.app.browser.file.BrowserEntry;
import io.xpipe.app.browser.fs.OpenFileSystemComp;
import io.xpipe.app.browser.fs.OpenFileSystemModel;
@ -21,7 +21,6 @@ import io.xpipe.app.util.ThreadHelper;
import io.xpipe.core.store.FileSystemStore;
import io.xpipe.core.store.ShellStore;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.Property;
import javafx.collections.ListChangeListener;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
@ -45,34 +44,21 @@ public class BrowserChooserComp extends SimpleComp {
}
public static void openSingleFile(
Supplier<DataStoreEntryRef<? extends FileSystemStore>> store, Consumer<FileReference> file) {
Supplier<DataStoreEntryRef<? extends FileSystemStore>> store, Consumer<FileReference> file, boolean save) {
PlatformThread.runLaterIfNeeded(() -> {
var model = new BrowserChooserModel(OpenFileSystemModel.SelectionMode.SINGLE_FILE);
var comp = new BrowserChooserComp(model)
.apply(struc -> struc.get().setPrefSize(1200, 700))
.apply(struc -> AppFont.normal(struc.get()));
var window = AppWindowHelper.sideWindow(AppI18n.get("openFileTitle"), stage -> comp, false, null);
var window = AppWindowHelper.sideWindow(AppI18n.get(save ? "saveFileTitle" : "openFileTitle"), stage -> comp, false, null);
model.setOnFinish(fileStores -> {
file.accept(fileStores.size() > 0 ? fileStores.getFirst() : null);
window.close();
});
window.show();
ThreadHelper.runAsync(() -> {
model.openFileSystemAsync(store.get(), null, null);
});
}
public static void saveSingleFile(Property<FileReference> file) {
PlatformThread.runLaterIfNeeded(() -> {
var model = new BrowserChooserModel(OpenFileSystemModel.SelectionMode.SINGLE_FILE);
var comp = new BrowserChooserComp(model)
.apply(struc -> struc.get().setPrefSize(1200, 700))
.apply(struc -> AppFont.normal(struc.get()));
var window = AppWindowHelper.sideWindow(AppI18n.get("saveFileTitle"), stage -> comp, true, null);
model.setOnFinish(fileStores -> {
file.setValue(fileStores.size() > 0 ? fileStores.getFirst() : null);
window.close();
});
window.show();
});
}

View file

@ -3,21 +3,21 @@ package io.xpipe.app.browser.session;
import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.storage.DataStoreEntryRef;
import io.xpipe.core.store.FileSystemStore;
import io.xpipe.core.store.DataStore;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import lombok.Getter;
@Getter
public abstract class BrowserSessionEntry {
public abstract class BrowserSessionEntry<T extends DataStore> {
protected final DataStoreEntryRef<? extends FileSystemStore> entry;
protected final DataStoreEntryRef<? extends T> entry;
protected final BooleanProperty busy = new SimpleBooleanProperty();
protected final BrowserAbstractSessionModel<?> browserModel;
protected final String name;
protected final String tooltip;
public BrowserSessionEntry(BrowserAbstractSessionModel<?> browserModel, DataStoreEntryRef<? extends FileSystemStore> entry) {
public BrowserSessionEntry(BrowserAbstractSessionModel<?> browserModel, DataStoreEntryRef<? extends T> entry) {
this.browserModel = browserModel;
this.entry = entry;
this.name = DataStorage.get().getStoreDisplayName(entry.get());

View file

@ -21,7 +21,7 @@ import lombok.Getter;
import java.util.ArrayList;
@Getter
public class BrowserSessionModel extends BrowserAbstractSessionModel<BrowserSessionEntry> {
public class BrowserSessionModel extends BrowserAbstractSessionModel<BrowserSessionEntry<?>> {
public static final BrowserSessionModel DEFAULT = new BrowserSessionModel(BrowserSavedStateImpl.load());

View file

@ -6,7 +6,9 @@ import io.xpipe.app.comp.base.ButtonComp;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.core.AppLayoutModel;
import io.xpipe.app.core.AppWindowHelper;
import io.xpipe.app.fxcomps.SimpleComp;
import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.fxcomps.CompStructure;
import io.xpipe.app.fxcomps.SimpleCompStructure;
import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.app.storage.ContextualFileReference;
@ -22,7 +24,6 @@ import javafx.beans.value.ObservableValue;
import javafx.scene.control.Alert;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.Region;
import org.kordamp.ikonli.javafx.FontIcon;
import java.nio.file.Files;
@ -30,7 +31,7 @@ import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.List;
public class ContextualFileReferenceChoiceComp extends SimpleComp {
public class ContextualFileReferenceChoiceComp extends Comp<CompStructure<HBox>> {
private final Property<DataStoreEntryRef<? extends FileSystemStore>> fileSystem;
private final Property<String> filePath;
@ -45,7 +46,7 @@ public class ContextualFileReferenceChoiceComp extends SimpleComp {
}
@Override
protected Region createSimple() {
public CompStructure<HBox> createBase() {
var fileNameComp = new TextFieldComp(filePath)
.apply(struc -> HBox.setHgrow(struc.get(), Priority.ALWAYS))
.styleClass(Styles.LEFT_PILL)
@ -60,7 +61,7 @@ public class ContextualFileReferenceChoiceComp extends SimpleComp {
filePath.setValue(fileStore.getPath());
fileSystem.setValue(fileStore.getFileSystem());
}
});
}, false);
})
.styleClass(Styles.CENTER_PILL)
.grow(false, true);
@ -129,6 +130,6 @@ public class ContextualFileReferenceChoiceComp extends SimpleComp {
});
});
return layout.createRegion();
return new SimpleCompStructure<>(layout.createStructure().get());
}
}

View file

@ -5,36 +5,52 @@ import io.xpipe.app.storage.DataStoreEntryRef;
import io.xpipe.app.util.StringSource;
import io.xpipe.core.store.ShellStore;
import javafx.beans.property.Property;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ObservableValue;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;
public class StringSourceComp extends SimpleComp {
private final Property<DataStoreEntryRef<? extends ShellStore>> fileSystem;
private final Property<DataStoreEntryRef<ShellStore>> fileSystem;
private final Property<StringSource> stringSource;
public <T extends ShellStore> StringSourceComp(ObservableValue<DataStoreEntryRef<T>> fileSystem, Property<StringSource> stringSource) {
this.stringSource = stringSource;
this.fileSystem = new SimpleObjectProperty<>();
fileSystem.subscribe(val -> {
this.fileSystem.setValue(val);
this.fileSystem.setValue(val.get().ref());
});
}
@Override
protected Region createSimple() {
var tab = new TabPane();
var inPlace = new SimpleObjectProperty<>(stringSource.getValue() instanceof StringSource.InPlace i ? i.get() : null);
var stringField = new TextAreaComp(inPlace);
tab.getTabs().add(new Tab());
var fs = stringSource.getValue() instanceof StringSource.File f ? f.getFile() : null;
var file = new SimpleObjectProperty<>(stringSource.getValue() instanceof StringSource.File f ? f.getFile() : null);
// new ContextualFileReferenceChoiceComp(fileSystem, file);
return null;
var file = new SimpleObjectProperty<>(stringSource.getValue() instanceof StringSource.File f ? f.getFile().serialize() : null);
var showText = new SimpleBooleanProperty(inPlace.get() != null);
var stringField = new TextAreaComp(inPlace);
stringField.hide(showText.not());
var fileComp = new ContextualFileReferenceChoiceComp(fileSystem, file);
fileComp.hide(showText);
var tr = stringField.createRegion();
var button = new IconButtonComp("mdi2c-checkbox-marked-outline", () -> {
showText.set(!showText.getValue());
}).createRegion();
AnchorPane.setBottomAnchor(button, 10.0);
AnchorPane.setRightAnchor(button, 10.0);
var anchorPane = new AnchorPane(tr, button);
AnchorPane.setBottomAnchor(tr, 0.0);
AnchorPane.setTopAnchor(tr, 0.0);
AnchorPane.setLeftAnchor(tr, 0.0);
AnchorPane.setRightAnchor(tr, 0.0);
var fr = fileComp.createRegion();
return new StackPane(tr, fr);
}
}

View file

@ -111,7 +111,7 @@ public class DataStoreEntry extends StorageElement {
this.categoryUuid = categoryUuid;
this.store = store;
this.storeNode = null;
this.validity = Validity.COMPLETE;
this.validity = Validity.INCOMPLETE;
this.configuration = Configuration.defaultConfiguration();
this.expanded = false;
this.color = null;

View file

@ -426,7 +426,7 @@ predefined=Predefined
default=Default
goodMorning=Good morning
goodAfternoon=Good afternoon
goodNight=Good night
goodEvening=Good evening
addVisual=Visual ...
ssh=SSH
sshConfiguration=SSH Configuration

View file

@ -12,7 +12,7 @@ Die genaue Anzahl der unterstützten Optionen hängt ausschließlich von deinem
Der Inhalt hier entspricht einem Host-Abschnitt in einer SSH-Konfigurationsdatei.
Beachte, dass du den `Host`-Eintrag nicht explizit definieren musst, denn das wird automatisch erledigt.
Wenn du mehr als einen Host-Abschnitt definieren willst, z. B. bei abhängigen Verbindungen wie einem Proxy-Jump-Host, der von einem anderen Config-Host abhängt, solltest du stattdessen eine richtige SSH-Konfigurationsdatei verwenden, da hier nur genau eine Host-Definition unterstützt wird.
Wenn du mehr als einen Host-Abschnitt definieren willst, z. B. bei abhängigen Verbindungen wie einem Proxy-Jump-Host, der von einem anderen Config-Host abhängt, kannst du auch mehrere Host-Einträge definieren. Es wird dann der erste Host als Verbindung genutzt.
Du musst keine Formatierung mit Leerzeichen oder Einrückung vornehmen, das ist für die Funktion nicht erforderlich.

View file

@ -12,7 +12,7 @@ The exact amount of supported options purely depends on your installed SSH clien
The content here is equivalent to one host section in an SSH config file.
Note that you don't have to explicitly define the `Host` entry, as that will be done automatically.
If you intend to define more than one host section, e.g. with dependent connections such as a proxy jump host that depends on another config host, you should use a proper SSH config file instead as only exactly one host definition is supported here.
If you intend to define more than one host section, e.g. with dependent connections such as a proxy jump host that depends on another config host, you can define multiple host entries in here as well. XPipe will then launch the first host entry.
You don't have to perform any formatting with whitespace or indentation, this is not needed for it to function.