Various small improvements

This commit is contained in:
crschnick
2023-07-04 01:28:33 +00:00
parent d84789b995
commit 313cc922ee
44 changed files with 523 additions and 166 deletions

View File

@@ -47,6 +47,12 @@ public class FileSystemHelper {
return null;
}
if (path.startsWith("\"") && path.endsWith("\"")) {
path = path.substring(1, path.length() - 1);
} else if (path.startsWith("'") && path.endsWith("'")) {
path = path.substring(1, path.length() - 1);
}
// Handle special case when file system creation has failed
if (model.getFileSystem() == null) {
return path;
@@ -100,6 +106,10 @@ public class FileSystemHelper {
throw new IllegalArgumentException(String.format("Directory %s is not absolute", resolved));
}
if (model.getFileSystem().fileExists(path)) {
return FileNames.toDirectory(FileNames.getParent(path));
}
return FileNames.toDirectory(resolved);
}

View File

@@ -1,93 +1,58 @@
package io.xpipe.app.comp;
import io.xpipe.app.browser.BrowserComp;
import io.xpipe.app.browser.BrowserModel;
import io.xpipe.app.comp.base.SideMenuBarComp;
import io.xpipe.app.comp.storage.store.StoreLayoutComp;
import io.xpipe.app.core.*;
import io.xpipe.app.core.AppActionLinkDetector;
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.fxcomps.util.PlatformThread;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.app.prefs.PrefsComp;
import javafx.beans.property.Property;
import javafx.beans.property.SimpleObjectProperty;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyCodeCombination;
import javafx.scene.input.KeyCombination;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Region;
import lombok.SneakyThrows;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class AppLayoutComp extends Comp<CompStructure<BorderPane>> {
private final List<SideMenuBarComp.Entry> entries;
private final Property<SideMenuBarComp.Entry> selected;
private final AppLayoutModel model = AppLayoutModel.get();
public AppLayoutComp() {
entries = createEntryList();
selected = new SimpleObjectProperty<>(AppState.get().isInitialLaunch() ? entries.get(1) : entries.get(0));
shortcut(new KeyCodeCombination(KeyCode.V, KeyCombination.SHORTCUT_DOWN), structure -> {
AppActionLinkDetector.detectOnPaste();
});
}
@SneakyThrows
private List<SideMenuBarComp.Entry> createEntryList() {
var l = new ArrayList<>(List.of(
new SideMenuBarComp.Entry(
AppI18n.observable("browser"), "mdi2f-file-cabinet", new BrowserComp(BrowserModel.DEFAULT)),
new SideMenuBarComp.Entry(AppI18n.observable("connections"), "mdi2c-connection", new StoreLayoutComp()),
// new SideMenuBarComp.Entry(AppI18n.observable("data"), "mdsal-dvr", new SourceCollectionLayoutComp()),
new SideMenuBarComp.Entry(
AppI18n.observable("settings"), "mdsmz-miscellaneous_services", new PrefsComp(this))));
// new SideMenuBarComp.Entry(AppI18n.observable("help"), "mdi2b-book-open-variant", new
// StorageLayoutComp()),
// new SideMenuBarComp.Entry(AppI18n.observable("account"), "mdi2a-account", new StorageLayoutComp())
if (AppProperties.get().isDeveloperMode() && !AppProperties.get().isImage()) {
l.add(new SideMenuBarComp.Entry(
AppI18n.observable("developer"), "mdi2b-book-open-variant", new DeveloperTabComp()));
}
// l.add(new SideMenuBarComp.Entry(AppI18n.observable("abc"), "mdi2b-book-open-variant", Comp.of(() -> {
// var fi = new FontIcon("mdsal-dvr");
// fi.setIconSize(30);
// fi.setIconColor(Color.valueOf("#111C"));
// JfxHelper.addEffect(fi);
// return new StackPane(fi);
// })));
return l;
}
@Override
public CompStructure<BorderPane> createBase() {
var map = new HashMap<SideMenuBarComp.Entry, Region>();
getRegion(entries.get(0), map);
getRegion(entries.get(1), map);
var map = new HashMap<AppLayoutModel.Entry, Region>();
getRegion(model.getEntries().get(0), map);
getRegion(model.getEntries().get(1), map);
var pane = new BorderPane();
var sidebar = new SideMenuBarComp(selected, entries);
pane.setCenter(getRegion(selected.getValue(), map));
var sidebar = new SideMenuBarComp(model.getSelected(), model.getEntries());
pane.setCenter(getRegion(model.getSelected().getValue(), map));
pane.setRight(sidebar.createRegion());
selected.addListener((c, o, n) -> {
if (o != null && o.equals(entries.get(2))) {
model.getSelected().addListener((c, o, n) -> {
if (o != null && o.equals(model.getEntries().get(2))) {
AppPrefs.get().save();
}
pane.setCenter(getRegion(n, map));
PlatformThread.runLaterIfNeeded(() -> {
pane.setCenter(getRegion(n, map));
});
});
AppFont.normal(pane);
return new SimpleCompStructure<>(pane);
}
private Region getRegion(SideMenuBarComp.Entry entry, Map<SideMenuBarComp.Entry, Region> map) {
private Region getRegion(AppLayoutModel.Entry entry, Map<AppLayoutModel.Entry, Region> map) {
if (map.containsKey(entry)) {
return map.get(entry);
}
@@ -96,16 +61,4 @@ public class AppLayoutComp extends Comp<CompStructure<BorderPane>> {
map.put(entry, r);
return r;
}
public List<SideMenuBarComp.Entry> getEntries() {
return entries;
}
public SideMenuBarComp.Entry getSelected() {
return selected.getValue();
}
public Property<SideMenuBarComp.Entry> selectedProperty() {
return selected;
}
}

View File

@@ -1,6 +1,7 @@
package io.xpipe.app.comp.base;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.core.AppLayoutModel;
import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.fxcomps.CompStructure;
import io.xpipe.app.fxcomps.SimpleCompStructure;
@@ -10,7 +11,6 @@ import io.xpipe.app.update.UpdateAvailableAlert;
import io.xpipe.app.update.XPipeDistributionType;
import javafx.beans.binding.Bindings;
import javafx.beans.property.Property;
import javafx.beans.value.ObservableValue;
import javafx.css.PseudoClass;
import javafx.scene.control.Button;
import javafx.scene.layout.Priority;
@@ -21,10 +21,10 @@ import java.util.List;
public class SideMenuBarComp extends Comp<CompStructure<VBox>> {
private final Property<SideMenuBarComp.Entry> value;
private final List<Entry> entries;
private final Property<AppLayoutModel.Entry> value;
private final List<AppLayoutModel.Entry> entries;
public SideMenuBarComp(Property<Entry> value, List<Entry> entries) {
public SideMenuBarComp(Property<AppLayoutModel.Entry> value, List<AppLayoutModel.Entry> entries) {
this.value = value;
this.entries = entries;
}
@@ -42,14 +42,15 @@ public class SideMenuBarComp extends Comp<CompStructure<VBox>> {
b.apply(struc -> {
struc.get().pseudoClassStateChanged(selected, value.getValue().equals(e));
value.addListener((c, o, n) -> {
struc.get().pseudoClassStateChanged(selected, n.equals(e));
PlatformThread.runLaterIfNeeded(() -> {
struc.get().pseudoClassStateChanged(selected, n.equals(e));
});
});
});
vbox.getChildren().add(b.createRegion());
});
{
// vbox.getChildren().add(new Spacer(Orientation.VERTICAL));
var fi = new FontIcon("mdi2u-update");
var b = new BigIconButton(AppI18n.observable("update"), fi, () -> UpdateAvailableAlert.showIfNeeded());
b.apply(GrowAugment.create(true, false));
@@ -76,5 +77,4 @@ public class SideMenuBarComp extends Comp<CompStructure<VBox>> {
return new SimpleCompStructure<>(vbox);
}
public record Entry(ObservableValue<String> name, String icon, Comp<?> comp) {}
}

View File

@@ -31,15 +31,13 @@ public class DenseStoreEntryComp extends StoreEntryComp {
grid.getColumnConstraints().add(new ColumnConstraints(0));
}
var custom = new ColumnConstraints(content != null ? 300 : 0);
var customSize = content != null ? 300 : 0;
var custom = new ColumnConstraints(0, customSize, customSize);
custom.setHalignment(HPos.RIGHT);
custom.setMinWidth(Region.USE_PREF_SIZE);
custom.setMaxWidth(Region.USE_PREF_SIZE);
var info = new ColumnConstraints(content != null ? 300 : 600);
var infoSize = content != null ? 300 : 600;
var info = new ColumnConstraints(0, infoSize, infoSize);
info.setHalignment(HPos.LEFT);
info.setMinWidth(Region.USE_PREF_SIZE);
info.setMaxWidth(Region.USE_PREF_SIZE);
var nameCC = new ColumnConstraints();
nameCC.setMinWidth(100);

View File

@@ -31,16 +31,14 @@ public class StandardStoreEntryComp extends StoreEntryComp {
grid.getColumnConstraints().addAll(nameCC);
grid.add(createInformation(), 2, 0, 1, 2);
var info = new ColumnConstraints(content != null ? 300 : 600);
var infoSize = content != null ? 300 : 600;
var info = new ColumnConstraints(0, infoSize, infoSize);
info.setHalignment(HPos.LEFT);
info.setMinWidth(Region.USE_PREF_SIZE);
info.setMaxWidth(Region.USE_PREF_SIZE);
grid.getColumnConstraints().add(info);
var custom = new ColumnConstraints(content != null ? 300 : 0);
var customSize = content != null ? 300 : 0;
var custom = new ColumnConstraints(0, customSize, customSize);
custom.setHalignment(HPos.RIGHT);
custom.setMinWidth(Region.USE_PREF_SIZE);
custom.setMaxWidth(Region.USE_PREF_SIZE);
var cr = content != null ? content.createRegion() : new Region();
var bb = createButtonBar().createRegion();
var controls = new HBox(cr, bb);

View File

@@ -175,8 +175,12 @@ public abstract class StoreEntryComp extends SimpleComp {
var list = new ArrayList<Comp<?>>();
for (var p : wrapper.getActionProviders().entrySet()) {
var actionProvider = p.getKey().getDataStoreCallSite();
if (!actionProvider.isMajor()
|| p.getKey().equals(wrapper.getDefaultActionProvider().getValue())) {
if (!actionProvider.isMajor(wrapper.getEntry().getStore().asNeeded())) {
continue;
}
var def = p.getKey().getDefaultDataStoreCallSite();
if (def != null && def.equals(wrapper.getDefaultActionProvider().getValue())) {
continue;
}
@@ -234,7 +238,7 @@ public abstract class StoreEntryComp extends SimpleComp {
for (var p : wrapper.getActionProviders().entrySet()) {
var actionProvider = p.getKey().getDataStoreCallSite();
if (actionProvider.isMajor()) {
if (actionProvider.isMajor(wrapper.getEntry().getStore().asNeeded())) {
continue;
}
@@ -269,7 +273,6 @@ public abstract class StoreEntryComp extends SimpleComp {
}
var refresh = new MenuItem(AppI18n.get("refresh"), new FontIcon("mdal-360"));
refresh.disableProperty().bind(wrapper.getRefreshable().not());
refresh.setOnAction(event -> {
DataStorage.get().refreshAsync(wrapper.getEntry(), true);
});

View File

@@ -32,9 +32,6 @@ public class StoreEntryWrapper implements StorageFilter.Filterable {
private final StringProperty summary = new SimpleStringProperty();
private final Map<ActionProvider, BooleanProperty> actionProviders;
private final Property<ActionProvider.DefaultDataStoreCallSite<?>> defaultActionProvider;
private final BooleanProperty editable = new SimpleBooleanProperty();
private final BooleanProperty renamable = new SimpleBooleanProperty();
private final BooleanProperty refreshable = new SimpleBooleanProperty();
private final BooleanProperty deletable = new SimpleBooleanProperty();
private final BooleanProperty expanded = new SimpleBooleanProperty();
@@ -108,13 +105,6 @@ public class StoreEntryWrapper implements StorageFilter.Filterable {
}
}
editable.setValue(entry.getState() != DataStoreEntry.State.LOAD_FAILED
&& (entry.getConfiguration().isEditable()
|| AppPrefs.get().developerDisableGuiRestrictions().get()));
renamable.setValue(entry.getConfiguration().isRenameable()
|| AppPrefs.get().developerDisableGuiRestrictions().getValue());
refreshable.setValue(entry.getConfiguration().isRefreshable()
|| AppPrefs.get().developerDisableGuiRestrictions().getValue());
deletable.setValue(entry.getConfiguration().isDeletable()
|| AppPrefs.get().developerDisableGuiRestrictions().getValue());

View File

@@ -168,7 +168,7 @@ public class AppI18n {
var key = getKey(s);
if (translations == null) {
TrackEvent.warn("Translations not initialized for" + key);
TrackEvent.warn("Translations not initialized for " + key);
return s;
}

View File

@@ -0,0 +1,74 @@
package io.xpipe.app.core;
import io.xpipe.app.browser.BrowserComp;
import io.xpipe.app.browser.BrowserModel;
import io.xpipe.app.comp.DeveloperTabComp;
import io.xpipe.app.comp.storage.store.StoreLayoutComp;
import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.prefs.PrefsComp;
import javafx.beans.property.Property;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ObservableValue;
import lombok.Getter;
import java.util.ArrayList;
import java.util.List;
@Getter
public class AppLayoutModel {
private static AppLayoutModel INSTANCE;
public static AppLayoutModel get() {
return INSTANCE;
}
public static void init() {
INSTANCE = new AppLayoutModel();
}
private final List<Entry> entries;
private final Property<Entry> selected;
public AppLayoutModel() {
this.entries = createEntryList();
this.selected = new SimpleObjectProperty<>(entries.get(1));
}
public void selectBrowser() {
selected.setValue(entries.get(0));
}
public void selectConnections() {
selected.setValue(entries.get(1));
}
private List<Entry> createEntryList() {
var l = new ArrayList<>(List.of(
new Entry(
AppI18n.observable("browser"), "mdi2f-file-cabinet", new BrowserComp(BrowserModel.DEFAULT)),
new Entry(AppI18n.observable("connections"), "mdi2c-connection", new StoreLayoutComp()),
// new SideMenuBarComp.Entry(AppI18n.observable("data"), "mdsal-dvr", new SourceCollectionLayoutComp()),
new Entry(
AppI18n.observable("settings"), "mdsmz-miscellaneous_services", new PrefsComp(this))));
// new SideMenuBarComp.Entry(AppI18n.observable("help"), "mdi2b-book-open-variant", new
// StorageLayoutComp()),
// new SideMenuBarComp.Entry(AppI18n.observable("account"), "mdi2a-account", new StorageLayoutComp())
if (AppProperties.get().isDeveloperMode() && !AppProperties.get().isImage()) {
l.add(new Entry(
AppI18n.observable("developer"), "mdi2b-book-open-variant", new DeveloperTabComp()));
}
// l.add(new SideMenuBarComp.Entry(AppI18n.observable("abc"), "mdi2b-book-open-variant", Comp.of(() -> {
// var fi = new FontIcon("mdsal-dvr");
// fi.setIconSize(30);
// fi.setIconColor(Color.valueOf("#111C"));
// JfxHelper.addEffect(fi);
// return new StackPane(fi);
// })));
return l;
}
public record Entry(ObservableValue<String> name, String icon, Comp<?> comp) {}
}

View File

@@ -240,6 +240,9 @@ public class AppMainWindow {
stage.getScene().setRoot(contentR);
TrackEvent.debug("Set content scene");
contentR.prefWidthProperty().bind(stage.getScene().widthProperty());
contentR.prefHeightProperty().bind(stage.getScene().heightProperty());
stage.getScene().addEventHandler(KeyEvent.KEY_PRESSED, event -> {
if (AppProperties.get().isDeveloperMode() && event.getCode().equals(KeyCode.F6)) {
var newR = content.createRegion();

View File

@@ -83,9 +83,6 @@ public class AppTheme {
PlatformThread.runLaterIfNeeded(() -> {
for (Window window : Window.getWindows()) {
// Fix scene content not taking the correct size after style seed change
window.setWidth(window.getWidth() - 1);
var scene = window.getScene();
Image snapshot = scene.snapshot(null);
Pane root = (Pane) scene.getRoot();

View File

@@ -62,6 +62,7 @@ public abstract class PlatformMode extends OperationMode {
AppTheme.init();
AppStyle.init();
AppImages.init();
AppLayoutModel.init();
TrackEvent.info("mode", "Finished essential component initialization before platform");
TrackEvent.info("mode", "Launching application ...");

View File

@@ -4,14 +4,14 @@ import io.xpipe.beacon.RequestMessage;
import io.xpipe.beacon.ResponseMessage;
import io.xpipe.beacon.exchange.MessageExchanges;
import java.util.List;
import java.util.Optional;
import java.util.ServiceLoader;
import java.util.Set;
import java.util.stream.Collectors;
public class MessageExchangeImpls {
private static Set<MessageExchangeImpl<?, ?>> ALL;
private static List<MessageExchangeImpl<?, ?>> ALL;
public static void loadAll() {
ALL = ServiceLoader.load(MessageExchangeImpl.class).stream()
@@ -20,7 +20,7 @@ public class MessageExchangeImpls {
// TrackEvent.trace("init", "Loaded exchange implementation " + ex.getId());
return ex;
})
.collect(Collectors.toSet());
.collect(Collectors.toList());
ALL.forEach(messageExchange -> {
if (MessageExchanges.byId(messageExchange.getId()).isEmpty()) {
@@ -51,7 +51,7 @@ public class MessageExchangeImpls {
return Optional.ofNullable((MessageExchangeImpl<RQ, RS>) r.orElse(null));
}
public static Set<MessageExchangeImpl<?, ?>> getAll() {
public static List<MessageExchangeImpl<?, ?>> getAll() {
return ALL;
}
}

View File

@@ -99,7 +99,7 @@ public interface ActionProvider {
Class<T> getApplicableClass();
default boolean isMajor() {
default boolean isMajor(T o) {
return false;
}

View File

@@ -42,8 +42,12 @@ public interface DataStoreProvider {
return new StoreSectionComp(section);
}
default String failureInfo() {
return null;
default boolean canHaveSubShells() {
return true;
}
default boolean shouldHaveSubShells() {
return canHaveSubShells();
}
default Comp<?> stateDisplay(StoreEntryWrapper w) {

View File

@@ -4,13 +4,13 @@ import com.dlsc.formsfx.model.structure.Field;
import io.xpipe.core.util.ModuleLayerLoader;
import javafx.beans.value.ObservableBooleanValue;
import java.util.List;
import java.util.ServiceLoader;
import java.util.Set;
import java.util.stream.Collectors;
public abstract class PrefsProvider {
private static Set<PrefsProvider> ALL;
private static List<PrefsProvider> ALL;
public static class Loader implements ModuleLayerLoader {
@@ -18,7 +18,7 @@ public abstract class PrefsProvider {
public void init(ModuleLayer layer) {
ALL = ServiceLoader.load(layer, PrefsProvider.class).stream()
.map(ServiceLoader.Provider::get)
.collect(Collectors.toSet());
.collect(Collectors.toList());
}
@Override
@@ -32,7 +32,7 @@ public abstract class PrefsProvider {
}
}
public static Set<PrefsProvider> getAll() {
public static List<PrefsProvider> getAll() {
return ALL;
}

View File

@@ -7,7 +7,6 @@ import io.xpipe.app.fxcomps.SimpleComp;
import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.util.CustomComboBoxBuilder;
import io.xpipe.core.store.DataStore;
import io.xpipe.core.store.LeafShellStore;
import io.xpipe.core.store.ShellStore;
import javafx.beans.property.Property;
import javafx.beans.property.SimpleStringProperty;
@@ -23,6 +22,10 @@ import java.util.function.Predicate;
@AllArgsConstructor
public class DataStoreChoiceComp<T extends DataStore> extends SimpleComp {
public static <T extends DataStore> DataStoreChoiceComp<T> other(Property<T> selected, Class<T> clazz, Predicate<T> filter) {
return new DataStoreChoiceComp<T>(Mode.OTHER, null, selected, clazz, filter);
}
public static DataStoreChoiceComp<ShellStore> proxy(Property<ShellStore> selected) {
return new DataStoreChoiceComp<>(Mode.PROXY, null, selected, ShellStore.class, shellStore -> true);
}
@@ -107,7 +110,7 @@ public class DataStoreChoiceComp<T extends DataStore> extends SimpleComp {
}
var s = e.getEntry().getStore();
if (!(mode == Mode.ENVIRONMENT) && s instanceof LeafShellStore) {
if (!(mode == Mode.ENVIRONMENT) && e.getEntry().getProvider() != null && !e.getEntry().getProvider().canHaveSubShells()) {
continue;
}

View File

@@ -102,7 +102,7 @@ public class SvgView {
wv.setFocusTraversable(false);
wv.setAccessibleRole(AccessibleRole.IMAGE_VIEW);
wv.getEngine().loadContent(getHtml(svgContent.getValue()));
wv.getEngine().loadContent(svgContent.getValue() != null ? getHtml(svgContent.getValue()) : null);
svgContent.addListener((c, o, n) -> {
if (n == null) {
wv.getEngine().loadContent("");

View File

@@ -149,6 +149,19 @@ public class AppPrefs {
StringField.ofStringType(customTerminalCommand).render(() -> new SimpleTextControl()),
terminalType.isEqualTo(ExternalTerminalType.CUSTOM));
private final BooleanProperty preferTerminalTabs = typed(new SimpleBooleanProperty(true), Boolean.class);
private final BooleanField preferTerminalTabsField =
BooleanField.ofBooleanType(preferTerminalTabs).render(() -> new CustomToggleControl());
// Start behaviour
// ===============
private final ObjectProperty<ExternalStartupBehaviour> externalStartupBehaviour =
typed(new SimpleObjectProperty<>(ExternalStartupBehaviour.TRAY), ExternalStartupBehaviour.class);
private final SingleSelectionField<ExternalStartupBehaviour> externalStartupBehaviourControl =
Field.ofSingleSelectionType(externalStartupBehaviourList, externalStartupBehaviour)
.render(() -> new TranslatableComboBoxControl<>());
// Close behaviour
// ===============
private final ObjectProperty<CloseBehaviour> closeBehaviour =
@@ -170,12 +183,10 @@ public class AppPrefs {
StringField.ofStringType(customEditorCommand).render(() -> new SimpleTextControl()),
externalEditor.isEqualTo(ExternalEditorType.CUSTOM));
private final IntegerProperty editorReloadTimeout = typed(new SimpleIntegerProperty(1000), Integer.class);
private final ObjectProperty<ExternalStartupBehaviour> externalStartupBehaviour =
typed(new SimpleObjectProperty<>(ExternalStartupBehaviour.TRAY), ExternalStartupBehaviour.class);
private final SingleSelectionField<ExternalStartupBehaviour> externalStartupBehaviourControl =
Field.ofSingleSelectionType(externalStartupBehaviourList, externalStartupBehaviour)
.render(() -> new TranslatableComboBoxControl<>());
private final BooleanProperty preferEditorTabs = typed(new SimpleBooleanProperty(true), Boolean.class);
private final BooleanField preferEditorTabsField =
BooleanField.ofBooleanType(preferEditorTabs).render(() -> new CustomToggleControl());
// Automatically update
// ====================
@@ -529,15 +540,14 @@ public class AppPrefs {
"appearance",
Group.of(
"uiOptions",
Setting.of("language", languageControl, languageInternal),
Setting.of("theme", themeControl, theme),
Setting.of("useSystemFont", useSystemFontInternal),
Setting.of("tooltipDelay", tooltipDelayInternal, tooltipDelayMin, tooltipDelayMax)),
Setting.of("tooltipDelay", tooltipDelayInternal, tooltipDelayMin, tooltipDelayMax),
Setting.of("language", languageControl, languageInternal)),
Group.of("windowOptions", Setting.of("saveWindowLocation", saveWindowLocationInternal))),
Category.of(
"integrations",
"editor",
Group.of(
"editor",
Setting.of("editorProgram", externalEditorControl, externalEditor),
Setting.of("customEditorCommand", customEditorCommandControl, customEditorCommand)
.applyVisibility(VisibilityProperty.of(
@@ -546,13 +556,15 @@ public class AppPrefs {
"editorReloadTimeout",
editorReloadTimeout,
editorReloadTimeoutMin,
editorReloadTimeoutMax)),
Group.of(
"terminal",
Setting.of("terminalProgram", terminalTypeControl, terminalType),
Setting.of("customTerminalCommand", customTerminalCommandControl, customTerminalCommand)
.applyVisibility(VisibilityProperty.of(
terminalType.isEqualTo(ExternalTerminalType.CUSTOM))))),
editorReloadTimeoutMax),
Setting.of("preferEditorTabs", preferEditorTabsField, preferEditorTabs))),
Category.of("terminal",
Group.of(
Setting.of("terminalProgram", terminalTypeControl, terminalType),
Setting.of("customTerminalCommand", customTerminalCommandControl, customTerminalCommand)
.applyVisibility(VisibilityProperty.of(
terminalType.isEqualTo(ExternalTerminalType.CUSTOM))),
Setting.of("preferTerminalTabs", preferTerminalTabsField, preferTerminalTabs))),
Category.of(
"developer",
Setting.of(

View File

@@ -1,7 +1,7 @@
package io.xpipe.app.prefs;
import io.xpipe.app.comp.AppLayoutComp;
import io.xpipe.app.core.AppFont;
import io.xpipe.app.core.AppLayoutModel;
import io.xpipe.app.fxcomps.SimpleComp;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;
@@ -9,9 +9,9 @@ import org.controlsfx.control.MasterDetailPane;
public class PrefsComp extends SimpleComp {
private final AppLayoutComp layout;
private final AppLayoutModel layout;
public PrefsComp(AppLayoutComp layout) {
public PrefsComp(AppLayoutModel layout) {
this.layout = layout;
}

View File

@@ -122,12 +122,9 @@ public abstract class StorageElement {
@Value
public static class Configuration {
boolean deletable;
boolean renameable;
boolean editable;
boolean refreshable;
public static Configuration defaultConfiguration() {
return new Configuration(true, true, true, true);
return new Configuration(true);
}
}
}

View File

@@ -6,6 +6,7 @@ import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.fxcomps.impl.*;
import io.xpipe.core.util.SecretValue;
import javafx.beans.property.Property;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Orientation;
@@ -64,6 +65,11 @@ public class OptionsBuilder {
return this;
}
public OptionsBuilder disable() {
comp.disable(new SimpleBooleanProperty(true));
return this;
}
public OptionsBuilder nonNull(Validator v) {
var e = name;
var p = props.get(props.size() - 1);