Improve settings menu and connection creation [release]

This commit is contained in:
crschnick 2023-02-13 23:04:20 +00:00
parent 28a8c95c71
commit 287f3d084d
25 changed files with 304 additions and 74 deletions

View file

@ -46,7 +46,7 @@ dependencies {
implementation group: 'org.kordamp.ikonli', name: 'ikonli-materialdesign2-pack', version: "12.2.0"
implementation group: 'org.kordamp.ikonli', name: 'ikonli-javafx', version: "12.2.0"
implementation group: 'org.kordamp.ikonli', name: 'ikonli-material-pack', version: "12.2.0"
implementation group: 'com.dlsc.preferencesfx', name: 'preferencesfx-core', version: '11.15.0'
implementation name: 'preferencesfx-core-11.15.0'
implementation group: 'com.dlsc.formsfx', name: 'formsfx-core', version: '11.6.0'
implementation group: 'org.slf4j', name: 'slf4j-api', version: '2.0.0'
implementation 'io.xpipe:modulefs:0.1.4'
@ -92,6 +92,7 @@ List<String> jvmRunArgs = [
"--add-opens", "java.base/java.lang=io.xpipe.core",
"--add-opens", "com.dustinredmond.fxtrayicon/com.dustinredmond.fxtrayicon=io.xpipe.app",
"--add-opens", "net.synedra.validatorfx/net.synedra.validatorfx=io.xpipe.extension",
"--add-opens", 'com.dlsc.preferencesfx/com.dlsc.preferencesfx.view=io.xpipe.app',
"-Xmx8g",
"--enable-preview",
// "-XX:+ExitOnOutOfMemoryError",

View file

@ -22,7 +22,7 @@ import lombok.experimental.FieldDefaults;
@AllArgsConstructor
public class DataStoreSelectorComp extends Comp<CompStructure<Button>> {
DataStoreProvider.Category category;
DataStoreProvider.DataCategory category;
Property<DataStore> chosenStore;
@Override
@ -30,7 +30,7 @@ public class DataStoreSelectorComp extends Comp<CompStructure<Button>> {
var button = new JFXButton();
button.setGraphic(getGraphic());
button.setOnAction(e -> {
GuiDsStoreCreator.show("inProgress", null, null, category, entry -> {
GuiDsStoreCreator.show("inProgress", null, null, v -> v.getCategory().equals(category), entry -> {
chosenStore.setValue(entry.getStore());
});
e.consume();

View file

@ -32,7 +32,7 @@ public class DsDbStoreChooserComp extends SimpleComp {
var filter = Bindings.createObjectBinding(
() -> (Predicate<DataStoreEntry>) e -> {
if (provider.getValue() == null) {
return e.getProvider().getCategory() == DataStoreProvider.Category.DATABASE;
return e.getProvider().getCategory() == DataStoreProvider.DataCategory.DATABASE;
}
return provider.getValue().couldSupportStore(e.getStore());
@ -42,7 +42,7 @@ public class DsDbStoreChooserComp extends SimpleComp {
var connections = new TabPaneComp.Entry(
I18n.observable("savedConnections"),
"mdi2m-monitor",
NamedStoreChoiceComp.create(filter, input, DataStoreProvider.Category.DATABASE)
NamedStoreChoiceComp.create(filter, input, DataStoreProvider.DataCategory.DATABASE)
.styleClass("store-local-file-chooser"));
var pane = new TabPaneComp(new SimpleObjectProperty<>(connections), List.of(connections));

View file

@ -18,28 +18,23 @@ import lombok.AllArgsConstructor;
import lombok.experimental.FieldDefaults;
import java.util.List;
import java.util.function.Predicate;
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
@AllArgsConstructor
public class DsStoreProviderChoiceComp extends Comp<CompStructure<ComboBox<Node>>> {
DataStoreProvider.Category type;
Predicate<DataStoreProvider> filter;
Property<DataStoreProvider> provider;
private Region createDefaultNode() {
return switch (type) {
case STREAM -> JfxHelper.createNamedEntry(
I18n.get("selectStreamType"), I18n.get("selectStreamTypeDescription"), "file_icon.png");
case SHELL -> JfxHelper.createNamedEntry(
I18n.get("selectShellType"), I18n.get("selectShellTypeDescription"), "machine_icon.png");
case DATABASE -> JfxHelper.createNamedEntry(
I18n.get("selectDatabaseType"), I18n.get("selectDatabaseTypeDescription"), "db_icon.png");
};
return JfxHelper.createNamedEntry(
I18n.get("selectType"), I18n.get("selectTypeDescription"), "machine_icon.png");
}
private List<DataStoreProvider> getProviders() {
return DataStoreProviders.getAll().stream()
.filter(p -> p.getCategory() == type)
.filter(filter)
.toList();
}

View file

@ -114,14 +114,14 @@ public class DsStreamStoreChoiceComp extends SimpleComp implements Validatable {
var named = new TabPaneComp.Entry(
I18n.observable("stored"),
"mdrmz-storage",
NamedStoreChoiceComp.create(filter, namedStore, DataStoreProvider.Category.STREAM));
NamedStoreChoiceComp.create(filter, namedStore, DataStoreProvider.DataCategory.STREAM));
var otherStore = new SimpleObjectProperty<DataStore>(
localStore.get() == null && remoteStore.get() == null && !isNamedStore ? selected.getValue() : null);
var other = new TabPaneComp.Entry(
I18n.observable("other"),
"mdrmz-web_asset",
new DataStoreSelectorComp(DataStoreProvider.Category.STREAM, otherStore));
new DataStoreSelectorComp(DataStoreProvider.DataCategory.STREAM, otherStore));
var selectedTab = new SimpleObjectProperty<TabPaneComp.Entry>();
if (localStore.get() != null) {

View file

@ -37,6 +37,7 @@ import lombok.experimental.FieldDefaults;
import java.util.List;
import java.util.UUID;
import java.util.function.Consumer;
import java.util.function.Predicate;
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
public class GuiDsStoreCreator extends MultiStepComp.Step<CompStructure<?>> {
@ -44,7 +45,7 @@ public class GuiDsStoreCreator extends MultiStepComp.Step<CompStructure<?>> {
MultiStepComp parent;
Property<DataStoreProvider> provider;
Property<DataStore> input;
DataStoreProvider.Category generalType;
Predicate<DataStoreProvider> filter;
BooleanProperty busy = new SimpleBooleanProperty();
Property<Validator> validator = new SimpleObjectProperty<>(new SimpleValidator());
Property<String> messageProp = new SimpleStringProperty();
@ -58,13 +59,13 @@ public class GuiDsStoreCreator extends MultiStepComp.Step<CompStructure<?>> {
MultiStepComp parent,
Property<DataStoreProvider> provider,
Property<DataStore> input,
DataStoreProvider.Category generalType,
Predicate<DataStoreProvider> filter,
String initialName) {
super(null);
this.parent = parent;
this.provider = provider;
this.input = input;
this.generalType = generalType;
this.filter = filter;
this.name = new SimpleStringProperty(initialName);
this.input.addListener((c, o, n) -> {
changedSinceError.setValue(true);
@ -88,7 +89,7 @@ public class GuiDsStoreCreator extends MultiStepComp.Step<CompStructure<?>> {
}
public static void showEdit(DataStoreEntry e) {
show(e.getName(), e.getProvider(), e.getStore(), e.getProvider().getCategory(), newE -> {
show(e.getName(), e.getProvider(), e.getStore(), v -> true, newE -> {
ThreadHelper.runAsync(() -> {
e.applyChanges(newE);
if (!DataStorage.get().getStores().contains(e)) {
@ -99,9 +100,8 @@ public class GuiDsStoreCreator extends MultiStepComp.Step<CompStructure<?>> {
});
}
public static void showCreation(DataStoreProvider.Category cat) {
show(null, null, null, cat, e -> {
public static void showCreation(Predicate<DataStoreProvider> filter) {
show(null, null, null, filter, e -> {
try {
DataStorage.get().addStore(e);
} catch (Exception ex) {
@ -114,13 +114,11 @@ public class GuiDsStoreCreator extends MultiStepComp.Step<CompStructure<?>> {
String initialName,
DataStoreProvider provider,
DataStore s,
DataStoreProvider.Category cat,
Predicate<DataStoreProvider> filter,
Consumer<DataStoreEntry> con) {
var prop = new SimpleObjectProperty<DataStoreProvider>(provider);
var store = new SimpleObjectProperty<DataStore>(s);
var name = cat == DataStoreProvider.Category.SHELL
? "addShellTitle"
: cat == DataStoreProvider.Category.DATABASE ? "addDatabaseTitle" : "addStreamTitle";
var name = "addConnection";
Platform.runLater(() -> {
var stage = AppWindowHelper.sideWindow(
I18n.get(name),
@ -128,7 +126,7 @@ public class GuiDsStoreCreator extends MultiStepComp.Step<CompStructure<?>> {
return new MultiStepComp() {
private final GuiDsStoreCreator creator =
new GuiDsStoreCreator(this, prop, store, cat, initialName);
new GuiDsStoreCreator(this, prop, store, filter, initialName);
@Override
protected List<Entry> setup() {
@ -182,7 +180,7 @@ public class GuiDsStoreCreator extends MultiStepComp.Step<CompStructure<?>> {
@Override
public CompStructure<? extends Region> createBase() {
var layout = new BorderPane();
var providerChoice = new DsStoreProviderChoiceComp(generalType, provider);
var providerChoice = new DsStoreProviderChoiceComp(filter, provider);
providerChoice.apply(GrowAugment.create(true, false));
SimpleChangeListener.apply(provider, n -> {

View file

@ -41,7 +41,7 @@ import java.util.function.Predicate;
public class NamedStoreChoiceComp extends SimpleComp implements Validatable {
private final ObservableValue<Predicate<DataStore>> filter;
private final DataStoreProvider.Category category;
private final DataStoreProvider.DataCategory category;
private final Property<? extends DataStore> selected;
private final StringProperty filterString = new SimpleStringProperty();
@ -53,7 +53,7 @@ public class NamedStoreChoiceComp extends SimpleComp implements Validatable {
public NamedStoreChoiceComp(
ObservableValue<Predicate<DataStore>> filter,
Property<? extends DataStore> selected,
DataStoreProvider.Category category) {
DataStoreProvider.DataCategory category) {
this.filter = filter;
this.selected = selected;
this.category = category;
@ -63,7 +63,7 @@ public class NamedStoreChoiceComp extends SimpleComp implements Validatable {
public static NamedStoreChoiceComp create(
ObservableValue<Predicate<DataStoreEntry>> filter,
Property<? extends DataStore> selected,
DataStoreProvider.Category category) {
DataStoreProvider.DataCategory category) {
return new NamedStoreChoiceComp(
Bindings.createObjectBinding(
() -> {
@ -142,7 +142,7 @@ public class NamedStoreChoiceComp extends SimpleComp implements Validatable {
var text = new LabelComp(I18n.observable("noMatchingStoreFound"))
.apply(struc -> VBox.setVgrow(struc.get(), Priority.ALWAYS));
var addButton = new ButtonComp(I18n.observable("addStore"), null, () -> {
GuiDsStoreCreator.showCreation(category);
GuiDsStoreCreator.showCreation(v -> v.getCategory().equals(category));
});
var notice = new VerticalComp(List.of(text, addButton))
.apply(struc -> {

View file

@ -20,28 +20,35 @@ public class StoreCreationBarComp extends SimpleComp {
@Override
protected Region createSimple() {
var newOtherStore = new ButtonComp(
I18n.observable("addOther"), new FontIcon("mdi2c-card-plus-outline"), () -> {
GuiDsStoreCreator.showCreation(v -> v.getDisplayCategory().equals(DataStoreProvider.DisplayCategory.OTHER));
})
.shortcut(new KeyCodeCombination(KeyCode.C, KeyCombination.SHORTCUT_DOWN))
.apply(new FancyTooltipAugment<>("addOther"));
var newStreamStore = new ButtonComp(
I18n.observable("addStreamStore"), new FontIcon("mdi2c-card-plus-outline"), () -> {
GuiDsStoreCreator.showCreation(DataStoreProvider.Category.STREAM);
I18n.observable("addCommand"), new FontIcon("mdi2c-code-greater-than"), () -> {
GuiDsStoreCreator.showCreation(v -> v.getDisplayCategory().equals(DataStoreProvider.DisplayCategory.COMMAND));
})
.shortcut(new KeyCodeCombination(KeyCode.L, KeyCombination.SHORTCUT_DOWN))
.apply(new FancyTooltipAugment<>("addStreamStore"));
.shortcut(new KeyCodeCombination(KeyCode.C, KeyCombination.SHORTCUT_DOWN))
.apply(new FancyTooltipAugment<>("addCommand"));
var newShellStore = new ButtonComp(
I18n.observable("addShellStore"), new FontIcon("mdi2h-home-plus-outline"), () -> {
GuiDsStoreCreator.showCreation(DataStoreProvider.Category.SHELL);
I18n.observable("addHost"), new FontIcon("mdi2h-home-plus-outline"), () -> {
GuiDsStoreCreator.showCreation(v -> v.getDisplayCategory().equals(DataStoreProvider.DisplayCategory.HOST));
})
.shortcut(new KeyCodeCombination(KeyCode.M, KeyCombination.SHORTCUT_DOWN))
.apply(new FancyTooltipAugment<>("addShellStore"));
.shortcut(new KeyCodeCombination(KeyCode.H, KeyCombination.SHORTCUT_DOWN))
.apply(new FancyTooltipAugment<>("addHost"));
var newDbStore = new ButtonComp(
I18n.observable("addDatabaseStore"), new FontIcon("mdi2d-database-plus-outline"), () -> {
GuiDsStoreCreator.showCreation(DataStoreProvider.Category.DATABASE);
I18n.observable("addDatabase"), new FontIcon("mdi2d-database-plus-outline"), () -> {
GuiDsStoreCreator.showCreation(v -> v.getDisplayCategory().equals(DataStoreProvider.DisplayCategory.DATABASE));
})
.shortcut(new KeyCodeCombination(KeyCode.D, KeyCombination.SHORTCUT_DOWN))
.apply(new FancyTooltipAugment<>("addDatabaseStore"));
.apply(new FancyTooltipAugment<>("addDatabase"));
var box = new VerticalComp(List.of(newShellStore, newDbStore, newStreamStore));
var box = new VerticalComp(List.of(newShellStore, newDbStore, newStreamStore, newOtherStore));
box.apply(s -> AppFont.medium(s.get()));
var bar = box.createRegion();
bar.getStyleClass().add("bar");

View file

@ -254,7 +254,7 @@ public class AppExtensionManager {
extendedLayer =
ModuleLayer.defineModulesWithOneLoader(cf, extended, scl).layer();
} else {
extendedLayer = ModuleLayer.boot();
extendedLayer = baseLayer;
}
addNativeLibrariesToPath();

View file

@ -135,6 +135,15 @@ public class AppI18n implements I18n {
return key;
}
public boolean containsKey(String s) {
var key = getKey(s);
if (translations == null) {
return false;
}
return translations.containsKey(key);
}
public String getLocalised(String s, Object... vars) {
var key = getKey(s);

View file

@ -15,7 +15,7 @@ public class StoreProviderListExchangeImpl extends StoreProviderListExchange
@Override
public Response handleRequest(BeaconHandler handler, Request msg) throws Exception {
var categories = DataStoreProvider.Category.values();
var categories = DataStoreProvider.DataCategory.values();
var all = DataStoreProviders.getAll();
var map = Arrays.stream(categories)
.collect(Collectors.toMap(category -> getName(category), category -> all.stream()
@ -31,7 +31,7 @@ public class StoreProviderListExchangeImpl extends StoreProviderListExchange
return Response.builder().entries(map).build();
}
private String getName(DataStoreProvider.Category category) {
private String getName(DataStoreProvider.DataCategory category) {
return category.name().substring(0, 1).toUpperCase()
+ category.name().substring(1).toLowerCase();
}

View file

@ -1,5 +1,6 @@
package io.xpipe.app.prefs;
import com.dlsc.formsfx.model.structure.Form;
import com.dlsc.formsfx.model.util.TranslationService;
import com.dlsc.preferencesfx.PreferencesFxEvent;
import com.dlsc.preferencesfx.history.History;
@ -11,6 +12,8 @@ import com.dlsc.preferencesfx.view.*;
import javafx.beans.property.ObjectProperty;
import javafx.event.EventHandler;
import javafx.event.EventType;
import javafx.scene.control.ScrollPane;
import lombok.SneakyThrows;
import java.util.List;
@ -56,10 +59,20 @@ public class AppPreferencesFx {
public void setupControls() {
undoRedoBox = new UndoRedoBox(preferencesFxModel.getHistory());
breadCrumbView = new BreadCrumbView(preferencesFxModel, undoRedoBox);
breadCrumbView = new BreadCrumbView(preferencesFxModel, undoRedoBox) {
@Override
public void initializeParts() {
}
@Override
public void layoutParts() {
}
};
breadCrumbPresenter = new BreadCrumbPresenter(preferencesFxModel, breadCrumbView);
categoryController = new CategoryController();
categoryController.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
categoryController.setFitToWidth(true);
initializeCategoryViews();
// display initial category
@ -88,9 +101,24 @@ public class AppPreferencesFx {
*/
private void initializeCategoryViews() {
preferencesFxModel.getFlatCategoriesLst().forEach(category -> {
CategoryView categoryView = new CategoryView(preferencesFxModel, category);
var categoryView = new CustomCategoryView(preferencesFxModel, category);
CategoryPresenter categoryPresenter =
new CategoryPresenter(preferencesFxModel, category, categoryView, breadCrumbPresenter);
new CategoryPresenter(preferencesFxModel, category, categoryView, breadCrumbPresenter) {
@Override
@SneakyThrows
public void initializeViewParts() {
var formMethod = CategoryPresenter.class.getDeclaredMethod("createForm");
formMethod.setAccessible(true);
var formField = CategoryPresenter.class.getDeclaredField("form");
formField.setAccessible(true);
formField.set(this, formMethod.invoke(this));
categoryView.initializeFormRenderer((Form) formField.get(this));
this.addI18nListener();
this.addInstantPersistenceListener();
}
};
categoryController.addView(category, categoryView, categoryPresenter);
});
}

View file

@ -402,17 +402,22 @@ public class AppPrefs {
Category.of(
"system",
Group.of(
"appBehaviour",
Setting.of(
"externalStartupBehaviour",
externalStartupBehaviourControl,
externalStartupBehaviour),
Setting.of("closeBehaviour", closeBehaviourControl, closeBehaviour),
Setting.of("closeBehaviour", closeBehaviourControl, closeBehaviour)),
Group.of(
"updates",
Setting.of("automaticallyUpdate", automaticallyUpdateField, automaticallyUpdate)
.applyVisibility(VisibilityProperty.of(new SimpleBooleanProperty(
XPipeDistributionType.get().supportsUpdate()))),
Setting.of("updateToPrereleases", updateToPrereleasesField, updateToPrereleases)
.applyVisibility(VisibilityProperty.of(new SimpleBooleanProperty(
XPipeDistributionType.get().supportsUpdate()))),
XPipeDistributionType.get().supportsUpdate())))),
Group.of(
"advanced",
Setting.of("storageDirectory", storageDirectoryControl, internalStorageDirectory),
Setting.of("logLevel", logLevelField, internalLogLevel),
Setting.of("developerMode", developerModeField, internalDeveloperMode))),
@ -423,14 +428,13 @@ public class AppPrefs {
Setting.of("language", languageControl, languageInternal),
Setting.of("theme", themeControl, themeInternal),
Setting.of("useSystemFont", useSystemFontInternal),
Setting.of("tooltipDelay", tooltipDelayInternal, tooltipDelayMin, tooltipDelayMax),
Setting.of("fontSize", fontSizeInternal, fontSizeMin, fontSizeMax)),
Setting.of("tooltipDelay", tooltipDelayInternal, tooltipDelayMin, tooltipDelayMax)),
Group.of("windowOptions", Setting.of("saveWindowLocation", saveWindowLocationInternal))),
Category.of(
"integrations",
Group.of(
"editor",
Setting.of("defaultProgram", externalEditorControl, externalEditor),
Setting.of("editorProgram", externalEditorControl, externalEditor),
Setting.of("customEditorCommand", customEditorCommandControl, customEditorCommand)
.applyVisibility(VisibilityProperty.of(
externalEditor.isEqualTo(ExternalEditorType.CUSTOM))),

View file

@ -0,0 +1,19 @@
package io.xpipe.app.prefs;
import com.dlsc.formsfx.model.structure.Form;
import com.dlsc.preferencesfx.model.Category;
import com.dlsc.preferencesfx.model.PreferencesFxModel;
import com.dlsc.preferencesfx.view.CategoryView;
public class CustomCategoryView extends CategoryView {
public CustomCategoryView(PreferencesFxModel model, Category categoryModel) {
super(model, categoryModel);
}
public void initializeFormRenderer(Form form) {
getChildren().clear();
var preferencesFormRenderer = new CustomFormRenderer(form);
getChildren().add(preferencesFormRenderer);
}
}

View file

@ -0,0 +1,123 @@
package io.xpipe.app.prefs;
import com.dlsc.formsfx.model.structure.Element;
import com.dlsc.formsfx.model.structure.Field;
import com.dlsc.formsfx.model.structure.Form;
import com.dlsc.formsfx.model.structure.NodeElement;
import com.dlsc.preferencesfx.formsfx.view.controls.SimpleControl;
import com.dlsc.preferencesfx.formsfx.view.renderer.PreferencesFxFormRenderer;
import com.dlsc.preferencesfx.formsfx.view.renderer.PreferencesFxGroup;
import com.dlsc.preferencesfx.formsfx.view.renderer.PreferencesFxGroupRenderer;
import com.dlsc.preferencesfx.util.PreferencesFxUtils;
import io.xpipe.app.core.AppFont;
import io.xpipe.app.core.AppI18n;
import io.xpipe.extension.I18n;
import javafx.geometry.Insets;
import javafx.scene.control.Label;
import javafx.scene.layout.GridPane;
import java.util.List;
import java.util.stream.Collectors;
public class CustomFormRenderer extends PreferencesFxFormRenderer {
public static final double SPACING = 8.0;
public CustomFormRenderer(Form form) {
super(form);
}
@Override
public void initializeParts() {
groups = form.getGroups().stream()
.map(group -> new PreferencesFxGroupRenderer((PreferencesFxGroup) group, this) {
@Override
public void initializeParts() {
super.initializeParts();
}
@Override
@SuppressWarnings({"rawtypes", "unchecked"})
public void layoutParts() {
StringBuilder styleClass = new StringBuilder("group");
// if there are no rows yet, getRowCount returns -1, in this case the next row is 0
int nextRow = PreferencesFxUtils.getRowCount(grid) + 1;
// Only when the preferencesGroup has a title
if (preferencesGroup.getTitle() != null) {
grid.add(titleLabel, 0, nextRow++, 2, 1);
titleLabel.getStyleClass().add("group-title");
AppFont.setSize(titleLabel, 2);
// Set margin for all but first group titles to visually separate groups
if (nextRow > 1) {
GridPane.setMargin(titleLabel, new Insets(SPACING * 3, 0, 0, 0));
}
}
List<Element> elements = preferencesGroup.getElements().stream()
.map(Element.class::cast)
.toList();
styleClass.append("-setting");
int rowAmount = nextRow;
for (int i = 0; i < elements.size(); i++) {
// add to GridPane
Element element = elements.get(i);
if (element instanceof Field f) {
var label = f.getLabel();
var descriptionKey = label != null ? label + "Description" : null;
SimpleControl c = (SimpleControl) ((Field) element).getRenderer();
c.setField((Field) element);
AppFont.header(c.getFieldLabel());
c.getFieldLabel().setPrefHeight(AppFont.getPixelSize(1));
c.getFieldLabel().setMaxHeight(AppFont.getPixelSize(1));
grid.add(c.getFieldLabel(), 0, i + rowAmount, 2, 1);
var descriptionLabel = new Label();
descriptionLabel.setWrapText(true);
descriptionLabel.disableProperty().bind(c.getFieldLabel().disabledProperty());
descriptionLabel.opacityProperty().bind(c.getFieldLabel().opacityProperty());
descriptionLabel.managedProperty().bind(c.getFieldLabel().managedProperty());
descriptionLabel.visibleProperty().bind(c.getFieldLabel().visibleProperty());
descriptionLabel.setMaxHeight(USE_PREF_SIZE);
if (AppI18n.get().containsKey(descriptionKey)) {
rowAmount++;
descriptionLabel.textProperty().bind(I18n.observable(descriptionKey));
grid.add(descriptionLabel, 0, i + rowAmount, 2, 1);
}
rowAmount++;
grid.add(c.getNode(), 0, i + rowAmount, 1, 1);
if (i == elements.size() - 1) {
// additional styling for the last setting
styleClass.append("-last");
}
var offset = preferencesGroup.getTitle() != null ? 15 : 0;
GridPane.setMargin(descriptionLabel, new Insets(SPACING, 0, 0, offset));
GridPane.setMargin(c.getNode(), new Insets(SPACING, 0, 0, offset));
if (!((i == 0) && (nextRow > 0))) {
GridPane.setMargin(c.getFieldLabel(), new Insets(SPACING * 3, 0, 0, offset));
} else {
GridPane.setMargin(c.getFieldLabel(), new Insets(SPACING, 0, 0, offset));
}
c.getFieldLabel().getStyleClass().add(styleClass.toString() + "-label");
c.getNode().getStyleClass().add(styleClass.toString() + "-node");
}
if (element instanceof NodeElement nodeElement) {
grid.add(nodeElement.getNode(), 0, i + rowAmount, GridPane.REMAINING, 1);
}
}
}
})
.collect(Collectors.toList());
}
}

View file

@ -80,7 +80,7 @@ public class XPipeDaemonProvider implements XPipeDaemon {
public <T extends Comp<?> & Validatable> T namedStoreChooser(
ObservableValue<Predicate<DataStore>> filter,
Property<? extends DataStore> selected,
DataStoreProvider.Category category) {
DataStoreProvider.DataCategory category) {
return (T) new NamedStoreChoiceComp(filter, selected, category);
}

View file

@ -34,12 +34,14 @@ none=None
save=Save
clean=Clean
refresh=Refresh
addDatabaseStore=Add Database ...
addDatabaseTitle=Add Database Store
addStreamStore=Add Stream ...
addDatabase=Add Database ...
addHost=Add Host ...
addCommand=Add Command ...
addOther=Add Other ...
addStreamTitle=Add Stream Store
selectQueryType=Query Type
selectQueryTypeDescription=Select Query Type
addConnection=Add Connection
selectType=Select Type
selectTypeDescription=Select connection type
selectDatabaseType=Database Type
selectDatabaseTypeDescription=Select Type of the Database
selectShellType=Shell Type

View file

@ -2,18 +2,26 @@ appearance=Appearance
integrations=Integrations
uiOptions=UI Options
theme=Theme
defaultProgram=Default Program
editorProgram=Default Program
editorProgramDescription=The default text editor to use when editing any kind of text data.
useSystemFont=Use system font
updates=Updates
advanced=Advanced
useSystemFontDescription=In case you're using a custom font on your system, you can opt to use it instead of the default X-Pipe font.
tooltipDelay=Tooltip delay
tooltipDelayDescription=The amount of milliseconds to wait until a tooltip is displayed.
fontSize=Font size
windowOptions=Window Options
saveWindowLocation=Save window location on exit
saveWindowLocation=Save window location
saveWindowLocationDescription=Controls whether the window coordinates should be saved and restored on restarts.
startupShutdown=Startup / Shutdown
system=System
updateToPrereleases=Update to prereleases
updateToPrereleasesDescription=When enabled, the update check will also look for available prereleases in addition to full releases.
storage=Storage
runOnStartup=Run on startup
closeBehaviour=Close behaviour
closeBehaviourDescription=Controls how X-Pipe should proceed upon closing its main window.
language=Language
lightTheme=Light Theme
darkTheme=Dark Theme
@ -23,6 +31,7 @@ minimizeToTray=Minimize to tray
closeBehaviourAlertTitle=Set closing behaviour
closeBehaviourAlertTitleHeader=Select what should happen when closing the window.
externalStartupBehaviour=External startup behaviour
externalStartupBehaviourDescription=Controls the behavior of the desktop application when X-Pipe is started from for example the CLI or an API.
clearCachesAlertTitle=Clean Cache
clearCachesAlertTitleHeader=Do you want to clean all X-Pipe caches?
clearCachesAlertTitleContent=Note that this will delete all the data that is stored to improve the user experience, for example file usage histories.
@ -37,19 +46,34 @@ notAnAbsolutePath=Not an absolute path
notADirectory=Not a directory
notAnEmptyDirectory=Not an empty directory
automaticallyUpdate=Automatically update
automaticallyUpdateDescription=When enabled, new releases are automatically downloaded in the background while X-Pipe is running and installed on the next launch.
sendAnonymousErrorReports=Send anonymous error reports
sendUsageStatistics=Send anonymous usage statistics
storageDirectory=Storage directory
storageDirectoryDescription=The location where X-Pipe should store all connection and data source information.
logLevel=Log level
appBehaviour=Application behaviour
logLevelDescription=The log level that should be used when writing log files.
developerMode=Developer mode
developerModeDescription=When enabled, you will have access to a variety of additional options that are useful for development.
editor=Editor
custom=Custom
customEditorCommand=Custom editor command
customEditorCommandDescription=The command to use to open the custom editor. The placeholder string $file will be replaced by the quoted actual file name when called. If you don't specify a placeholder string, the actual filename will be appended.
editorReloadTimeout=Editor reload timeout
editorReloadTimeoutDescription=The amount of milliseconds to wait before reading a file after it has been updated. This avoids issues in cases where your editor is slow at writing or releasing file locks.
notepad++=Notepad++
notepad++Windows=Notepad++
notepad++Linux=Notepad++
notepad=Notepad
developer=Developer
developerDisableUpdateVersionCheck=Disable Update Version Check
developerDisableUpdateVersionCheckDescription=Controls whether the update checker will ignore the version number when looking for an update.
developerDisableGuiRestrictions=Disable GUI restrictions
developerDisableGuiRestrictionsDescription=Controls wether some disabled actions can still be executed from the user interface.
developerShowHiddenEntries=Show hidden entries
developerShowHiddenEntriesDescription=When enabled, hidden and internal data sources will be shown.
developerShowHiddenProviders=Show hidden providers
developerShowHiddenProvidersDescription=Controls whether hidden and internal connection and data source providers will be shown in the creation dialog.
developerDisableConnectorInstallationVersionCheck=Disable Connector Version Check
developerDisableConnectorInstallationVersionCheckDescription=Controls whether the update checker will ignore the version number when inspecting the version of an X-Pipe connector installed on a remote machine.

2
dist/changelogs/0.4.30.md vendored Normal file
View file

@ -0,0 +1,2 @@
- Improve settings menu layout
- Improve connection creation sections

View file

@ -71,8 +71,8 @@ public class InMemoryStoreProvider implements DataStoreProvider {
}
@Override
public Category getCategory() {
return Category.STREAM;
public DataCategory getCategory() {
return DataCategory.STREAM;
}
@Override

View file

@ -30,7 +30,7 @@ public class RawFileOutputTarget implements DataSourceTarget {
new SimpleObjectProperty<>(store -> store instanceof StreamDataStore
&& (store.getFlow().hasOutput())),
target,
DataStoreProvider.Category.STREAM);
DataStoreProvider.DataCategory.STREAM);
storeChoice
.apply(GrowAugment.create(true, true))
.apply(struc -> GridPane.setVgrow(struc.get(), Priority.ALWAYS));

View file

@ -26,19 +26,30 @@ public interface DataStoreProvider {
}
}
default Category getCategory() {
default DataCategory getCategory() {
var c = getStoreClasses().get(0);
if (StreamDataStore.class.isAssignableFrom(c)) {
return Category.STREAM;
return DataCategory.STREAM;
}
if (FileSystemStore.class.isAssignableFrom(c) || ShellStore.class.isAssignableFrom(c)) {
return Category.SHELL;
return DataCategory.SHELL;
}
throw new ExtensionException("Provider " + getId() + " has no set category");
}
default DisplayCategory getDisplayCategory() {
var category = getCategory();
if (category.equals(DataCategory.SHELL)) {
return DisplayCategory.HOST;
}
if (category.equals(DataCategory.DATABASE)) {
return DisplayCategory.DATABASE;
}
return DisplayCategory.OTHER;
}
default DataStore getParent(DataStore store) {
return null;
}
@ -105,9 +116,16 @@ public interface DataStoreProvider {
return true;
}
enum Category {
enum DataCategory {
STREAM,
SHELL,
DATABASE;
}
enum DisplayCategory {
HOST,
DATABASE,
COMMAND,
OTHER;
}
}

View file

@ -47,7 +47,7 @@ public interface XPipeDaemon {
<T extends Comp<?> & Validatable> T namedStoreChooser(
ObservableValue<Predicate<DataStore>> filter,
Property<? extends DataStore> selected,
DataStoreProvider.Category category);
DataStoreProvider.DataCategory category);
<T extends Comp<?> & Validatable> T namedSourceChooser(
ObservableValue<Predicate<DataSource<?>>> filter,

Binary file not shown.

View file

@ -1 +1 @@
0.4.29
0.4.30