Code refactoring and bugfixes (#13)

* Popover: fixed a bug that a node value was not being set
* PlatformUtils: fixed a bug that MacOS can be an OS with name darwin
* Optimized switch statements
* Code formatting and cleanup
* Removed unused imports
* Reformat markdown tables
* Use try-with-resources
* Improve Javadoc
* Enforce Git compliance
* Better NPE error messages
* Fixed spelling errors
This commit is contained in:
CodeDead 2022-10-05 07:05:18 +02:00 committed by GitHub
parent 4261e5be1d
commit aa294eb773
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
64 changed files with 341 additions and 231 deletions

@ -55,7 +55,7 @@ Check the [docs](https://mkpaz.github.io/atlantafx/) for more information.
* SASS
JavaFX standard themes, namely Modena and Caspian, maintained as a huge single CSS file, which is an overwhelmingly hard task. This alone makes creating a new JavaFX theme from scratch hardly possible. Also, JavaFX styling is based on CSS v2.1 specification which does not provide, nor variables, nor mixins, nor modules nor any other goodies that are default for modern front-end development. AtlantaFX themes are written in SASS with each component in a separate module and use recent [Dart SASS](https://sass-lang.com/dart-sass) implementation for CSS compilation. It also follows [Github Primer](https://primer.style/design/foundations/color) color system to make creating new themes more simple.
JavaFX standard themes, namely Modena and Caspian, maintained as a huge single CSS file, which is an overwhelmingly hard task. This alone makes creating a new JavaFX theme from scratch hardly possible. Also, JavaFX styling is based on CSS v2.1 specification which does not provide, nor variables, nor mixins, nor modules nor any other goodies that are default for modern front-end development. AtlantaFX themes are written in SASS with each component in a separate module and use recent [Dart SASS](https://sass-lang.com/dart-sass) implementation for CSS compilation. It also follows [GitHub Primer](https://primer.style/design/foundations/color) color system to make creating new themes more simple.
* Additional controls

@ -120,7 +120,7 @@ public class BreadcrumbsSkin<T> extends SkinBase<Breadcrumbs<T>> {
if (i > 0) {
// we have to position the bread crumbs slightly overlapping
double ins = n instanceof Breadcrumbs.BreadCrumbButton ? ((Breadcrumbs.BreadCrumbButton) n).getArrowWidth() : 0;
double ins = n instanceof Breadcrumbs.BreadCrumbButton d ? d.getArrowWidth() : 0;
x = snapPositionX(x - ins);
}

@ -238,7 +238,7 @@ public class InlineDatePickerSkin extends BehaviorSkinBase<InlineDatePicker, Inl
backButton = new Button();
backButton.getStyleClass().addAll("back-button");
backButton.setOnMouseClicked(e -> behavior.moveBackward(e));
backButton.setOnMouseClicked(behavior::moveBackward);
StackPane leftArrow = new StackPane();
leftArrow.getStyleClass().add("left-arrow");
@ -256,7 +256,7 @@ public class InlineDatePickerSkin extends BehaviorSkinBase<InlineDatePicker, Inl
forwardButton = new Button();
forwardButton.getStyleClass().addAll("forward-button");
forwardButton.setOnMouseClicked(e -> behavior.moveForward(e));
forwardButton.setOnMouseClicked(behavior::moveForward);
StackPane rightArrow = new StackPane();
rightArrow.getStyleClass().add("right-arrow");
@ -564,8 +564,8 @@ public class InlineDatePickerSkin extends BehaviorSkinBase<InlineDatePicker, Inl
public void rememberFocusedDayCell() {
Node node = getControl().getScene().getFocusOwner();
if (node instanceof DateCell) {
lastFocusedDayCell = (DateCell) node;
if (node instanceof DateCell dc) {
lastFocusedDayCell = dc;
}
}

@ -79,7 +79,9 @@ public class Popover extends PopupControl {
private final ObjectProperty<Duration> fadeInDuration = new SimpleObjectProperty<>(DEFAULT_FADE_DURATION);
private final ObjectProperty<Duration> fadeOutDuration = new SimpleObjectProperty<>(DEFAULT_FADE_DURATION);
/** Creates a popover with a label as the content node. */
/**
* Creates a popover with a label as the content node.
*/
public Popover() {
super();
@ -134,7 +136,7 @@ public class Popover extends PopupControl {
/**
* The root pane stores the content node of the popover. It is accessible
* via this method in order to support proper styling.
*
* <p>
* Example:
*
* <pre>
@ -151,7 +153,10 @@ public class Popover extends PopupControl {
private final ObjectProperty<Node> contentNode = new SimpleObjectProperty<>(this, "contentNode") {
@Override
public void setValue(Node node) {
if (node == null) { throw new IllegalArgumentException("content node can not be null"); }
if (node == null) {
throw new NullPointerException("Node cannot be null!");
}
this.set(node);
}
};
@ -168,7 +173,6 @@ public class Popover extends PopupControl {
* Returns the value of the content property
*
* @return the content node
*
* @see #contentNodeProperty()
*/
public final Node getContentNode() {
@ -179,7 +183,6 @@ public class Popover extends PopupControl {
* Sets the value of the content property.
*
* @param content the new content node value
*
* @see #contentNodeProperty()
*/
public final void setContentNode(Node content) {
@ -262,7 +265,9 @@ public class Popover extends PopupControl {
}
}
/** {@inheritDoc} */
/**
* {@inheritDoc}
*/
@Override
public final void show(Window owner) {
super.show(owner);
@ -275,7 +280,9 @@ public class Popover extends PopupControl {
ownerWindow.addEventFilter(WindowEvent.WINDOW_HIDING, closePopoverOnOwnerWindowClose);
}
/** {@inheritDoc} */
/**
* {@inheritDoc}
*/
@Override
public final void show(Window ownerWindow, double anchorX, double anchorY) {
super.show(ownerWindow, anchorX, anchorY);
@ -326,7 +333,7 @@ public class Popover extends PopupControl {
targetY = y;
if (owner == null) {
throw new IllegalArgumentException("owner can not be null");
throw new NullPointerException("Owner Node cannot be null!");
}
// this is all needed because children windows do not get their x and y
@ -348,8 +355,8 @@ public class Popover extends PopupControl {
// the user clicked somewhere into the transparent background,
// if this is the case then hide the window (when attached)
getScene().addEventHandler(MOUSE_CLICKED, mouseEvent -> {
if (mouseEvent.getTarget().equals(getScene().getRoot())) {
if (!isDetached()) { hide(); }
if (mouseEvent.getTarget().equals(getScene().getRoot()) && !isDetached()) {
hide();
}
});
@ -519,7 +526,6 @@ public class Popover extends PopupControl {
* Sets the value of the headerAlwaysVisible property.
*
* @param visible if true, then the header is visible even while attached
*
* @see #headerAlwaysVisibleProperty()
*/
public final void setHeaderAlwaysVisible(boolean visible) {
@ -530,7 +536,6 @@ public class Popover extends PopupControl {
* Returns the value of the detachable property.
*
* @return true if the header is visible even while attached
*
* @see #headerAlwaysVisibleProperty()
*/
public final boolean isHeaderAlwaysVisible() {
@ -550,7 +555,6 @@ public class Popover extends PopupControl {
* Sets the value of the closeButtonEnabled property.
*
* @param enabled if false, the popover will not be closeable by the header's close button
*
* @see #closeButtonEnabledProperty()
*/
public final void setCloseButtonEnabled(boolean enabled) {
@ -561,7 +565,6 @@ public class Popover extends PopupControl {
* Returns the value of the closeButtonEnabled property.
*
* @return true if the header's close button is enabled
*
* @see #closeButtonEnabledProperty()
*/
public final boolean isCloseButtonEnabled() {
@ -581,7 +584,6 @@ public class Popover extends PopupControl {
* Sets the value of the detachable property.
*
* @param detachable if true then the user can detach / tear off the popover
*
* @see #detachableProperty()
*/
public final void setDetachable(boolean detachable) {
@ -592,7 +594,6 @@ public class Popover extends PopupControl {
* Returns the value of the detachable property.
*
* @return true if the user is allowed to detach / tear off the popover
*
* @see #detachableProperty()
*/
public final boolean isDetachable() {
@ -617,7 +618,6 @@ public class Popover extends PopupControl {
*
* @param detached if true the popover will change its appearance to "detached"
* mode
*
* @see #detachedProperty()
*/
public final void setDetached(boolean detached) {
@ -628,7 +628,6 @@ public class Popover extends PopupControl {
* Returns the value of the detached property.
*
* @return true if the popover is currently detached.
*
* @see #detachedProperty()
*/
public final boolean isDetached() {
@ -650,7 +649,6 @@ public class Popover extends PopupControl {
* Returns the value of the arrow size property.
*
* @return the arrow size property value
*
* @see #arrowSizeProperty()
*/
public final double getArrowSize() {
@ -661,7 +659,6 @@ public class Popover extends PopupControl {
* Sets the value of the arrow size property.
*
* @param size the new value of the arrow size property
*
* @see #arrowSizeProperty()
*/
public final void setArrowSize(double size) {
@ -684,7 +681,6 @@ public class Popover extends PopupControl {
* Returns the value of the arrow indent property.
*
* @return the arrow indent value
*
* @see #arrowIndentProperty()
*/
public final double getArrowIndent() {
@ -695,7 +691,6 @@ public class Popover extends PopupControl {
* Sets the value of the arrow indent property.
*
* @param size the arrow indent value
*
* @see #arrowIndentProperty()
*/
public final void setArrowIndent(double size) {
@ -717,7 +712,6 @@ public class Popover extends PopupControl {
* Returns the value of the corner radius property.
*
* @return the corner radius
*
* @see #cornerRadiusProperty()
*/
public final double getCornerRadius() {
@ -728,7 +722,6 @@ public class Popover extends PopupControl {
* Sets the value of the corner radius property.
*
* @param radius the corner radius
*
* @see #cornerRadiusProperty()
*/
public final void setCornerRadius(double radius) {
@ -750,7 +743,6 @@ public class Popover extends PopupControl {
* Returns the value of the title property.
*
* @return the detached title
*
* @see #titleProperty()
*/
public final String getTitle() {
@ -761,12 +753,11 @@ public class Popover extends PopupControl {
* Sets the value of the title property.
*
* @param title the title to use when detached
*
* @see #titleProperty()
*/
public final void setTitle(String title) {
if (title == null) {
throw new IllegalArgumentException("title can not be null");
throw new NullPointerException("Title cannot be null!");
}
titleProperty().set(title);
}
@ -778,7 +769,6 @@ public class Popover extends PopupControl {
* location of the arrow if auto fix is enabled.
*
* @return the arrow location property
*
* @see #setAutoFix(boolean)
*/
public final ObjectProperty<ArrowLocation> arrowLocationProperty() {
@ -789,7 +779,6 @@ public class Popover extends PopupControl {
* Sets the value of the arrow location property.
*
* @param location the requested location
*
* @see #arrowLocationProperty()
*/
public final void setArrowLocation(ArrowLocation location) {
@ -800,14 +789,15 @@ public class Popover extends PopupControl {
* Returns the value of the arrow location property.
*
* @return the preferred arrow location
*
* @see #arrowLocationProperty()
*/
public final ArrowLocation getArrowLocation() {
return arrowLocationProperty().get();
}
/** All possible arrow locations */
/**
* All possible arrow locations
*/
public enum ArrowLocation {
LEFT_TOP,
LEFT_CENTER,
@ -845,7 +835,6 @@ public class Popover extends PopupControl {
* Returns the value of the fade-in duration property.
*
* @return the fade-in duration
*
* @see #fadeInDurationProperty()
*/
public final Duration getFadeInDuration() {
@ -857,7 +846,6 @@ public class Popover extends PopupControl {
* Popover.show(..).
*
* @param duration the requested fade-in duration
*
* @see #fadeInDurationProperty()
*/
public final void setFadeInDuration(Duration duration) {
@ -868,7 +856,6 @@ public class Popover extends PopupControl {
* Returns the value of the fade-out duration property.
*
* @return the fade-out duration
*
* @see #fadeOutDurationProperty()
*/
public final Duration getFadeOutDuration() {
@ -879,7 +866,6 @@ public class Popover extends PopupControl {
* Sets the value of the fade-out duration property.
*
* @param duration the requested fade-out duration
*
* @see #fadeOutDurationProperty()
*/
public final void setFadeOutDuration(Duration duration) {
@ -900,7 +886,6 @@ public class Popover extends PopupControl {
* Returns the value of the "animated" property.
*
* @return true if the Popover will be shown and hidden with a short fade animation
*
* @see #animatedProperty()
*/
public final boolean isAnimated() {
@ -911,7 +896,6 @@ public class Popover extends PopupControl {
* Sets the value of the "animated" property.
*
* @param animated if true the Popover will be shown and hidden with a short fade animation
*
* @see #animatedProperty()
*/
public final void setAnimated(boolean animated) {

@ -31,17 +31,18 @@ public class ProgressSliderSkin extends SliderSkin {
protected void layoutChildren(double x, double y, double w, double h) {
super.layoutChildren(x, y, w, h);
double progressX, progressY, progressWidth, progressHeight;
double progressX = track.getLayoutX();
double progressY;
double progressWidth;
double progressHeight;
// intentionally ignore background radius in calculation,
// because slider looks better this way
if (getSkinnable().getOrientation() == Orientation.HORIZONTAL) {
progressX = track.getLayoutX();
progressY = track.getLayoutY();
progressWidth = thumb.getLayoutX() - snappedLeftInset();
progressHeight = track.getHeight();
} else {
progressX = track.getLayoutX();
progressY = thumb.getLayoutY();
progressWidth = track.getWidth();
progressHeight = track.getLayoutBounds().getMaxY() + track.getLayoutY() - thumb.getLayoutY() - snappedBottomInset();

@ -3,7 +3,12 @@ package atlantafx.base.theme;
public final class NordDark implements Theme {
public NordDark() { }
/**
* Initialize a new NordDark
*/
public NordDark() {
// Default constructor
}
@Override
public String getName() {

@ -3,7 +3,12 @@ package atlantafx.base.theme;
public final class NordLight implements Theme {
public NordLight() { }
/**
* Initialize a new NordLight
*/
public NordLight() {
// Default constructor
}
@Override
public String getName() {

@ -3,7 +3,12 @@ package atlantafx.base.theme;
public final class PrimerDark implements Theme {
public PrimerDark() { }
/**
* Initialize a new PrimerDark
*/
public PrimerDark() {
// Default constructor
}
@Override
public String getName() {

@ -3,7 +3,12 @@ package atlantafx.base.theme;
public final class PrimerLight implements Theme {
public PrimerLight() { }
/**
* Initialize a new PrimerLight
*/
public PrimerLight() {
// Default constructor
}
@Override
public String getName() {

@ -4,8 +4,6 @@ package atlantafx.base.theme;
import javafx.css.PseudoClass;
import javafx.scene.Node;
import java.util.Objects;
@SuppressWarnings("unused")
public final class Styles {
@ -77,11 +75,20 @@ public final class Styles {
public static final String TEXT_UNDERLINED = "text-underlined";
public static final String TEXT_MUTED = "text-muted";
/**
* Initialize a new Styles
*/
private Styles() {
// Default constructor
}
// @formatter:on
public static void toggleStyleClass(Node node, String styleClass) {
Objects.requireNonNull(node);
Objects.requireNonNull(styleClass);
if (node == null)
throw new NullPointerException("Node cannot be null!");
if (styleClass == null)
throw new NullPointerException("Style class cannot be null!");
int idx = node.getStyleClass().indexOf(styleClass);
if (idx > 0) {
@ -92,8 +99,10 @@ public final class Styles {
}
public static void addStyleClass(Node node, String styleClass, String... excludes) {
Objects.requireNonNull(node);
Objects.requireNonNull(styleClass);
if (node == null)
throw new NullPointerException("Node cannot be null!");
if (styleClass == null)
throw new NullPointerException("Style class cannot be null!");
if (excludes != null && excludes.length > 0) {
node.getStyleClass().removeAll(excludes);
@ -102,8 +111,10 @@ public final class Styles {
}
public static void activatePseudoClass(Node node, PseudoClass pseudoClass, PseudoClass... excludes) {
Objects.requireNonNull(node);
Objects.requireNonNull(pseudoClass);
if (node == null)
throw new NullPointerException("Node cannot be null!");
if (pseudoClass == null)
throw new NullPointerException("PseudoClass cannot be null!");
if (excludes != null && excludes.length > 0) {
for (PseudoClass exclude : excludes) {

@ -1,8 +1,6 @@
/* SPDX-License-Identifier: MIT */
package atlantafx.base.theme;
import java.util.Objects;
import static javafx.application.Application.STYLESHEET_CASPIAN;
import static javafx.application.Application.STYLESHEET_MODENA;
@ -17,9 +15,11 @@ public interface Theme {
boolean isDarkMode();
static Theme of(String name, String userAgentStylesheet, boolean darkMode) {
Objects.requireNonNull(name);
Objects.requireNonNull(userAgentStylesheet);
static Theme of(final String name, final String userAgentStylesheet, final boolean darkMode) {
if (name == null)
throw new NullPointerException("Name cannot be null!");
if (userAgentStylesheet == null)
throw new NullPointerException("User agent stylesheet cannot be null!");
return new Theme() {

@ -7,17 +7,32 @@ package atlantafx.base.theme;
*/
public final class Tweaks {
/** Removes or hides dropdown arrow button */
/**
* Initialize a new Tweaks
*/
private Tweaks() {
// Default constructor
}
/**
* Removes or hides dropdown arrow button
*/
public static final String NO_ARROW = "no-arrow";
/** Removes external control borders */
/**
* Removes external control borders
*/
public static final String EDGE_TO_EDGE = "edge-to-edge";
/** Alignment */
/**
* Alignment
*/
public static final String ALIGN_LEFT = "align-left";
public static final String ALIGN_CENTER = "align-center";
public static final String ALIGN_RIGHT = "align-right";
/** Forces a control to use alternative icon, if available */
/**
* Forces a control to use alternative icon, if available
*/
public static final String ALT_ICON = "alt-icon";
}

@ -26,15 +26,17 @@ import java.text.DecimalFormat;
*/
public class DoubleStringConverter extends StringConverter<Double> {
private final DecimalFormat _format = new DecimalFormat("0.##");
private Runnable _reset;
private final DecimalFormat decimalFormat = new DecimalFormat("0.##");
private Runnable reset;
/**
* Creates a {@link DoubleStringConverter}.
* Swallows {@link NumberFormatException} but does nothing
* in response until {@link #setReset} is defined.
*/
public DoubleStringConverter() { }
public DoubleStringConverter() {
// Default constructor
}
/**
* Creates a {@link DoubleStringConverter} with an editor reset callback.
@ -43,7 +45,7 @@ public class DoubleStringConverter extends StringConverter<Double> {
* @param reset the {@link Runnable} to call upon {@link NumberFormatException}
*/
public DoubleStringConverter(Runnable reset) {
_reset = reset;
this.reset = reset;
}
/**
@ -59,10 +61,12 @@ public class DoubleStringConverter extends StringConverter<Double> {
* @throws NullPointerException if {@code input} is {@code null}
*/
public DoubleStringConverter(TextField input, double min, double max) {
if (input == null) { throw new NullPointerException("input"); }
if (input == null) {
throw new NullPointerException("Input cannot be null!");
}
final double resetValue = Math.min(Math.max(0, min), max);
_reset = () -> input.setText(_format.format(resetValue));
reset = () -> input.setText(decimalFormat.format(resetValue));
// bound JavaFX properties cannot be explicitly set
// if (!input.tooltipProperty().isBound()) {
@ -71,11 +75,15 @@ public class DoubleStringConverter extends StringConverter<Double> {
// restrict direct input to valid numerical characters
input.textProperty().addListener((ov, oldValue, newValue) -> {
if (newValue == null || newValue.isEmpty()) { return; }
if (newValue == null || newValue.isEmpty()) {
return;
}
// special case: minus sign if negative values allowed
if (min < 0 && newValue.endsWith("-")) {
if (newValue.length() > 1) { Platform.runLater(() -> input.setText("-")); }
if (newValue.length() > 1) {
Platform.runLater(() -> input.setText("-"));
}
return;
}
@ -95,10 +103,14 @@ public class DoubleStringConverter extends StringConverter<Double> {
// redundant for Spinner but not harmful
final double restricted = Math.min(Math.max(value, min), max);
if (value != restricted) { input.setText(_format.format(restricted)); }
if (value != restricted) {
input.setText(decimalFormat.format(restricted));
}
// required for Spinner which handles onAction
if (oldHandler != null) { oldHandler.handle(t); }
if (oldHandler != null) {
oldHandler.handle(t);
}
});
}
@ -139,7 +151,7 @@ public class DoubleStringConverter extends StringConverter<Double> {
* @see #fromString
*/
public void setReset(Runnable reset) {
_reset = reset;
this.reset = reset;
}
/**
@ -154,14 +166,18 @@ public class DoubleStringConverter extends StringConverter<Double> {
@Override
public Double fromString(String s) {
if (s == null || s.isEmpty()) {
if (_reset != null) { _reset.run(); }
if (reset != null) {
reset.run();
}
return 0.0;
}
try {
return Double.valueOf(s);
} catch (NumberFormatException e) {
if (_reset != null) { _reset.run(); }
if (reset != null) {
reset.run();
}
return 0.0;
}
}
@ -175,7 +191,9 @@ public class DoubleStringConverter extends StringConverter<Double> {
*/
@Override
public String toString(Double value) {
if (value == null) { return "0"; }
return _format.format(value);
if (value == null) {
return "0";
}
return decimalFormat.format(value);
}
}

@ -21,14 +21,15 @@ import javafx.util.StringConverter;
*/
public class IntegerStringConverter extends StringConverter<Integer> {
private Runnable _reset;
private Runnable reset;
/**
* Creates an {@link IntegerStringConverter}.
* Swallows {@link NumberFormatException} but does nothing
* in response until {@link #setReset} is defined.
*/
public IntegerStringConverter() { }
public IntegerStringConverter() {
}
/**
* Creates an {@link IntegerStringConverter} with an editor reset callback.
@ -37,7 +38,7 @@ public class IntegerStringConverter extends StringConverter<Integer> {
* @param reset the {@link Runnable} to call upon {@link NumberFormatException}
*/
public IntegerStringConverter(Runnable reset) {
_reset = reset;
this.reset = reset;
}
/**
@ -53,10 +54,12 @@ public class IntegerStringConverter extends StringConverter<Integer> {
* @throws NullPointerException if {@code input} is {@code null}
*/
public IntegerStringConverter(TextField input, int min, int max) {
if (input == null) { throw new NullPointerException("input"); }
if (input == null) {
throw new NullPointerException("Input cannot be null!");
}
final int resetValue = Math.min(Math.max(0, min), max);
_reset = () -> input.setText(Integer.toString(resetValue));
reset = () -> input.setText(Integer.toString(resetValue));
// bound JavaFX properties cannot be explicitly set
// if (!input.tooltipProperty().isBound()) {
@ -65,11 +68,15 @@ public class IntegerStringConverter extends StringConverter<Integer> {
// restrict direct input to valid numerical characters
input.textProperty().addListener((ov, oldValue, newValue) -> {
if (newValue == null || newValue.isEmpty()) { return; }
if (newValue == null || newValue.isEmpty()) {
return;
}
// special case: minus sign if negative values allowed
if (min < 0 && newValue.endsWith("-")) {
if (newValue.length() > 1) { Platform.runLater(() -> input.setText("-")); }
if (newValue.length() > 1) {
Platform.runLater(() -> input.setText("-"));
}
return;
}
@ -89,10 +96,14 @@ public class IntegerStringConverter extends StringConverter<Integer> {
// redundant for Spinner but not harmful
final int restricted = Math.min(Math.max(value, min), max);
if (value != restricted) { input.setText(Integer.toString(restricted)); }
if (value != restricted) {
input.setText(Integer.toString(restricted));
}
// required for Spinner which handles onAction
if (oldHandler != null) { oldHandler.handle(t); }
if (oldHandler != null) {
oldHandler.handle(t);
}
});
}
@ -133,7 +144,7 @@ public class IntegerStringConverter extends StringConverter<Integer> {
* @see #fromString
*/
public void setReset(Runnable reset) {
_reset = reset;
this.reset = reset;
}
/**
@ -148,14 +159,18 @@ public class IntegerStringConverter extends StringConverter<Integer> {
@Override
public Integer fromString(String s) {
if (s == null || s.isEmpty()) {
if (_reset != null) { _reset.run(); }
if (reset != null) {
reset.run();
}
return 0;
}
try {
return Integer.valueOf(s);
} catch (NumberFormatException e) {
if (_reset != null) { _reset.run(); }
if (reset != null) {
reset.run();
}
return 0;
}
}
@ -169,7 +184,9 @@ public class IntegerStringConverter extends StringConverter<Integer> {
*/
@Override
public String toString(Integer value) {
if (value == null) { return "0"; }
if (value == null) {
return "0";
}
return Integer.toString(value);
}
}

@ -27,9 +27,12 @@ public class PasswordTextFormatter extends TextFormatter<String> {
char bullet) {
super(valueConverter, null, filter);
Objects.requireNonNull(valueConverter);
Objects.requireNonNull(filter);
Objects.requireNonNull(textField);
if (valueConverter == null)
throw new NullPointerException("StringConverter cannot be null!");
if (filter == null)
throw new NullPointerException("UnaryOperator cannot be null!");
if (textField == null)
throw new NullPointerException("TextField cannot be null!");
PasswordFilter passwordFilter = (PasswordFilter) getFilter();
passwordFilter.setBullet(bullet);
@ -39,7 +42,9 @@ public class PasswordTextFormatter extends TextFormatter<String> {
// Force text field update, because converter is only called on focus
// events by default. Don't use commitValue() here because caret position
// won't be correct due to #javafx-bug (https://bugs.openjdk.org/browse/JDK-8248914).
if (val == null) { return; }
if (val == null) {
return;
}
textField.setText(passwordProperty().get());
});
@ -90,7 +95,9 @@ public class PasswordTextFormatter extends TextFormatter<String> {
@Override
public String toString(String s) {
if (s == null) { return ""; }
if (s == null) {
return "";
}
return filter.revealPassword.get() ? filter.password.get() : filter.maskText(s.length());
}

@ -3,8 +3,15 @@ package atlantafx.base.util;
public final class PlatformUtils {
private static final String OS = System.getProperty("os.name");
private static final boolean MAC = OS.startsWith("Mac");
/**
* Initialize a new PlatformUtils
*/
private PlatformUtils() {
// Default constructor
}
private static final String OS = System.getProperty("os.name", "generic").toLowerCase();
private static final boolean MAC = OS.contains("mac") || OS.contains("darwin");
public static boolean isMac() {
return MAC;

@ -4,16 +4,16 @@ parent: Colors
nav_order: 2
---
Global variables are defined at the Scene root level. You can preview all of the them in the Sampler app.
Global variables are defined at the Scene root level. You can preview all of them in the Sampler app.
AtlantaFX is based on GitHub Primer color system. You can check [GitHub Primer interface guidelines](https://primer.style/design/foundations/color) for more detailed instructions. There'are functional color variables and color scale variables.
AtlantaFX is based on GitHub Primer color system. You can check [GitHub Primer interface guidelines](https://primer.style/design/foundations/color) for more detailed instructions. There are functional color variables and color scale variables.
## Functional colors
Foreground colors.
| Color | Usage |
|-------|-------|
|----------------------|----------------------------------------------------------------------------------------------------------------------------------|
| `-color-fg-default` | Primary color for text and icons. It should be used for body content, titles and labels. |
| `-color-fg-muted` | For content that is secondary or that provides additional context but is not critical to understanding the flow of an interface. |
| `-color-fg-subtle` | For placeholders or decorative foregrounds. |
@ -22,7 +22,7 @@ Foreground colors.
Background colors.
| Color | Usage |
|-------|-------|
|---------------------|--------------------------------------------------------------------|
| `-color-bg-default` | Primary background color. |
| `-color-bg-overlay` | Background color for popup controls such as popovers and tooltips. |
| `-color-bg-subtle` | Provides visual rest and contrast against the default background. |

@ -24,7 +24,8 @@
<!-- AppDir spec compliant dir for creating AppImage -->
<build.package.appDir>${project.build.directory}${file.separator}app-dir</build.package.appDir>
<!-- jlink generated runtime image -->
<build.package.runtimeImageDir>${project.build.directory}${file.separator}runtime-image</build.package.runtimeImageDir>
<build.package.runtimeImageDir>${project.build.directory}${file.separator}runtime-image
</build.package.runtimeImageDir>
<!-- contains package scripts after filtering and placeholder replacement -->
<build.package.scriptsDir>${project.build.directory}${file.separator}package-scripts</build.package.scriptsDir>
<!-- jpackage directory for temp artifacts -->
@ -136,7 +137,9 @@
<artifactId>sass-cli-maven-plugin</artifactId>
<configuration>
<args>
<arg>${project.basedir}/src/main/resources/assets/styles/scss/index.scss:${project.build.directory}/classes/atlantafx/sampler/assets/styles/index.css</arg>
<arg>
${project.basedir}/src/main/resources/assets/styles/scss/index.scss:${project.build.directory}/classes/atlantafx/sampler/assets/styles/index.css
</arg>
<arg>--no-source-map</arg>
</args>
</configuration>
@ -223,7 +226,9 @@
</goals>
<configuration>
<toolName>jlink</toolName>
<addModules>java.base,java.logging,jdk.localedata,java.desktop,java.prefs,javafx.controls,javafx.swing,javafx.web</addModules>
<addModules>
java.base,java.logging,jdk.localedata,java.desktop,java.prefs,javafx.controls,javafx.swing,javafx.web
</addModules>
<modulePath>${build.platformModulesDir}</modulePath>
<output>${build.package.runtimeImageDir}</output>
<args>

@ -60,7 +60,9 @@ public class Launcher extends Application {
var tm = ThemeManager.getInstance();
tm.setScene(scene);
tm.setTheme(tm.getDefaultTheme());
if (IS_DEV_MODE) { startCssFX(scene); }
if (IS_DEV_MODE) {
startCssFX(scene);
}
scene.getStylesheets().addAll(Resources.resolve("assets/styles/index.css"));
@ -89,9 +91,9 @@ public class Launcher extends Application {
}
private void loadApplicationProperties() {
try {
var properties = new Properties();
properties.load(new InputStreamReader(Resources.getResourceAsStream("application.properties"), UTF_8));
Properties properties = new Properties();
try (InputStreamReader in = new InputStreamReader(Resources.getResourceAsStream("application.properties"), UTF_8)) {
properties.load(in);
properties.forEach((key, value) -> System.setProperty(
String.valueOf(key),
String.valueOf(value)

@ -14,7 +14,7 @@ import java.util.function.Consumer;
* Subscribe and publish events. Events are published in channels distinguished by event type.
* Channels can be grouped using an event type hierarchy.
* <p>
* You can use the default event bus instance {@link #getInstance}, which is a singleton
* You can use the default event bus instance {@link #getInstance}, which is a singleton,
* or you can create one or multiple instances of {@link DefaultEventBus}.
*/
@SuppressWarnings({"unchecked", "rawtypes"})

@ -12,7 +12,6 @@ import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static atlantafx.sampler.util.Containers.setScrollConstraints;
@ -66,6 +65,7 @@ public abstract class AbstractPage extends BorderPane implements Page {
@Override
public void reset() { }
@Override
protected void layoutChildren() {
super.layoutChildren();
if (isRendered) { return; }
@ -81,7 +81,7 @@ public abstract class AbstractPage extends BorderPane implements Page {
}
protected Overlay lookupOverlay() {
return getScene() != null && getScene().lookup("." + Overlay.STYLE_CLASS) instanceof Overlay overlay ? overlay : null;
return getScene() != null && getScene().lookup("." + Overlay.STYLE_CLASS) instanceof Overlay ov ? ov : null;
}
///////////////////////////////////////////////////////////////////////////
@ -93,7 +93,7 @@ public abstract class AbstractPage extends BorderPane implements Page {
}
protected <T> List<T> generate(Supplier<T> supplier, int count) {
return Stream.generate(supplier).limit(count).collect(Collectors.toList());
return Stream.generate(supplier).limit(count).toList();
}
protected Feather randomIcon() {

@ -216,10 +216,10 @@ public class TablePage extends AbstractPage {
var stockCol = new TableColumn<Product, Double>("Stock");
stockCol.getColumns().setAll(stockCountCol, stockAvailCol);
var table = new TableView<Product>();
table.getColumns().setAll(stateCol, indexCol, iconCol, brandCol, nameCol, priceCol, stockCol);
var tableView = new TableView<Product>();
tableView.getColumns().setAll(stateCol, indexCol, iconCol, brandCol, nameCol, priceCol, stockCol);
return table;
return tableView;
}
private MenuButton createTablePropertiesMenu(TableView<Product> table) {

@ -73,7 +73,9 @@ class ColorPaletteBlock extends VBox {
var bgFill = getBgColor();
// this happens when css isn't updated yet
if (bgFill == null) { return; }
if (bgFill == null) {
return;
}
toggleHover(true);
editIcon.setFill(getColorLuminance(flattenColor(bgBaseColor.get(), bgFill)) < LUMINANCE_THRESHOLD ?
@ -82,7 +84,9 @@ class ColorPaletteBlock extends VBox {
});
colorRectangle.setOnMouseExited(e -> toggleHover(false));
colorRectangle.setOnMouseClicked(e -> {
if (actionHandler != null) { actionHandler.accept(this); }
if (actionHandler != null) {
actionHandler.accept(this);
}
});
getChildren().addAll(
@ -152,7 +156,10 @@ class ColorPaletteBlock extends VBox {
}
static String validateColorName(String colorName) {
if (colorName == null || !colorName.startsWith("-color")) {
if (colorName == null) {
throw new NullPointerException("Color name cannot be null!");
}
if (!colorName.startsWith("-color")) {
throw new IllegalArgumentException("Invalid color name: '" + colorName + "'.");
}
return colorName;

@ -4,7 +4,6 @@ package atlantafx.sampler.page.showcase.filemanager;
import atlantafx.base.controls.Breadcrumbs;
import atlantafx.base.controls.Spacer;
import atlantafx.base.theme.Tweaks;
import atlantafx.sampler.page.components.BreadcrumbsPage;
import atlantafx.sampler.page.showcase.ShowcasePage;
import atlantafx.sampler.util.Containers;
import javafx.geometry.Insets;

@ -7,13 +7,17 @@ import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.attribute.FileTime;
import java.text.CharacterIterator;
import java.text.StringCharacterIterator;
final class Utils {
private Utils() {
// Default constructor
}
public static long fileSize(Path path) {
if (path == null) { return 0; }
if (path == null) {
return 0;
}
try {
return Files.size(path);
} catch (IOException e) {
@ -22,7 +26,9 @@ final class Utils {
}
public static boolean isFileHidden(Path path) {
if (path == null) { return false; }
if (path == null) {
return false;
}
try {
return Files.isHidden(path);
} catch (IOException e) {
@ -31,7 +37,9 @@ final class Utils {
}
public static FileTime fileMTime(Path path, LinkOption... options) {
if (path == null) { return null; }
if (path == null) {
return null;
}
try {
return Files.getLastModifiedTime(path, options);
} catch (IOException e) {
@ -45,7 +53,7 @@ final class Utils {
try {
Desktop.getDesktop().open(path.toFile());
} catch (IOException e) {
throw new RuntimeException();
throw new RuntimeException(e);
}
}).start();
}

@ -28,13 +28,20 @@ public enum ContrastLevel {
public boolean satisfies(double ratio) {
switch (this) {
case AA_NORMAL -> { return ratio >= 4.5; }
case AA_LARGE -> { return ratio >= 3; }
case AAA_NORMAL -> { return ratio >= 7; }
case AAA_LARGE -> { return ratio >= 4.5; }
case AA_NORMAL, AAA_LARGE -> {
return ratio >= 4.5;
}
case AA_LARGE -> {
return ratio >= 3;
}
case AAA_NORMAL -> {
return ratio >= 7;
}
default -> {
return false;
}
}
}
public static double getContrastRatio(Color color1, Color color2) {
return getContrastRatio(getColorLuminance(color1), getColorLuminance(color2));
@ -67,7 +74,9 @@ public enum ContrastLevel {
return (tmp[0] * 0.2126) + (tmp[1] * 0.7152) + (tmp[2] * 0.0722);
}
/** @see ContrastLevel#getColorLuminance(double[]) */
/**
* @see ContrastLevel#getColorLuminance(double[])
*/
public static double getColorLuminance(Color color) {
return getColorLuminance(new double[]{color.getRed(), color.getGreen(), color.getBlue()});
}

@ -219,7 +219,7 @@ public class JColorUtils {
}
/**
* Convert the hex single color to a RGB integer
* Convert the hex single color to an RGB integer
*
* @param color hex single color in format FF or F
* @return integer color inclusively between 0 and 255
@ -233,7 +233,7 @@ public class JColorUtils {
}
/**
* Convert the arithmetic RGB float to a RGB integer
* Convert the arithmetic RGB float to an RGB integer
*
* @param color float color inclusively between 0.0 and 1.0
* @return integer color inclusively between 0 and 255