mirror of
https://github.com/xpipe-io/xpipe.git
synced 2026-06-21 22:09:09 -04:00
Move to atlantafx
This commit is contained in:
@@ -5,6 +5,7 @@ import io.xpipe.app.util.Hyperlinks;
|
||||
import io.xpipe.extension.fxcomps.Comp;
|
||||
import io.xpipe.extension.fxcomps.CompStructure;
|
||||
import io.xpipe.extension.fxcomps.SimpleCompStructure;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.scene.layout.StackPane;
|
||||
@@ -18,6 +19,7 @@ public class ThirdPartyDependencyListComp extends Comp<CompStructure<?>> {
|
||||
link.setOnAction(e -> {
|
||||
Hyperlinks.open(t.link());
|
||||
});
|
||||
tp.setPadding(Insets.EMPTY);
|
||||
tp.setGraphic(link);
|
||||
tp.setAlignment(Pos.CENTER_LEFT);
|
||||
AppFont.medium(tp);
|
||||
@@ -49,6 +51,7 @@ public class ThirdPartyDependencyListComp extends Comp<CompStructure<?>> {
|
||||
acc.setPrefWidth(500);
|
||||
var sp = new ScrollPane(acc);
|
||||
sp.setFitToWidth(true);
|
||||
sp.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
|
||||
return new SimpleCompStructure<>(sp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import io.xpipe.extension.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;
|
||||
@@ -48,7 +49,7 @@ public class BigIconButton extends ButtonComp {
|
||||
|
||||
@Value
|
||||
@Builder
|
||||
public static class Structure implements CompStructure<JFXButton> {
|
||||
public static class Structure implements CompStructure<Button> {
|
||||
JFXButton button;
|
||||
VBox stack;
|
||||
Node graphic;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package io.xpipe.app.comp.base;
|
||||
|
||||
import com.jfoenix.controls.JFXButton;
|
||||
import io.xpipe.extension.fxcomps.Comp;
|
||||
import io.xpipe.extension.fxcomps.CompStructure;
|
||||
import io.xpipe.extension.fxcomps.SimpleCompStructure;
|
||||
@@ -11,9 +10,10 @@ import javafx.beans.value.ObservableValue;
|
||||
import javafx.css.Size;
|
||||
import javafx.css.SizeUnits;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.Button;
|
||||
import org.kordamp.ikonli.javafx.FontIcon;
|
||||
|
||||
public class ButtonComp extends Comp<CompStructure<JFXButton>> {
|
||||
public class ButtonComp extends Comp<CompStructure<Button>> {
|
||||
|
||||
private final ObservableValue<String> name;
|
||||
private final ObjectProperty<Node> graphic;
|
||||
@@ -48,14 +48,14 @@ public class ButtonComp extends Comp<CompStructure<JFXButton>> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompStructure<JFXButton> createBase() {
|
||||
var button = new JFXButton(null);
|
||||
public CompStructure<Button> createBase() {
|
||||
var button = new Button(null);
|
||||
if (name != null) {
|
||||
button.textProperty().bind(name);
|
||||
}
|
||||
var graphic = getGraphic();
|
||||
if (graphic instanceof FontIcon f) {
|
||||
f.iconColorProperty().bind(button.textFillProperty());
|
||||
//f.iconColorProperty().bind(button.textFillProperty());
|
||||
SimpleChangeListener.apply(button.fontProperty(), c -> {
|
||||
f.setIconSize((int) new Size(c.getSize(), SizeUnits.PT).pixels());
|
||||
});
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package io.xpipe.app.comp.base;
|
||||
|
||||
import com.jfoenix.controls.JFXCheckBox;
|
||||
import io.xpipe.extension.fxcomps.SimpleComp;
|
||||
import javafx.beans.property.ListProperty;
|
||||
import javafx.scene.control.CheckBox;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.ScrollPane;
|
||||
import javafx.scene.layout.Region;
|
||||
@@ -24,8 +24,9 @@ public class ListSelectorComp<T> extends SimpleComp {
|
||||
@Override
|
||||
protected Region createSimple() {
|
||||
var vbox = new VBox();
|
||||
vbox.getStyleClass().add("content");
|
||||
for (var v : values) {
|
||||
var cb = new JFXCheckBox(null);
|
||||
var cb = new CheckBox(null);
|
||||
cb.selectedProperty().addListener((c, o, n) -> {
|
||||
if (n) {
|
||||
selected.add(v);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package io.xpipe.app.comp.storage.store;
|
||||
|
||||
import io.xpipe.app.comp.base.ListViewComp;
|
||||
import io.xpipe.app.comp.base.ListBoxViewComp;
|
||||
import io.xpipe.app.comp.base.MultiContentComp;
|
||||
import io.xpipe.extension.fxcomps.Comp;
|
||||
import io.xpipe.extension.fxcomps.SimpleComp;
|
||||
@@ -20,7 +20,7 @@ public class StoreEntryListComp extends SimpleComp {
|
||||
StoreViewState.get()
|
||||
.getFilterString()
|
||||
.map(s -> (storeEntrySection -> storeEntrySection.shouldShow(s))));
|
||||
var content = new ListViewComp<>(filtered, topLevel, null, (StoreEntrySection e) -> {
|
||||
var content = new ListBoxViewComp<>(filtered, topLevel, (StoreEntrySection e) -> {
|
||||
return e.comp(true);
|
||||
});
|
||||
return content.styleClass("store-list-comp");
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
package io.xpipe.app.core;
|
||||
|
||||
import atlantafx.base.theme.NordDark;
|
||||
import atlantafx.base.theme.NordLight;
|
||||
import atlantafx.base.theme.PrimerDark;
|
||||
import atlantafx.base.theme.PrimerLight;
|
||||
import io.xpipe.app.prefs.AppPrefs;
|
||||
import io.xpipe.extension.I18n;
|
||||
import io.xpipe.extension.event.ErrorEvent;
|
||||
import io.xpipe.extension.event.TrackEvent;
|
||||
import io.xpipe.extension.prefs.PrefsChoiceValue;
|
||||
import javafx.application.Application;
|
||||
import javafx.scene.Scene;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
@@ -19,20 +24,16 @@ import java.util.*;
|
||||
|
||||
public class AppStyle {
|
||||
|
||||
private static final Map<String, String> COLOR_SCHEME_CONTENTS = new HashMap<>();
|
||||
private static final Map<Path, String> STYLESHEET_CONTENTS = new HashMap<>();
|
||||
private static final List<Scene> scenes = new ArrayList<>();
|
||||
private static String FONT_CONTENTS = "";
|
||||
|
||||
public static void init() {
|
||||
if (COLOR_SCHEME_CONTENTS.size() > 0) {
|
||||
if (STYLESHEET_CONTENTS.size() > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
TrackEvent.info("Loading stylesheets ...");
|
||||
for (var t : Theme.values()) {
|
||||
loadTheme(t);
|
||||
}
|
||||
loadStylesheets();
|
||||
|
||||
if (AppPrefs.get() != null) {
|
||||
@@ -45,25 +46,6 @@ public class AppStyle {
|
||||
}
|
||||
}
|
||||
|
||||
private static void loadTheme(Theme theme) {
|
||||
for (var module : AppExtensionManager.getInstance().getContentModules()) {
|
||||
AppResources.with(module.getName(), "theme", path -> {
|
||||
var file = path.resolve(theme.getId() + ".css");
|
||||
if (!Files.exists(file)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
var bytes = Files.readAllBytes(file);
|
||||
var s = "data:text/css;base64," + Base64.getEncoder().encodeToString(bytes);
|
||||
COLOR_SCHEME_CONTENTS.put(theme.getId(), s);
|
||||
} catch (IOException ex) {
|
||||
ErrorEvent.fromThrowable(ex).omitted(true).build().handle();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private static void loadStylesheets() {
|
||||
AppResources.with(AppResources.XPIPE_MODULE, "font-config/font.css", path -> {
|
||||
var bytes = Files.readAllBytes(path);
|
||||
@@ -99,8 +81,7 @@ public class AppStyle {
|
||||
|
||||
private static void changeTheme(Theme oldTheme, Theme newTheme) {
|
||||
scenes.forEach(scene -> {
|
||||
scene.getStylesheets().remove(COLOR_SCHEME_CONTENTS.get(oldTheme.getId()));
|
||||
scene.getStylesheets().add(COLOR_SCHEME_CONTENTS.get(newTheme.getId()));
|
||||
Application.setUserAgentStylesheet(newTheme.getTheme().getUserAgentStylesheet());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -117,7 +98,6 @@ public class AppStyle {
|
||||
}
|
||||
|
||||
public static void reloadStylesheets(Scene scene) {
|
||||
COLOR_SCHEME_CONTENTS.clear();
|
||||
STYLESHEET_CONTENTS.clear();
|
||||
FONT_CONTENTS = "";
|
||||
|
||||
@@ -128,7 +108,7 @@ public class AppStyle {
|
||||
|
||||
public static void addStylesheets(Scene scene) {
|
||||
var t = AppPrefs.get() != null ? AppPrefs.get().theme.getValue() : Theme.LIGHT;
|
||||
scene.getStylesheets().add(COLOR_SCHEME_CONTENTS.get(t.getId()));
|
||||
Application.setUserAgentStylesheet(t.getTheme().getUserAgentStylesheet());
|
||||
TrackEvent.debug("Set theme " + t.getId() + " for scene");
|
||||
|
||||
if (AppPrefs.get() != null && !AppPrefs.get().useSystemFont.get()) {
|
||||
@@ -146,10 +126,14 @@ public class AppStyle {
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum Theme implements PrefsChoiceValue {
|
||||
LIGHT("light");
|
||||
LIGHT("light", new PrimerLight()),
|
||||
DARK("dark", new PrimerDark()),
|
||||
NORD_LIGHT("nordLight", new NordLight()),
|
||||
NORD_DARK("nordDark", new NordDark());
|
||||
// DARK("dark");
|
||||
|
||||
private final String id;
|
||||
private final atlantafx.base.theme.Theme theme;
|
||||
|
||||
@Override
|
||||
public String toTranslatedString() {
|
||||
|
||||
@@ -23,6 +23,9 @@ import org.kordamp.ikonli.javafx.FontIcon;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import static atlantafx.base.theme.Styles.ACCENT;
|
||||
import static atlantafx.base.theme.Styles.BUTTON_OUTLINED;
|
||||
|
||||
public class ErrorHandlerComp extends SimpleComp {
|
||||
|
||||
private static final AtomicBoolean showing = new AtomicBoolean(false);
|
||||
@@ -98,6 +101,7 @@ public class ErrorHandlerComp extends SimpleComp {
|
||||
var ac = createActionComp(action);
|
||||
actionBox.getChildren().add(ac);
|
||||
}
|
||||
actionBox.getChildren().get(1).getStyleClass().addAll(BUTTON_OUTLINED, ACCENT);
|
||||
|
||||
content.getChildren().addAll(actionBox, new Separator(Orientation.HORIZONTAL));
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import javafx.beans.property.SimpleListProperty;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.beans.property.StringProperty;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.control.Hyperlink;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.TextArea;
|
||||
@@ -25,6 +26,9 @@ import javafx.stage.Stage;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
import static atlantafx.base.theme.Styles.ACCENT;
|
||||
import static atlantafx.base.theme.Styles.BUTTON_OUTLINED;
|
||||
|
||||
public class UserReportComp extends SimpleComp {
|
||||
|
||||
private final StringProperty text = new SimpleStringProperty();
|
||||
@@ -45,13 +49,16 @@ public class UserReportComp extends SimpleComp {
|
||||
}
|
||||
|
||||
private Comp<?> createAttachments() {
|
||||
var list = new ListSelectorComp<>(event.getAttachments(), file -> {
|
||||
if (file.equals(AppLogs.get().getSessionLogsDirectory())) {
|
||||
return I18n.get("logFilesAttachment");
|
||||
}
|
||||
var list = new ListSelectorComp<>(
|
||||
event.getAttachments(),
|
||||
file -> {
|
||||
if (file.equals(AppLogs.get().getSessionLogsDirectory())) {
|
||||
return I18n.get("logFilesAttachment");
|
||||
}
|
||||
|
||||
return file.getFileName().toString();
|
||||
}, includedDiagnostics)
|
||||
return file.getFileName().toString();
|
||||
},
|
||||
includedDiagnostics)
|
||||
.styleClass("attachment-list");
|
||||
var tp = new TitledPaneComp(I18n.observable("additionalErrorAttachments"), list, 100)
|
||||
.apply(struc -> struc.get().setExpanded(true))
|
||||
@@ -93,9 +100,12 @@ public class UserReportComp extends SimpleComp {
|
||||
dataPolicyButton.setOnAction(event1 -> {
|
||||
Hyperlinks.open(Hyperlinks.DOCS_PRIVACY);
|
||||
});
|
||||
var sendButton = new ButtonComp(I18n.observable("sendReport"), null, this::send).createRegion();
|
||||
var sendButton = new ButtonComp(I18n.observable("sendReport"), null, this::send)
|
||||
.apply(struc -> struc.get().getStyleClass().addAll(BUTTON_OUTLINED, ACCENT))
|
||||
.createRegion();
|
||||
var spacer = new Region();
|
||||
var buttons = new HBox(dataPolicyButton, spacer, sendButton);
|
||||
buttons.setAlignment(Pos.CENTER);
|
||||
buttons.getStyleClass().add("buttons");
|
||||
HBox.setHgrow(spacer, Priority.ALWAYS);
|
||||
AppFont.medium(dataPolicyButton);
|
||||
|
||||
@@ -3,7 +3,6 @@ package io.xpipe.app.prefs;
|
||||
import com.dlsc.formsfx.model.structure.*;
|
||||
import com.dlsc.preferencesfx.formsfx.view.controls.SimpleComboBoxControl;
|
||||
import com.dlsc.preferencesfx.formsfx.view.controls.SimpleTextControl;
|
||||
import com.dlsc.preferencesfx.formsfx.view.controls.ToggleControl;
|
||||
import com.dlsc.preferencesfx.model.Category;
|
||||
import com.dlsc.preferencesfx.model.Group;
|
||||
import com.dlsc.preferencesfx.model.Setting;
|
||||
@@ -139,10 +138,10 @@ public class AppPrefs {
|
||||
private final BooleanProperty automaticallyUpdate =
|
||||
typed(new SimpleBooleanProperty(XPipeDistributionType.get().supportsUpdate()), Boolean.class);
|
||||
private final BooleanField automaticallyUpdateField =
|
||||
BooleanField.ofBooleanType(automaticallyUpdate).render(() -> new ToggleControl());
|
||||
BooleanField.ofBooleanType(automaticallyUpdate).render(() -> new CustomToggleControl());
|
||||
private final BooleanProperty updateToPrereleases = typed(new SimpleBooleanProperty(false), Boolean.class);
|
||||
private final BooleanField updateToPrereleasesField =
|
||||
BooleanField.ofBooleanType(updateToPrereleases).render(() -> new ToggleControl());
|
||||
BooleanField.ofBooleanType(updateToPrereleases).render(() -> new CustomToggleControl());
|
||||
|
||||
private final BooleanProperty confirmDeletions = typed(new SimpleBooleanProperty(true), Boolean.class);
|
||||
|
||||
@@ -179,31 +178,31 @@ public class AppPrefs {
|
||||
: internalDeveloperMode;
|
||||
private final BooleanField developerModeField = Field.ofBooleanType(effectiveDeveloperMode)
|
||||
.editable(System.getProperty(DEVELOPER_MODE_PROP) == null)
|
||||
.render(() -> new ToggleControl());
|
||||
.render(() -> new CustomToggleControl());
|
||||
|
||||
private final BooleanProperty developerDisableUpdateVersionCheck =
|
||||
typed(new SimpleBooleanProperty(false), Boolean.class);
|
||||
private final BooleanField developerDisableUpdateVersionCheckField =
|
||||
BooleanField.ofBooleanType(developerDisableUpdateVersionCheck).render(() -> new ToggleControl());
|
||||
BooleanField.ofBooleanType(developerDisableUpdateVersionCheck).render(() -> new CustomToggleControl());
|
||||
|
||||
private final BooleanProperty developerDisableGuiRestrictions =
|
||||
typed(new SimpleBooleanProperty(false), Boolean.class);
|
||||
private final BooleanField developerDisableGuiRestrictionsField =
|
||||
BooleanField.ofBooleanType(developerDisableGuiRestrictions).render(() -> new ToggleControl());
|
||||
BooleanField.ofBooleanType(developerDisableGuiRestrictions).render(() -> new CustomToggleControl());
|
||||
|
||||
private final BooleanProperty developerShowHiddenProviders = typed(new SimpleBooleanProperty(false), Boolean.class);
|
||||
private final BooleanField developerShowHiddenProvidersField =
|
||||
BooleanField.ofBooleanType(developerShowHiddenProviders).render(() -> new ToggleControl());
|
||||
BooleanField.ofBooleanType(developerShowHiddenProviders).render(() -> new CustomToggleControl());
|
||||
|
||||
private final BooleanProperty developerShowHiddenEntries = typed(new SimpleBooleanProperty(false), Boolean.class);
|
||||
private final BooleanField developerShowHiddenEntriesField =
|
||||
BooleanField.ofBooleanType(developerShowHiddenEntries).render(() -> new ToggleControl());
|
||||
BooleanField.ofBooleanType(developerShowHiddenEntries).render(() -> new CustomToggleControl());
|
||||
|
||||
private final BooleanProperty developerDisableConnectorInstallationVersionCheck =
|
||||
typed(new SimpleBooleanProperty(false), Boolean.class);
|
||||
private final BooleanField developerDisableConnectorInstallationVersionCheckField = BooleanField.ofBooleanType(
|
||||
developerDisableConnectorInstallationVersionCheck)
|
||||
.render(() -> new ToggleControl());
|
||||
.render(() -> new CustomToggleControl());
|
||||
|
||||
public ReadOnlyProperty<CloseBehaviour> closeBehaviour() {
|
||||
return closeBehaviour;
|
||||
|
||||
@@ -52,7 +52,9 @@ public class CustomFormRenderer extends PreferencesFxFormRenderer {
|
||||
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));
|
||||
GridPane.setMargin(titleLabel, new Insets(SPACING * 3, 0, SPACING, 0));
|
||||
} else {
|
||||
GridPane.setMargin(titleLabel, new Insets(SPACING, 0, SPACING, 0));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +81,7 @@ public class CustomFormRenderer extends PreferencesFxFormRenderer {
|
||||
var descriptionLabel = new Label();
|
||||
descriptionLabel.setWrapText(true);
|
||||
descriptionLabel.disableProperty().bind(c.getFieldLabel().disabledProperty());
|
||||
descriptionLabel.opacityProperty().bind(c.getFieldLabel().opacityProperty());
|
||||
descriptionLabel.opacityProperty().bind(c.getFieldLabel().opacityProperty().multiply(0.8));
|
||||
descriptionLabel.managedProperty().bind(c.getFieldLabel().managedProperty());
|
||||
descriptionLabel.visibleProperty().bind(c.getFieldLabel().visibleProperty());
|
||||
descriptionLabel.setMaxHeight(USE_PREF_SIZE);
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
package io.xpipe.app.prefs;
|
||||
|
||||
import atlantafx.base.controls.ToggleSwitch;
|
||||
import com.dlsc.formsfx.model.structure.BooleanField;
|
||||
import com.dlsc.preferencesfx.formsfx.view.controls.SimpleControl;
|
||||
import com.dlsc.preferencesfx.formsfx.view.controls.ToggleControl;
|
||||
import com.dlsc.preferencesfx.util.VisibilityProperty;
|
||||
import javafx.scene.control.Label;
|
||||
|
||||
/**
|
||||
* Displays a control for boolean values with a toggle from ControlsFX.
|
||||
*
|
||||
* @author François Martin
|
||||
* @author Marco Sanfratello
|
||||
*/
|
||||
public class CustomToggleControl extends SimpleControl<BooleanField, ToggleSwitch> {
|
||||
|
||||
/**
|
||||
* Constructs a ToggleControl of {@link ToggleControl} type, with visibility condition.
|
||||
*
|
||||
* @param visibilityProperty property for control visibility of this element
|
||||
*
|
||||
* @return the constructed ToggleControl
|
||||
*/
|
||||
public static ToggleControl of(VisibilityProperty visibilityProperty) {
|
||||
ToggleControl toggleControl = new ToggleControl();
|
||||
|
||||
toggleControl.setVisibilityProperty(visibilityProperty);
|
||||
|
||||
return toggleControl;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void initializeParts() {
|
||||
super.initializeParts();
|
||||
fieldLabel = new Label(field.labelProperty().getValue());
|
||||
node = new atlantafx.base.controls.ToggleSwitch();
|
||||
node.getStyleClass().add("toggle-control");
|
||||
node.setSelected(field.getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void layoutParts() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setupBindings() {
|
||||
super.setupBindings();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setupValueChangedListeners() {
|
||||
super.setupValueChangedListeners();
|
||||
field.userInputProperty().addListener((observable, oldValue, newValue) -> {
|
||||
node.setSelected(Boolean.parseBoolean(field.getUserInput()));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setupEventHandlers() {
|
||||
node.selectedProperty().addListener((observable, oldValue, newValue) -> {
|
||||
field.userInputProperty().setValue(String.valueOf(newValue));
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -36,6 +36,7 @@ open module io.xpipe.app {
|
||||
requires com.sun.jna;
|
||||
requires com.sun.jna.platform;
|
||||
requires org.slf4j;
|
||||
requires atlantafx.base;
|
||||
requires org.ocpsoft.prettytime;
|
||||
requires com.dlsc.preferencesfx;
|
||||
requires com.vladsch.flexmark;
|
||||
|
||||
Reference in New Issue
Block a user