Checkstyle: reformat code

This commit is contained in:
mkpaz 2023-02-09 20:08:30 +04:00
parent a9bc7ace6f
commit deb27f576a
147 changed files with 2566 additions and 1849 deletions

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.base.controls; package atlantafx.base.controls;
import javafx.scene.control.Control; import javafx.scene.control.Control;
@ -22,7 +23,9 @@ public abstract class BehaviorBase<C extends Control, S extends SkinBase<C>> {
return skin; return skin;
} }
/** Called from {@link SkinBase#dispose()} to clean up the behavior state */ /**
* Called from {@link SkinBase#dispose()} to clean up the behavior state
*/
public void dispose() { public void dispose() {
this.control = null; this.control = null;
this.skin = null; this.skin = null;

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.base.controls; package atlantafx.base.controls;
import java.util.function.Consumer; import java.util.function.Consumer;
@ -31,7 +32,8 @@ public abstract class BehaviorSkinBase<C extends Control, B extends BehaviorBase
* {@link SkinBase#registerChangeListener(ObservableValue, Consumer)} method, * {@link SkinBase#registerChangeListener(ObservableValue, Consumer)} method,
* because it will be done automatically from dispose method. * because it will be done automatically from dispose method.
*/ */
protected void unregisterListeners() { } protected void unregisterListeners() {
}
/** /**
* {@inheritDoc} * {@inheritDoc}

@ -26,6 +26,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package atlantafx.base.controls; package atlantafx.base.controls;
import java.util.UUID; import java.util.UUID;
@ -61,11 +62,13 @@ public class Breadcrumbs<T> extends Control {
protected static final String DEFAULT_STYLE_CLASS = "breadcrumbs"; protected static final String DEFAULT_STYLE_CLASS = "breadcrumbs";
protected final Callback<BreadCrumbItem<T>, ButtonBase> defaultCrumbNodeFactory = protected final Callback<BreadCrumbItem<T>, ButtonBase> defaultCrumbNodeFactory =
item -> new Hyperlink(item.getStringValue()); item -> new Hyperlink(item.getStringValue());
protected final Callback<BreadCrumbItem<T>, ? extends Node> defaultDividerFactory = protected final Callback<BreadCrumbItem<T>, ? extends Node> defaultDividerFactory =
item -> item != null && !item.isLast() ? new Label("/") : null; item -> item != null && !item.isLast() ? new Label("/") : null;
/** Creates an empty bread crumb bar. */ /**
* Creates an empty bread crumb bar.
*/
public Breadcrumbs() { public Breadcrumbs() {
this(null); this(null);
} }
@ -88,7 +91,9 @@ public class Breadcrumbs<T> extends Control {
setDividerFactory(defaultDividerFactory); setDividerFactory(defaultDividerFactory);
} }
/** {@inheritDoc} */ /**
* {@inheritDoc}
*/
@Override @Override
protected Skin<?> createDefaultSkin() { protected Skin<?> createDefaultSkin() {
return new BreadcrumbsSkin<>(this); return new BreadcrumbsSkin<>(this);
@ -131,7 +136,7 @@ public class Breadcrumbs<T> extends Control {
} }
protected final ObjectProperty<BreadCrumbItem<T>> selectedCrumb = protected final ObjectProperty<BreadCrumbItem<T>> selectedCrumb =
new SimpleObjectProperty<>(this, "selectedCrumb"); new SimpleObjectProperty<>(this, "selectedCrumb");
public final BreadCrumbItem<T> getSelectedCrumb() { public final BreadCrumbItem<T> getSelectedCrumb() {
return selectedCrumb.get(); return selectedCrumb.get();
@ -153,7 +158,7 @@ public class Breadcrumbs<T> extends Control {
} }
protected final BooleanProperty autoNavigation = protected final BooleanProperty autoNavigation =
new SimpleBooleanProperty(this, "autoNavigationEnabled", true); new SimpleBooleanProperty(this, "autoNavigationEnabled", true);
public final boolean isAutoNavigationEnabled() { public final boolean isAutoNavigationEnabled() {
return autoNavigation.get(); return autoNavigation.get();
@ -178,7 +183,7 @@ public class Breadcrumbs<T> extends Control {
} }
protected final ObjectProperty<Callback<BreadCrumbItem<T>, ButtonBase>> crumbFactory = protected final ObjectProperty<Callback<BreadCrumbItem<T>, ButtonBase>> crumbFactory =
new SimpleObjectProperty<>(this, "crumbFactory"); new SimpleObjectProperty<>(this, "crumbFactory");
public final void setCrumbFactory(Callback<BreadCrumbItem<T>, ButtonBase> value) { public final void setCrumbFactory(Callback<BreadCrumbItem<T>, ButtonBase> value) {
if (value == null) { if (value == null) {
@ -208,7 +213,7 @@ public class Breadcrumbs<T> extends Control {
} }
protected final ObjectProperty<Callback<BreadCrumbItem<T>, ? extends Node>> dividerFactory = protected final ObjectProperty<Callback<BreadCrumbItem<T>, ? extends Node>> dividerFactory =
new SimpleObjectProperty<>(this, "dividerFactory"); new SimpleObjectProperty<>(this, "dividerFactory");
public final void setDividerFactory(Callback<BreadCrumbItem<T>, ? extends Node> value) { public final void setDividerFactory(Callback<BreadCrumbItem<T>, ? extends Node> value) {
if (value == null) { if (value == null) {
@ -228,7 +233,9 @@ public class Breadcrumbs<T> extends Control {
return onCrumbAction; return onCrumbAction;
} }
/** Set a new EventHandler for when a user selects a crumb. */ /**
* Set a new EventHandler for when a user selects a crumb.
*/
public final void setOnCrumbAction(EventHandler<BreadCrumbActionEvent<T>> value) { public final void setOnCrumbAction(EventHandler<BreadCrumbActionEvent<T>> value) {
onCrumbActionProperty().set(value); onCrumbActionProperty().set(value);
} }
@ -239,7 +246,7 @@ public class Breadcrumbs<T> extends Control {
protected final ObjectProperty<EventHandler<BreadCrumbActionEvent<T>>> onCrumbAction = new ObjectPropertyBase<>() { protected final ObjectProperty<EventHandler<BreadCrumbActionEvent<T>>> onCrumbAction = new ObjectPropertyBase<>() {
@SuppressWarnings({ "unchecked", "rawtypes" }) @SuppressWarnings({"unchecked", "rawtypes"})
@Override @Override
protected void invalidated() { protected void invalidated() {
setEventHandler(BreadCrumbActionEvent.CRUMB_ACTION, (EventHandler<BreadCrumbActionEvent>) (Object) get()); setEventHandler(BreadCrumbActionEvent.CRUMB_ACTION, (EventHandler<BreadCrumbActionEvent>) (Object) get());
@ -289,7 +296,9 @@ public class Breadcrumbs<T> extends Control {
} }
} }
/** Represents an Event which is fired when a bread crumb was activated. */ /**
* Represents an Event which is fired when a bread crumb was activated.
*/
public static class BreadCrumbActionEvent<TE> extends Event { public static class BreadCrumbActionEvent<TE> extends Event {
/** /**
@ -298,11 +307,13 @@ public class Breadcrumbs<T> extends Control {
* has changed. * has changed.
*/ */
public static final EventType<BreadCrumbActionEvent<?>> CRUMB_ACTION public static final EventType<BreadCrumbActionEvent<?>> CRUMB_ACTION
= new EventType<>("CRUMB_ACTION" + UUID.randomUUID()); = new EventType<>("CRUMB_ACTION" + UUID.randomUUID());
private final BreadCrumbItem<TE> selectedCrumb; private final BreadCrumbItem<TE> selectedCrumb;
/** Creates a new event that can subsequently be fired. */ /**
* Creates a new event that can subsequently be fired.
*/
public BreadCrumbActionEvent(BreadCrumbItem<TE> selectedCrumb) { public BreadCrumbActionEvent(BreadCrumbItem<TE> selectedCrumb) {
super(CRUMB_ACTION); super(CRUMB_ACTION);
this.selectedCrumb = selectedCrumb; this.selectedCrumb = selectedCrumb;

@ -26,6 +26,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package atlantafx.base.controls; package atlantafx.base.controls;
import atlantafx.base.controls.Breadcrumbs.BreadCrumbItem; import atlantafx.base.controls.Breadcrumbs.BreadCrumbItem;
@ -78,7 +79,9 @@ public class BreadcrumbsSkin<T> extends SkinBase<Breadcrumbs<T>> {
double bottomInset, double leftInset) { double bottomInset, double leftInset) {
double width = 0; double width = 0;
for (Node node : getChildren()) { for (Node node : getChildren()) {
if (!node.isManaged()) { continue; } if (!node.isManaged()) {
continue;
}
width += snapSizeX(node.prefWidth(height)); width += snapSizeX(node.prefWidth(height));
} }
@ -148,8 +151,12 @@ public class BreadcrumbsSkin<T> extends SkinBase<Breadcrumbs<T>> {
Collections.reverse(path); Collections.reverse(path);
// if the path consists of a single item it considered as first, but not last // if the path consists of a single item it considered as first, but not last
if (path.size() > 0) { path.get(0).setFirst(true); } if (path.size() > 0) {
if (path.size() > 1) { path.get(path.size() - 1).setLast(true); } path.get(0).setFirst(true);
}
if (path.size() > 1) {
path.get(path.size() - 1).setLast(true);
}
return path; return path;
} }

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.base.controls; package atlantafx.base.controls;
import javafx.beans.property.StringProperty; import javafx.beans.property.StringProperty;

@ -26,6 +26,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package atlantafx.base.controls; package atlantafx.base.controls;
import javafx.beans.property.ObjectProperty; import javafx.beans.property.ObjectProperty;
@ -41,7 +42,9 @@ import javafx.scene.control.TextField;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public class CustomTextField extends TextField { public class CustomTextField extends TextField {
/** Instantiates a default CustomTextField. */ /**
* Instantiates a default CustomTextField.
*/
public CustomTextField() { public CustomTextField() {
getStyleClass().add("custom-text-field"); getStyleClass().add("custom-text-field");
} }
@ -106,7 +109,9 @@ public class CustomTextField extends TextField {
// Methods // // Methods //
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
/** {@inheritDoc} */ /**
* {@inheritDoc}
*/
@Override @Override
protected Skin<?> createDefaultSkin() { protected Skin<?> createDefaultSkin() {
return new CustomTextFieldSkin(this) { return new CustomTextFieldSkin(this) {

@ -26,6 +26,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package atlantafx.base.controls; package atlantafx.base.controls;
import javafx.beans.property.ObjectProperty; import javafx.beans.property.ObjectProperty;

@ -24,6 +24,7 @@
* or visit www.oracle.com if you need additional information or have any * or visit www.oracle.com if you need additional information or have any
* questions. * questions.
*/ */
package atlantafx.base.controls; package atlantafx.base.controls;
import java.time.DateTimeException; import java.time.DateTimeException;
@ -72,7 +73,9 @@ public class InlineDatePicker extends Control {
protected LocalDate lastValidDate = null; protected LocalDate lastValidDate = null;
protected Chronology lastValidChronology = IsoChronology.INSTANCE; protected Chronology lastValidChronology = IsoChronology.INSTANCE;
/** Creates a default DatePicker instance with a <code>null</code> date value set. */ /**
* Creates a default DatePicker instance with a <code>null</code> date value set.
*/
public InlineDatePicker() { public InlineDatePicker() {
this(null); this(null);
@ -111,7 +114,9 @@ public class InlineDatePicker extends Control {
getStyleClass().add(DEFAULT_STYLE_CLASS); getStyleClass().add(DEFAULT_STYLE_CLASS);
} }
/** {@inheritDoc} */ /**
* {@inheritDoc}
*/
@Override @Override
protected Skin<?> createDefaultSkin() { protected Skin<?> createDefaultSkin() {
return new InlineDatePickerSkin(this); return new InlineDatePickerSkin(this);
@ -131,7 +136,9 @@ public class InlineDatePicker extends Control {
valueProperty().set(value); valueProperty().set(value);
} }
public ObjectProperty<LocalDate> valueProperty() { return value; } public ObjectProperty<LocalDate> valueProperty() {
return value;
}
/** /**
* A custom cell factory can be provided to customize individual day cells * A custom cell factory can be provided to customize individual day cells
@ -270,18 +277,18 @@ public class InlineDatePicker extends Control {
private static final List<CssMetaData<? extends Styleable, ?>> STYLEABLES; private static final List<CssMetaData<? extends Styleable, ?>> STYLEABLES;
private static final CssMetaData<InlineDatePicker, Boolean> SHOW_WEEK_NUMBERS = private static final CssMetaData<InlineDatePicker, Boolean> SHOW_WEEK_NUMBERS =
new CssMetaData<>("-fx-show-week-numbers", BooleanConverter.getInstance(), false) { new CssMetaData<>("-fx-show-week-numbers", BooleanConverter.getInstance(), false) {
@Override @Override
public boolean isSettable(InlineDatePicker n) { public boolean isSettable(InlineDatePicker n) {
return n.showWeekNumbers == null || !n.showWeekNumbers.isBound(); return n.showWeekNumbers == null || !n.showWeekNumbers.isBound();
} }
@Override @Override
@SuppressWarnings("RedundantCast") @SuppressWarnings("RedundantCast")
public StyleableProperty<Boolean> getStyleableProperty(InlineDatePicker n) { public StyleableProperty<Boolean> getStyleableProperty(InlineDatePicker n) {
return (StyleableProperty<Boolean>) (WritableValue<Boolean>) n.showWeekNumbersProperty(); return (StyleableProperty<Boolean>) (WritableValue<Boolean>) n.showWeekNumbersProperty();
} }
}; };
static { static {
final List<CssMetaData<? extends Styleable, ?>> styleables = new ArrayList<>(Control.getClassCssMetaData()); final List<CssMetaData<? extends Styleable, ?>> styleables = new ArrayList<>(Control.getClassCssMetaData());
@ -298,7 +305,9 @@ public class InlineDatePicker extends Control {
return StyleableProperties.STYLEABLES; return StyleableProperties.STYLEABLES;
} }
/** {@inheritDoc} */ /**
* {@inheritDoc}
*/
@Override @Override
public List<CssMetaData<? extends Styleable, ?>> getControlCssMetaData() { public List<CssMetaData<? extends Styleable, ?>> getControlCssMetaData() {
return getClassCssMetaData(); return getClassCssMetaData();

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.base.controls; package atlantafx.base.controls;
import static atlantafx.base.util.PlatformUtils.isMac; import static atlantafx.base.util.PlatformUtils.isMac;
@ -56,7 +57,9 @@ public class InlineDatePickerBehavior extends BehaviorBase<InlineDatePicker, Inl
} }
// prevents any other key events but ESC from reaching the control owner // prevents any other key events but ESC from reaching the control owner
if (e.getCode() != ESCAPE) { e.consume(); } if (e.getCode() != ESCAPE) {
e.consume();
}
} }
public void moveForward(MouseEvent e) { public void moveForward(MouseEvent e) {

@ -24,6 +24,7 @@
* or visit www.oracle.com if you need additional information or have any * or visit www.oracle.com if you need additional information or have any
* questions. * questions.
*/ */
package atlantafx.base.controls; package atlantafx.base.controls;
import static atlantafx.base.controls.InlineDatePicker.isValidDate; import static atlantafx.base.controls.InlineDatePicker.isValidDate;
@ -101,11 +102,16 @@ public class InlineDatePickerSkin extends BehaviorSkinBase<InlineDatePicker, Inl
private final ObjectProperty<YearMonth> displayedYearMonth = new SimpleObjectProperty<>(this, "displayedYearMonth"); private final ObjectProperty<YearMonth> displayedYearMonth = new SimpleObjectProperty<>(this, "displayedYearMonth");
public ObjectProperty<YearMonth> displayedYearMonthProperty() { return displayedYearMonth; } public ObjectProperty<YearMonth> displayedYearMonthProperty() {
return displayedYearMonth;
}
private final ObjectBinding<LocalDate> firstDayOfMonth = Bindings.createObjectBinding(() -> displayedYearMonth.get().atDay(1), displayedYearMonth); private final ObjectBinding<LocalDate> firstDayOfMonth =
Bindings.createObjectBinding(() -> displayedYearMonth.get().atDay(1), displayedYearMonth);
public LocalDate getFirstDayOfMonth() { return firstDayOfMonth.get(); } public LocalDate getFirstDayOfMonth() {
return firstDayOfMonth.get();
}
public InlineDatePickerSkin(InlineDatePicker datePicker) { public InlineDatePickerSkin(InlineDatePicker datePicker) {
super(datePicker); super(datePicker);
@ -115,7 +121,7 @@ public class InlineDatePickerSkin extends BehaviorSkinBase<InlineDatePicker, Inl
registerChangeListener(datePicker.valueProperty(), e -> { registerChangeListener(datePicker.valueProperty(), e -> {
LocalDate date = datePicker.getValue(); LocalDate date = datePicker.getValue();
displayedYearMonthProperty().set( displayedYearMonthProperty().set(
date != null ? YearMonth.from(date) : YearMonth.now(ZoneId.systemDefault()) date != null ? YearMonth.from(date) : YearMonth.now(ZoneId.systemDefault())
); );
updateValues(); updateValues();
datePicker.fireEvent(new ActionEvent()); datePicker.fireEvent(new ActionEvent());
@ -197,7 +203,7 @@ public class InlineDatePickerSkin extends BehaviorSkinBase<InlineDatePicker, Inl
LocalDate value = getControl().getValue(); LocalDate value = getControl().getValue();
displayedYearMonth.set( displayedYearMonth.set(
value != null ? YearMonth.from(value) : YearMonth.now(ZoneId.systemDefault()) value != null ? YearMonth.from(value) : YearMonth.now(ZoneId.systemDefault())
); );
displayedYearMonth.addListener((observable, oldValue, newValue) -> updateValues()); displayedYearMonth.addListener((observable, oldValue, newValue) -> updateValues());
@ -381,9 +387,9 @@ public class InlineDatePickerSkin extends BehaviorSkinBase<InlineDatePicker, Inl
// use a formatter to ensure correct localization // use a formatter to ensure correct localization
// such as when Thai numerals are required. // such as when Thai numerals are required.
String cellText = weekNumberFormatter String cellText = weekNumberFormatter
.withLocale(locale) .withLocale(locale)
.withDecimalStyle(DecimalStyle.of(locale)) .withDecimalStyle(DecimalStyle.of(locale))
.format(date); .format(date);
weekNumberCells.get(i).setText(cellText); weekNumberCells.get(i).setText(cellText);
} }
} }
@ -445,9 +451,9 @@ public class InlineDatePickerSkin extends BehaviorSkinBase<InlineDatePicker, Inl
} }
String cellText = dayCellFormatter.withLocale(locale) String cellText = dayCellFormatter.withLocale(locale)
.withChronology(chrono) .withChronology(chrono)
.withDecimalStyle(DecimalStyle.of(locale)) .withDecimalStyle(DecimalStyle.of(locale))
.format(cDate); .format(cDate);
dayCell.setText(cellText); dayCell.setText(cellText);
dayCell.updateItem(date, false); dayCell.updateItem(date, false);
@ -480,13 +486,13 @@ public class InlineDatePickerSkin extends BehaviorSkinBase<InlineDatePicker, Inl
try { try {
ChronoLocalDate chronoDate = chrono.date(yearMonth.atDay(1)); ChronoLocalDate chronoDate = chrono.date(yearMonth.atDay(1));
String str = monthFormatterSO.withLocale(getLocale()) String str = monthFormatterSO.withLocale(getLocale())
.withChronology(chrono) .withChronology(chrono)
.format(chronoDate); .format(chronoDate);
if (Character.isDigit(str.charAt(0))) { if (Character.isDigit(str.charAt(0))) {
// fallback: if standalone format returned a number, use standard format instead // fallback: if standalone format returned a number, use standard format instead
str = monthFormatter.withLocale(getLocale()) str = monthFormatter.withLocale(getLocale())
.withChronology(chrono) .withChronology(chrono)
.format(chronoDate); .format(chronoDate);
} }
return capitalize(str); return capitalize(str);
} catch (DateTimeException ex) { } catch (DateTimeException ex) {
@ -500,9 +506,9 @@ public class InlineDatePickerSkin extends BehaviorSkinBase<InlineDatePicker, Inl
try { try {
ChronoLocalDate chronoDate = chrono.date(yearMonth.atDay(1)); ChronoLocalDate chronoDate = chrono.date(yearMonth.atDay(1));
return yearFormatter.withLocale(getLocale()) return yearFormatter.withLocale(getLocale())
.withChronology(chrono) .withChronology(chrono)
.withDecimalStyle(DecimalStyle.of(getLocale())) .withDecimalStyle(DecimalStyle.of(getLocale()))
.format(chronoDate); .format(chronoDate);
} catch (DateTimeException ex) { } catch (DateTimeException ex) {
// date is out of range // date is out of range
return ""; return "";
@ -550,7 +556,9 @@ public class InlineDatePickerSkin extends BehaviorSkinBase<InlineDatePicker, Inl
protected void createDayCells() { protected void createDayCells() {
EventHandler<MouseEvent> dayCellActionHandler = e -> { EventHandler<MouseEvent> dayCellActionHandler = e -> {
if (e.getButton() != MouseButton.PRIMARY) { return; } if (e.getButton() != MouseButton.PRIMARY) {
return;
}
DateCell dayCell = (DateCell) e.getSource(); DateCell dayCell = (DateCell) e.getSource();
selectDayCell(dayCell); selectDayCell(dayCell);
lastFocusedDayCell = dayCell; lastFocusedDayCell = dayCell;
@ -570,8 +578,8 @@ public class InlineDatePickerSkin extends BehaviorSkinBase<InlineDatePicker, Inl
protected DateCell createDayCell() { protected DateCell createDayCell() {
Callback<InlineDatePicker, DateCell> factory = getControl().getDayCellFactory(); Callback<InlineDatePicker, DateCell> factory = getControl().getDayCellFactory();
return Objects.requireNonNullElseGet( return Objects.requireNonNullElseGet(
factory != null ? factory.call(getControl()) : null, factory != null ? factory.call(getControl()) : null,
DateCell::new DateCell::new
); );
} }
@ -612,8 +620,8 @@ public class InlineDatePickerSkin extends BehaviorSkinBase<InlineDatePicker, Inl
int firstChar = word.codePointAt(0); int firstChar = word.codePointAt(0);
if (!Character.isTitleCase(firstChar)) { if (!Character.isTitleCase(firstChar)) {
word = new String(new int[] { word = new String(new int[] {
Character.toTitleCase(firstChar) }, 0, 1) + Character.toTitleCase(firstChar)}, 0, 1) +
word.substring(Character.offsetByCodePoints(word, 0, 1)); word.substring(Character.offsetByCodePoints(word, 0, 1));
} }
} }
return word; return word;

@ -26,6 +26,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package atlantafx.base.controls; package atlantafx.base.controls;
import static java.util.Objects.requireNonNull; import static java.util.Objects.requireNonNull;
@ -179,7 +180,6 @@ public class Popover extends PopupControl {
* Returns the value of the content property * Returns the value of the content property
* *
* @return the content node * @return the content node
*
* @see #contentNodeProperty() * @see #contentNodeProperty()
*/ */
public final Node getContentNode() { public final Node getContentNode() {
@ -190,7 +190,6 @@ public class Popover extends PopupControl {
* Sets the value of the content property. * Sets the value of the content property.
* *
* @param content the new content node value * @param content the new content node value
*
* @see #contentNodeProperty() * @see #contentNodeProperty()
*/ */
public final void setContentNode(Node content) { public final void setContentNode(Node content) {
@ -224,7 +223,7 @@ public class Popover extends PopupControl {
private Window ownerWindow; private Window ownerWindow;
private final EventHandler<WindowEvent> closePopoverOnOwnerWindowCloseLambda = event -> ownerWindowHiding(); private final EventHandler<WindowEvent> closePopoverOnOwnerWindowCloseLambda = event -> ownerWindowHiding();
private final WeakEventHandler<WindowEvent> closePopoverOnOwnerWindowClose = private final WeakEventHandler<WindowEvent> closePopoverOnOwnerWindowClose =
new WeakEventHandler<>(closePopoverOnOwnerWindowCloseLambda); new WeakEventHandler<>(closePopoverOnOwnerWindowCloseLambda);
/** /**
* Shows the popover in a position relative to the edges of the given owner * Shows the popover in a position relative to the edges of the given owner
@ -247,10 +246,10 @@ public class Popover extends PopupControl {
* given owner. If the arrow points up then the popover will be placed * given owner. If the arrow points up then the popover will be placed
* below the given owner node. * below the given owner node.
* *
* @param owner the owner of the popover * @param owner the owner of the popover
* @param offset if negative specifies the distance to the owner node or when * @param offset if negative specifies the distance to the owner node or when
* positive specifies the number of pixels that the arrow will * positive specifies the number of pixels that the arrow will
* overlap with the owner node (positive values are recommended) * overlap with the owner node (positive values are recommended)
*/ */
public final void show(Node owner, double offset) { public final void show(Node owner, double offset) {
requireNonNull(owner); requireNonNull(owner);
@ -259,16 +258,16 @@ public class Popover extends PopupControl {
switch (getArrowLocation()) { switch (getArrowLocation()) {
case BOTTOM_CENTER, BOTTOM_LEFT, BOTTOM_RIGHT -> show( case BOTTOM_CENTER, BOTTOM_LEFT, BOTTOM_RIGHT -> show(
owner, bounds.getMinX() + bounds.getWidth() / 2, bounds.getMinY() + offset owner, bounds.getMinX() + bounds.getWidth() / 2, bounds.getMinY() + offset
); );
case LEFT_BOTTOM, LEFT_CENTER, LEFT_TOP -> show( case LEFT_BOTTOM, LEFT_CENTER, LEFT_TOP -> show(
owner, bounds.getMaxX() - offset, bounds.getMinY() + bounds.getHeight() / 2 owner, bounds.getMaxX() - offset, bounds.getMinY() + bounds.getHeight() / 2
); );
case RIGHT_BOTTOM, RIGHT_CENTER, RIGHT_TOP -> show( case RIGHT_BOTTOM, RIGHT_CENTER, RIGHT_TOP -> show(
owner, bounds.getMinX() + offset, bounds.getMinY() + bounds.getHeight() / 2 owner, bounds.getMinX() + offset, bounds.getMinY() + bounds.getHeight() / 2
); );
case TOP_CENTER, TOP_LEFT, TOP_RIGHT -> show( case TOP_CENTER, TOP_LEFT, TOP_RIGHT -> show(
owner, bounds.getMinX() + bounds.getWidth() / 2, bounds.getMinY() + bounds.getHeight() - offset owner, bounds.getMinX() + bounds.getWidth() / 2, bounds.getMinY() + bounds.getHeight() - offset
); );
} }
} }
@ -309,8 +308,8 @@ public class Popover extends PopupControl {
* of the arrow of the popover and not the location of the window. * of the arrow of the popover and not the location of the window.
* *
* @param owner the owning node * @param owner the owning node
* @param x the x coordinate for the popover arrow tip * @param x the x coordinate for the popover arrow tip
* @param y the y coordinate for the popover arrow tip * @param y the y coordinate for the popover arrow tip
*/ */
@Override @Override
public final void show(Node owner, double x, double y) { public final void show(Node owner, double x, double y) {
@ -322,11 +321,11 @@ public class Popover extends PopupControl {
* the given owner node. The x and y coordinate will be the target location * the given owner node. The x and y coordinate will be the target location
* of the arrow of the popover and not the location of the window. * of the arrow of the popover and not the location of the window.
* *
* @param owner the owning node * @param owner the owning node
* @param x the x coordinate for the popover arrow tip * @param x the x coordinate for the popover arrow tip
* @param y the y coordinate for the popover arrow tip * @param y the y coordinate for the popover arrow tip
* @param fadeInDuration the time it takes for the popover to be fully visible. * @param fadeInDuration the time it takes for the popover to be fully visible.
* This duration takes precedence over the fade-in property without setting. * This duration takes precedence over the fade-in property without setting.
*/ */
public final void show(Node owner, double x, double y, Duration fadeInDuration) { public final void show(Node owner, double x, double y, Duration fadeInDuration) {
/* /*
@ -379,7 +378,8 @@ public class Popover extends PopupControl {
// due to JavaFX async nature. The only way seems to start popover as invisible (not opaque) // due to JavaFX async nature. The only way seems to start popover as invisible (not opaque)
// and then restore its visibility after a fixed delay to hide window repositioning. // and then restore its visibility after a fixed delay to hide window repositioning.
// Still it's not a 100% guarantee,but better than nothing. // Still it's not a 100% guarantee,but better than nothing.
int delay = Math.min((int) Objects.requireNonNullElse(fadeInDuration, DEFAULT_FADE_DURATION).toMillis() / 2, 250); int delay =
Math.min((int) Objects.requireNonNullElse(fadeInDuration, DEFAULT_FADE_DURATION).toMillis() / 2, 250);
new Timer().schedule(new TimerTask() { new Timer().schedule(new TimerTask() {
@Override @Override
public void run() { public void run() {
@ -430,7 +430,7 @@ public class Popover extends PopupControl {
* Hides the popover by quickly changing its opacity to 0. * Hides the popover by quickly changing its opacity to 0.
* *
* @param fadeOutDuration the duration of the fade transition that is being used to * @param fadeOutDuration the duration of the fade transition that is being used to
* change the opacity of the popover * change the opacity of the popover
*/ */
public final void hide(Duration fadeOutDuration) { public final void hide(Duration fadeOutDuration) {
if (fadeOutDuration == null) { if (fadeOutDuration == null) {
@ -479,13 +479,13 @@ public class Popover extends PopupControl {
private double computeXOffset() { private double computeXOffset() {
return switch (getArrowLocation()) { return switch (getArrowLocation()) {
case TOP_LEFT, BOTTOM_LEFT -> ( case TOP_LEFT, BOTTOM_LEFT -> (
getCornerRadius() + getArrowIndent() + getArrowSize() getCornerRadius() + getArrowIndent() + getArrowSize()
); );
case TOP_CENTER, BOTTOM_CENTER -> ( case TOP_CENTER, BOTTOM_CENTER -> (
getContentNode().prefWidth(-1) / 2 getContentNode().prefWidth(-1) / 2
); );
case TOP_RIGHT, BOTTOM_RIGHT -> ( case TOP_RIGHT, BOTTOM_RIGHT -> (
getContentNode().prefWidth(-1) - getArrowIndent() - getCornerRadius() - getArrowSize() getContentNode().prefWidth(-1) - getArrowIndent() - getCornerRadius() - getArrowSize()
); );
default -> 0; default -> 0;
}; };
@ -497,11 +497,11 @@ public class Popover extends PopupControl {
return switch (getArrowLocation()) { return switch (getArrowLocation()) {
case LEFT_TOP, RIGHT_TOP -> getCornerRadius() + getArrowIndent() + getArrowSize(); case LEFT_TOP, RIGHT_TOP -> getCornerRadius() + getArrowIndent() + getArrowSize();
case LEFT_CENTER, RIGHT_CENTER -> Math.max( case LEFT_CENTER, RIGHT_CENTER -> Math.max(
prefContentHeight, 2 * (getCornerRadius() + getArrowIndent() + getArrowSize()) prefContentHeight, 2 * (getCornerRadius() + getArrowIndent() + getArrowSize())
) / 2; ) / 2;
case LEFT_BOTTOM, RIGHT_BOTTOM -> Math.max( case LEFT_BOTTOM, RIGHT_BOTTOM -> Math.max(
prefContentHeight - getCornerRadius() - getArrowIndent() - getArrowSize(), prefContentHeight - getCornerRadius() - getArrowIndent() - getArrowSize(),
getCornerRadius() + getArrowIndent() + getArrowSize() getCornerRadius() + getArrowIndent() + getArrowSize()
); );
default -> 0; default -> 0;
}; };
@ -531,7 +531,6 @@ public class Popover extends PopupControl {
* Sets the value of the headerAlwaysVisible property. * Sets the value of the headerAlwaysVisible property.
* *
* @param visible if true, then the header is visible even while attached * @param visible if true, then the header is visible even while attached
*
* @see #headerAlwaysVisibleProperty() * @see #headerAlwaysVisibleProperty()
*/ */
public final void setHeaderAlwaysVisible(boolean visible) { public final void setHeaderAlwaysVisible(boolean visible) {
@ -542,7 +541,6 @@ public class Popover extends PopupControl {
* Returns the value of the detachable property. * Returns the value of the detachable property.
* *
* @return true if the header is visible even while attached * @return true if the header is visible even while attached
*
* @see #headerAlwaysVisibleProperty() * @see #headerAlwaysVisibleProperty()
*/ */
public final boolean isHeaderAlwaysVisible() { public final boolean isHeaderAlwaysVisible() {
@ -562,7 +560,6 @@ public class Popover extends PopupControl {
* Sets the value of the closeButtonEnabled property. * Sets the value of the closeButtonEnabled property.
* *
* @param enabled if false, the popover will not be closeable by the header's close button * @param enabled if false, the popover will not be closeable by the header's close button
*
* @see #closeButtonEnabledProperty() * @see #closeButtonEnabledProperty()
*/ */
public final void setCloseButtonEnabled(boolean enabled) { public final void setCloseButtonEnabled(boolean enabled) {
@ -573,7 +570,6 @@ public class Popover extends PopupControl {
* Returns the value of the closeButtonEnabled property. * Returns the value of the closeButtonEnabled property.
* *
* @return true if the header's close button is enabled * @return true if the header's close button is enabled
*
* @see #closeButtonEnabledProperty() * @see #closeButtonEnabledProperty()
*/ */
public final boolean isCloseButtonEnabled() { public final boolean isCloseButtonEnabled() {
@ -593,7 +589,6 @@ public class Popover extends PopupControl {
* Sets the value of the detachable property. * Sets the value of the detachable property.
* *
* @param detachable if true then the user can detach / tear off the popover * @param detachable if true then the user can detach / tear off the popover
*
* @see #detachableProperty() * @see #detachableProperty()
*/ */
public final void setDetachable(boolean detachable) { public final void setDetachable(boolean detachable) {
@ -604,7 +599,6 @@ public class Popover extends PopupControl {
* Returns the value of the detachable property. * Returns the value of the detachable property.
* *
* @return true if the user is allowed to detach / tear off the popover * @return true if the user is allowed to detach / tear off the popover
*
* @see #detachableProperty() * @see #detachableProperty()
*/ */
public final boolean isDetachable() { public final boolean isDetachable() {
@ -628,8 +622,7 @@ public class Popover extends PopupControl {
* Sets the value of the detached property. * Sets the value of the detached property.
* *
* @param detached if true the popover will change its appearance to "detached" * @param detached if true the popover will change its appearance to "detached"
* mode * mode
*
* @see #detachedProperty() * @see #detachedProperty()
*/ */
public final void setDetached(boolean detached) { public final void setDetached(boolean detached) {
@ -640,7 +633,6 @@ public class Popover extends PopupControl {
* Returns the value of the detached property. * Returns the value of the detached property.
* *
* @return true if the popover is currently detached. * @return true if the popover is currently detached.
*
* @see #detachedProperty() * @see #detachedProperty()
*/ */
public final boolean isDetached() { public final boolean isDetached() {
@ -662,7 +654,6 @@ public class Popover extends PopupControl {
* Returns the value of the arrow size property. * Returns the value of the arrow size property.
* *
* @return the arrow size property value * @return the arrow size property value
*
* @see #arrowSizeProperty() * @see #arrowSizeProperty()
*/ */
public final double getArrowSize() { public final double getArrowSize() {
@ -673,7 +664,6 @@ public class Popover extends PopupControl {
* Sets the value of the arrow size property. * Sets the value of the arrow size property.
* *
* @param size the new value of the arrow size property * @param size the new value of the arrow size property
*
* @see #arrowSizeProperty() * @see #arrowSizeProperty()
*/ */
public final void setArrowSize(double size) { public final void setArrowSize(double size) {
@ -696,7 +686,6 @@ public class Popover extends PopupControl {
* Returns the value of the arrow indent property. * Returns the value of the arrow indent property.
* *
* @return the arrow indent value * @return the arrow indent value
*
* @see #arrowIndentProperty() * @see #arrowIndentProperty()
*/ */
public final double getArrowIndent() { public final double getArrowIndent() {
@ -707,7 +696,6 @@ public class Popover extends PopupControl {
* Sets the value of the arrow indent property. * Sets the value of the arrow indent property.
* *
* @param size the arrow indent value * @param size the arrow indent value
*
* @see #arrowIndentProperty() * @see #arrowIndentProperty()
*/ */
public final void setArrowIndent(double size) { public final void setArrowIndent(double size) {
@ -729,7 +717,6 @@ public class Popover extends PopupControl {
* Returns the value of the corner radius property. * Returns the value of the corner radius property.
* *
* @return the corner radius * @return the corner radius
*
* @see #cornerRadiusProperty() * @see #cornerRadiusProperty()
*/ */
public final double getCornerRadius() { public final double getCornerRadius() {
@ -740,7 +727,6 @@ public class Popover extends PopupControl {
* Sets the value of the corner radius property. * Sets the value of the corner radius property.
* *
* @param radius the corner radius * @param radius the corner radius
*
* @see #cornerRadiusProperty() * @see #cornerRadiusProperty()
*/ */
public final void setCornerRadius(double radius) { public final void setCornerRadius(double radius) {
@ -762,7 +748,6 @@ public class Popover extends PopupControl {
* Returns the value of the title property. * Returns the value of the title property.
* *
* @return the detached title * @return the detached title
*
* @see #titleProperty() * @see #titleProperty()
*/ */
public final String getTitle() { public final String getTitle() {
@ -773,7 +758,6 @@ public class Popover extends PopupControl {
* Sets the value of the title property. * Sets the value of the title property.
* *
* @param title the title to use when detached * @param title the title to use when detached
*
* @see #titleProperty() * @see #titleProperty()
*/ */
public final void setTitle(String title) { public final void setTitle(String title) {
@ -783,14 +767,14 @@ public class Popover extends PopupControl {
titleProperty().set(title); titleProperty().set(title);
} }
private final ObjectProperty<ArrowLocation> arrowLocation = new SimpleObjectProperty<>(this, "arrowLocation", ArrowLocation.LEFT_TOP); private final ObjectProperty<ArrowLocation> arrowLocation =
new SimpleObjectProperty<>(this, "arrowLocation", ArrowLocation.LEFT_TOP);
/** /**
* Stores the preferred arrow location. This might not be the actual * Stores the preferred arrow location. This might not be the actual
* location of the arrow if auto fix is enabled. * location of the arrow if auto fix is enabled.
* *
* @return the arrow location property * @return the arrow location property
*
* @see #setAutoFix(boolean) * @see #setAutoFix(boolean)
*/ */
public final ObjectProperty<ArrowLocation> arrowLocationProperty() { public final ObjectProperty<ArrowLocation> arrowLocationProperty() {
@ -801,7 +785,6 @@ public class Popover extends PopupControl {
* Sets the value of the arrow location property. * Sets the value of the arrow location property.
* *
* @param location the requested location * @param location the requested location
*
* @see #arrowLocationProperty() * @see #arrowLocationProperty()
*/ */
public final void setArrowLocation(ArrowLocation location) { public final void setArrowLocation(ArrowLocation location) {
@ -812,7 +795,6 @@ public class Popover extends PopupControl {
* Returns the value of the arrow location property. * Returns the value of the arrow location property.
* *
* @return the preferred arrow location * @return the preferred arrow location
*
* @see #arrowLocationProperty() * @see #arrowLocationProperty()
*/ */
public final ArrowLocation getArrowLocation() { public final ArrowLocation getArrowLocation() {
@ -859,7 +841,6 @@ public class Popover extends PopupControl {
* Returns the value of the fade-in duration property. * Returns the value of the fade-in duration property.
* *
* @return the fade-in duration * @return the fade-in duration
*
* @see #fadeInDurationProperty() * @see #fadeInDurationProperty()
*/ */
public final Duration getFadeInDuration() { public final Duration getFadeInDuration() {
@ -871,7 +852,6 @@ public class Popover extends PopupControl {
* Popover.show(..). * Popover.show(..).
* *
* @param duration the requested fade-in duration * @param duration the requested fade-in duration
*
* @see #fadeInDurationProperty() * @see #fadeInDurationProperty()
*/ */
public final void setFadeInDuration(Duration duration) { public final void setFadeInDuration(Duration duration) {
@ -882,7 +862,6 @@ public class Popover extends PopupControl {
* Returns the value of the fade-out duration property. * Returns the value of the fade-out duration property.
* *
* @return the fade-out duration * @return the fade-out duration
*
* @see #fadeOutDurationProperty() * @see #fadeOutDurationProperty()
*/ */
public final Duration getFadeOutDuration() { public final Duration getFadeOutDuration() {
@ -893,7 +872,6 @@ public class Popover extends PopupControl {
* Sets the value of the fade-out duration property. * Sets the value of the fade-out duration property.
* *
* @param duration the requested fade-out duration * @param duration the requested fade-out duration
*
* @see #fadeOutDurationProperty() * @see #fadeOutDurationProperty()
*/ */
public final void setFadeOutDuration(Duration duration) { public final void setFadeOutDuration(Duration duration) {
@ -914,7 +892,6 @@ public class Popover extends PopupControl {
* Returns the value of the "animated" property. * Returns the value of the "animated" property.
* *
* @return true if the Popover will be shown and hidden with a short fade animation * @return true if the Popover will be shown and hidden with a short fade animation
*
* @see #animatedProperty() * @see #animatedProperty()
*/ */
public final boolean isAnimated() { public final boolean isAnimated() {
@ -925,7 +902,6 @@ public class Popover extends PopupControl {
* Sets the value of the "animated" property. * Sets the value of the "animated" property.
* *
* @param animated if true the Popover will be shown and hidden with a short fade animation * @param animated if true the Popover will be shown and hidden with a short fade animation
*
* @see #animatedProperty() * @see #animatedProperty()
*/ */
public final void setAnimated(boolean animated) { public final void setAnimated(boolean animated) {

@ -26,6 +26,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package atlantafx.base.controls; package atlantafx.base.controls;
import static atlantafx.base.controls.Popover.ArrowLocation; import static atlantafx.base.controls.Popover.ArrowLocation;
@ -90,12 +91,12 @@ public class PopoverSkin implements Skin<Popover> {
// the min width and height equal (2 * corner radius + 2 * arrow indent + 2 * arrow size) // the min width and height equal (2 * corner radius + 2 * arrow indent + 2 * arrow size)
stackPane.minWidthProperty().bind( stackPane.minWidthProperty().bind(
Bindings.add(Bindings.multiply(2, popover.arrowSizeProperty()), Bindings.add(Bindings.multiply(2, popover.arrowSizeProperty()),
Bindings.add( Bindings.add(
Bindings.multiply(2, popover.cornerRadiusProperty()), Bindings.multiply(2, popover.cornerRadiusProperty()),
Bindings.multiply(2, popover.arrowIndentProperty()) Bindings.multiply(2, popover.arrowIndentProperty())
)
) )
)
); );
stackPane.minHeightProperty().bind(stackPane.minWidthProperty()); stackPane.minHeightProperty().bind(stackPane.minWidthProperty());
@ -111,8 +112,8 @@ public class PopoverSkin implements Skin<Popover> {
closeIcon.setMaxSize(MAX_VALUE, MAX_VALUE); closeIcon.setMaxSize(MAX_VALUE, MAX_VALUE);
closeIcon.setContentDisplay(GRAPHIC_ONLY); closeIcon.setContentDisplay(GRAPHIC_ONLY);
closeIcon.visibleProperty().bind( closeIcon.visibleProperty().bind(
popover.closeButtonEnabledProperty().and( popover.closeButtonEnabledProperty().and(
popover.detachedProperty().or(popover.headerAlwaysVisibleProperty()))); popover.detachedProperty().or(popover.headerAlwaysVisibleProperty())));
closeIcon.getStyleClass().add("icon"); closeIcon.getStyleClass().add("icon");
closeIcon.setAlignment(TOP_RIGHT); closeIcon.setAlignment(TOP_RIGHT);
closeIcon.getGraphic().setOnMouseClicked(evt -> popover.hide()); closeIcon.getGraphic().setOnMouseClicked(evt -> popover.hide());
@ -156,10 +157,10 @@ public class PopoverSkin implements Skin<Popover> {
switch (getSkinnable().getArrowLocation()) { switch (getSkinnable().getArrowLocation()) {
case LEFT_TOP, LEFT_CENTER, LEFT_BOTTOM -> popover.setAnchorX( case LEFT_TOP, LEFT_CENTER, LEFT_BOTTOM -> popover.setAnchorX(
popover.getAnchorX() + popover.getArrowSize() popover.getAnchorX() + popover.getArrowSize()
); );
case TOP_LEFT, TOP_CENTER, TOP_RIGHT -> popover.setAnchorY( case TOP_LEFT, TOP_CENTER, TOP_RIGHT -> popover.setAnchorY(
popover.getAnchorY() + popover.getArrowSize() popover.getAnchorY() + popover.getArrowSize()
); );
} }
} else { } else {
@ -252,7 +253,8 @@ public class PopoverSkin implements Skin<Popover> {
} }
@Override @Override
public void dispose() { } public void dispose() {
}
private Node createCloseIcon() { private Node createCloseIcon() {
Group group = new Group(); Group group = new Group();
@ -293,15 +295,15 @@ public class PopoverSkin implements Skin<Popover> {
private VLineTo lineBRight, lineERight, lineHRight, lineKRight; private VLineTo lineBRight, lineERight, lineHRight, lineKRight;
private LineTo lineCRight, lineDRight, lineFRight, lineGRight, lineIRight, private LineTo lineCRight, lineDRight, lineFRight, lineGRight, lineIRight,
lineJRight; lineJRight;
private HLineTo lineBBottom, lineEBottom, lineHBottom, lineKBottom; private HLineTo lineBBottom, lineEBottom, lineHBottom, lineKBottom;
private LineTo lineCBottom, lineDBottom, lineFBottom, lineGBottom, private LineTo lineCBottom, lineDBottom, lineFBottom, lineGBottom,
lineIBottom, lineJBottom; lineIBottom, lineJBottom;
private VLineTo lineBLeft, lineELeft, lineHLeft, lineKLeft; private VLineTo lineBLeft, lineELeft, lineHLeft, lineKLeft;
private LineTo lineCLeft, lineDLeft, lineFLeft, lineGLeft, lineILeft, private LineTo lineCLeft, lineDLeft, lineFLeft, lineGLeft, lineILeft,
lineJLeft; lineJLeft;
private void createPathElements() { private void createPathElements() {
DoubleProperty centerYProperty = new SimpleDoubleProperty(); DoubleProperty centerYProperty = new SimpleDoubleProperty();
@ -323,24 +325,24 @@ public class PopoverSkin implements Skin<Popover> {
DoubleProperty arrowSizeProperty = getSkinnable().arrowSizeProperty(); DoubleProperty arrowSizeProperty = getSkinnable().arrowSizeProperty();
DoubleProperty arrowIndentProperty = getSkinnable() DoubleProperty arrowIndentProperty = getSkinnable()
.arrowIndentProperty(); .arrowIndentProperty();
centerYProperty.bind(Bindings.divide(stackPane.heightProperty(), 2)); centerYProperty.bind(Bindings.divide(stackPane.heightProperty(), 2));
centerXProperty.bind(Bindings.divide(stackPane.widthProperty(), 2)); centerXProperty.bind(Bindings.divide(stackPane.widthProperty(), 2));
leftEdgePlusRadiusProperty.bind(Bindings.add(leftEdgeProperty, leftEdgePlusRadiusProperty.bind(Bindings.add(leftEdgeProperty,
getSkinnable().cornerRadiusProperty())); getSkinnable().cornerRadiusProperty()));
topEdgePlusRadiusProperty.bind(Bindings.add(topEdgeProperty, topEdgePlusRadiusProperty.bind(Bindings.add(topEdgeProperty,
getSkinnable().cornerRadiusProperty())); getSkinnable().cornerRadiusProperty()));
rightEdgeProperty.bind(stackPane.widthProperty()); rightEdgeProperty.bind(stackPane.widthProperty());
rightEdgeMinusRadiusProperty.bind(Bindings.subtract(rightEdgeProperty, rightEdgeMinusRadiusProperty.bind(Bindings.subtract(rightEdgeProperty,
getSkinnable().cornerRadiusProperty())); getSkinnable().cornerRadiusProperty()));
bottomEdgeProperty.bind(stackPane.heightProperty()); bottomEdgeProperty.bind(stackPane.heightProperty());
bottomEdgeMinusRadiusProperty.bind(Bindings.subtract( bottomEdgeMinusRadiusProperty.bind(Bindings.subtract(
bottomEdgeProperty, getSkinnable().cornerRadiusProperty())); bottomEdgeProperty, getSkinnable().cornerRadiusProperty()));
// == INIT == // == INIT ==
moveTo = new MoveTo(); moveTo = new MoveTo();
@ -350,51 +352,51 @@ public class PopoverSkin implements Skin<Popover> {
// == TOP EDGE == // == TOP EDGE ==
lineBTop = new HLineTo(); lineBTop = new HLineTo();
lineBTop.xProperty().bind( lineBTop.xProperty().bind(
Bindings.add(leftEdgePlusRadiusProperty, arrowIndentProperty)); Bindings.add(leftEdgePlusRadiusProperty, arrowIndentProperty));
lineCTop = new LineTo(); lineCTop = new LineTo();
lineCTop.xProperty().bind( lineCTop.xProperty().bind(
Bindings.add(lineBTop.xProperty(), arrowSizeProperty)); Bindings.add(lineBTop.xProperty(), arrowSizeProperty));
lineCTop.yProperty().bind( lineCTop.yProperty().bind(
Bindings.subtract(topEdgeProperty, arrowSizeProperty)); Bindings.subtract(topEdgeProperty, arrowSizeProperty));
lineDTop = new LineTo(); lineDTop = new LineTo();
lineDTop.xProperty().bind( lineDTop.xProperty().bind(
Bindings.add(lineCTop.xProperty(), arrowSizeProperty)); Bindings.add(lineCTop.xProperty(), arrowSizeProperty));
lineDTop.yProperty().bind(topEdgeProperty); lineDTop.yProperty().bind(topEdgeProperty);
lineETop = new HLineTo(); lineETop = new HLineTo();
lineETop.xProperty().bind( lineETop.xProperty().bind(
Bindings.subtract(centerXProperty, arrowSizeProperty)); Bindings.subtract(centerXProperty, arrowSizeProperty));
lineFTop = new LineTo(); lineFTop = new LineTo();
lineFTop.xProperty().bind(centerXProperty); lineFTop.xProperty().bind(centerXProperty);
lineFTop.yProperty().bind( lineFTop.yProperty().bind(
Bindings.subtract(topEdgeProperty, arrowSizeProperty)); Bindings.subtract(topEdgeProperty, arrowSizeProperty));
lineGTop = new LineTo(); lineGTop = new LineTo();
lineGTop.xProperty().bind( lineGTop.xProperty().bind(
Bindings.add(centerXProperty, arrowSizeProperty)); Bindings.add(centerXProperty, arrowSizeProperty));
lineGTop.yProperty().bind(topEdgeProperty); lineGTop.yProperty().bind(topEdgeProperty);
lineHTop = new HLineTo(); lineHTop = new HLineTo();
lineHTop.xProperty().bind( lineHTop.xProperty().bind(
Bindings.subtract(Bindings.subtract( Bindings.subtract(Bindings.subtract(
rightEdgeMinusRadiusProperty, arrowIndentProperty), rightEdgeMinusRadiusProperty, arrowIndentProperty),
Bindings.multiply(arrowSizeProperty, 2))); Bindings.multiply(arrowSizeProperty, 2)));
lineITop = new LineTo(); lineITop = new LineTo();
lineITop.xProperty().bind( lineITop.xProperty().bind(
Bindings.subtract(Bindings.subtract( Bindings.subtract(Bindings.subtract(
rightEdgeMinusRadiusProperty, arrowIndentProperty), rightEdgeMinusRadiusProperty, arrowIndentProperty),
arrowSizeProperty)); arrowSizeProperty));
lineITop.yProperty().bind( lineITop.yProperty().bind(
Bindings.subtract(topEdgeProperty, arrowSizeProperty)); Bindings.subtract(topEdgeProperty, arrowSizeProperty));
lineJTop = new LineTo(); lineJTop = new LineTo();
lineJTop.xProperty().bind( lineJTop.xProperty().bind(
Bindings.subtract(rightEdgeMinusRadiusProperty, Bindings.subtract(rightEdgeMinusRadiusProperty,
arrowIndentProperty)); arrowIndentProperty));
lineJTop.yProperty().bind(topEdgeProperty); lineJTop.yProperty().bind(topEdgeProperty);
lineKTop = new HLineTo(); lineKTop = new HLineTo();
@ -404,58 +406,58 @@ public class PopoverSkin implements Skin<Popover> {
rightCurveTo = new QuadCurveTo(); rightCurveTo = new QuadCurveTo();
rightCurveTo.xProperty().bind(rightEdgeProperty); rightCurveTo.xProperty().bind(rightEdgeProperty);
rightCurveTo.yProperty().bind( rightCurveTo.yProperty().bind(
Bindings.add(topEdgeProperty, cornerProperty)); Bindings.add(topEdgeProperty, cornerProperty));
rightCurveTo.controlXProperty().bind(rightEdgeProperty); rightCurveTo.controlXProperty().bind(rightEdgeProperty);
rightCurveTo.controlYProperty().bind(topEdgeProperty); rightCurveTo.controlYProperty().bind(topEdgeProperty);
lineBRight = new VLineTo(); lineBRight = new VLineTo();
lineBRight.yProperty().bind( lineBRight.yProperty().bind(
Bindings.add(topEdgePlusRadiusProperty, arrowIndentProperty)); Bindings.add(topEdgePlusRadiusProperty, arrowIndentProperty));
lineCRight = new LineTo(); lineCRight = new LineTo();
lineCRight.xProperty().bind( lineCRight.xProperty().bind(
Bindings.add(rightEdgeProperty, arrowSizeProperty)); Bindings.add(rightEdgeProperty, arrowSizeProperty));
lineCRight.yProperty().bind( lineCRight.yProperty().bind(
Bindings.add(lineBRight.yProperty(), arrowSizeProperty)); Bindings.add(lineBRight.yProperty(), arrowSizeProperty));
lineDRight = new LineTo(); lineDRight = new LineTo();
lineDRight.xProperty().bind(rightEdgeProperty); lineDRight.xProperty().bind(rightEdgeProperty);
lineDRight.yProperty().bind( lineDRight.yProperty().bind(
Bindings.add(lineCRight.yProperty(), arrowSizeProperty)); Bindings.add(lineCRight.yProperty(), arrowSizeProperty));
lineERight = new VLineTo(); lineERight = new VLineTo();
lineERight.yProperty().bind( lineERight.yProperty().bind(
Bindings.subtract(centerYProperty, arrowSizeProperty)); Bindings.subtract(centerYProperty, arrowSizeProperty));
lineFRight = new LineTo(); lineFRight = new LineTo();
lineFRight.xProperty().bind( lineFRight.xProperty().bind(
Bindings.add(rightEdgeProperty, arrowSizeProperty)); Bindings.add(rightEdgeProperty, arrowSizeProperty));
lineFRight.yProperty().bind(centerYProperty); lineFRight.yProperty().bind(centerYProperty);
lineGRight = new LineTo(); lineGRight = new LineTo();
lineGRight.xProperty().bind(rightEdgeProperty); lineGRight.xProperty().bind(rightEdgeProperty);
lineGRight.yProperty().bind( lineGRight.yProperty().bind(
Bindings.add(centerYProperty, arrowSizeProperty)); Bindings.add(centerYProperty, arrowSizeProperty));
lineHRight = new VLineTo(); lineHRight = new VLineTo();
lineHRight.yProperty().bind( lineHRight.yProperty().bind(
Bindings.subtract(Bindings.subtract( Bindings.subtract(Bindings.subtract(
bottomEdgeMinusRadiusProperty, arrowIndentProperty), bottomEdgeMinusRadiusProperty, arrowIndentProperty),
Bindings.multiply(arrowSizeProperty, 2))); Bindings.multiply(arrowSizeProperty, 2)));
lineIRight = new LineTo(); lineIRight = new LineTo();
lineIRight.xProperty().bind( lineIRight.xProperty().bind(
Bindings.add(rightEdgeProperty, arrowSizeProperty)); Bindings.add(rightEdgeProperty, arrowSizeProperty));
lineIRight.yProperty().bind( lineIRight.yProperty().bind(
Bindings.subtract(Bindings.subtract( Bindings.subtract(Bindings.subtract(
bottomEdgeMinusRadiusProperty, arrowIndentProperty), bottomEdgeMinusRadiusProperty, arrowIndentProperty),
arrowSizeProperty)); arrowSizeProperty));
lineJRight = new LineTo(); lineJRight = new LineTo();
lineJRight.xProperty().bind(rightEdgeProperty); lineJRight.xProperty().bind(rightEdgeProperty);
lineJRight.yProperty().bind( lineJRight.yProperty().bind(
Bindings.subtract(bottomEdgeMinusRadiusProperty, Bindings.subtract(bottomEdgeMinusRadiusProperty,
arrowIndentProperty)); arrowIndentProperty));
lineKRight = new VLineTo(); lineKRight = new VLineTo();
lineKRight.yProperty().bind(bottomEdgeMinusRadiusProperty); lineKRight.yProperty().bind(bottomEdgeMinusRadiusProperty);
@ -469,50 +471,50 @@ public class PopoverSkin implements Skin<Popover> {
lineBBottom = new HLineTo(); lineBBottom = new HLineTo();
lineBBottom.xProperty().bind( lineBBottom.xProperty().bind(
Bindings.subtract(rightEdgeMinusRadiusProperty, Bindings.subtract(rightEdgeMinusRadiusProperty,
arrowIndentProperty)); arrowIndentProperty));
lineCBottom = new LineTo(); lineCBottom = new LineTo();
lineCBottom.xProperty().bind( lineCBottom.xProperty().bind(
Bindings.subtract(lineBBottom.xProperty(), arrowSizeProperty)); Bindings.subtract(lineBBottom.xProperty(), arrowSizeProperty));
lineCBottom.yProperty().bind( lineCBottom.yProperty().bind(
Bindings.add(bottomEdgeProperty, arrowSizeProperty)); Bindings.add(bottomEdgeProperty, arrowSizeProperty));
lineDBottom = new LineTo(); lineDBottom = new LineTo();
lineDBottom.xProperty().bind( lineDBottom.xProperty().bind(
Bindings.subtract(lineCBottom.xProperty(), arrowSizeProperty)); Bindings.subtract(lineCBottom.xProperty(), arrowSizeProperty));
lineDBottom.yProperty().bind(bottomEdgeProperty); lineDBottom.yProperty().bind(bottomEdgeProperty);
lineEBottom = new HLineTo(); lineEBottom = new HLineTo();
lineEBottom.xProperty().bind( lineEBottom.xProperty().bind(
Bindings.add(centerXProperty, arrowSizeProperty)); Bindings.add(centerXProperty, arrowSizeProperty));
lineFBottom = new LineTo(); lineFBottom = new LineTo();
lineFBottom.xProperty().bind(centerXProperty); lineFBottom.xProperty().bind(centerXProperty);
lineFBottom.yProperty().bind( lineFBottom.yProperty().bind(
Bindings.add(bottomEdgeProperty, arrowSizeProperty)); Bindings.add(bottomEdgeProperty, arrowSizeProperty));
lineGBottom = new LineTo(); lineGBottom = new LineTo();
lineGBottom.xProperty().bind( lineGBottom.xProperty().bind(
Bindings.subtract(centerXProperty, arrowSizeProperty)); Bindings.subtract(centerXProperty, arrowSizeProperty));
lineGBottom.yProperty().bind(bottomEdgeProperty); lineGBottom.yProperty().bind(bottomEdgeProperty);
lineHBottom = new HLineTo(); lineHBottom = new HLineTo();
lineHBottom.xProperty().bind( lineHBottom.xProperty().bind(
Bindings.add(Bindings.add(leftEdgePlusRadiusProperty, Bindings.add(Bindings.add(leftEdgePlusRadiusProperty,
arrowIndentProperty), Bindings.multiply( arrowIndentProperty), Bindings.multiply(
arrowSizeProperty, 2))); arrowSizeProperty, 2)));
lineIBottom = new LineTo(); lineIBottom = new LineTo();
lineIBottom.xProperty().bind( lineIBottom.xProperty().bind(
Bindings.add(Bindings.add(leftEdgePlusRadiusProperty, Bindings.add(Bindings.add(leftEdgePlusRadiusProperty,
arrowIndentProperty), arrowSizeProperty)); arrowIndentProperty), arrowSizeProperty));
lineIBottom.yProperty().bind( lineIBottom.yProperty().bind(
Bindings.add(bottomEdgeProperty, arrowSizeProperty)); Bindings.add(bottomEdgeProperty, arrowSizeProperty));
lineJBottom = new LineTo(); lineJBottom = new LineTo();
lineJBottom.xProperty().bind( lineJBottom.xProperty().bind(
Bindings.add(leftEdgePlusRadiusProperty, arrowIndentProperty)); Bindings.add(leftEdgePlusRadiusProperty, arrowIndentProperty));
lineJBottom.yProperty().bind(bottomEdgeProperty); lineJBottom.yProperty().bind(bottomEdgeProperty);
lineKBottom = new HLineTo(); lineKBottom = new HLineTo();
@ -522,57 +524,57 @@ public class PopoverSkin implements Skin<Popover> {
leftCurveTo = new QuadCurveTo(); leftCurveTo = new QuadCurveTo();
leftCurveTo.xProperty().bind(leftEdgeProperty); leftCurveTo.xProperty().bind(leftEdgeProperty);
leftCurveTo.yProperty().bind( leftCurveTo.yProperty().bind(
Bindings.subtract(bottomEdgeProperty, cornerProperty)); Bindings.subtract(bottomEdgeProperty, cornerProperty));
leftCurveTo.controlXProperty().bind(leftEdgeProperty); leftCurveTo.controlXProperty().bind(leftEdgeProperty);
leftCurveTo.controlYProperty().bind(bottomEdgeProperty); leftCurveTo.controlYProperty().bind(bottomEdgeProperty);
lineBLeft = new VLineTo(); lineBLeft = new VLineTo();
lineBLeft.yProperty().bind( lineBLeft.yProperty().bind(
Bindings.subtract(bottomEdgeMinusRadiusProperty, Bindings.subtract(bottomEdgeMinusRadiusProperty,
arrowIndentProperty)); arrowIndentProperty));
lineCLeft = new LineTo(); lineCLeft = new LineTo();
lineCLeft.xProperty().bind( lineCLeft.xProperty().bind(
Bindings.subtract(leftEdgeProperty, arrowSizeProperty)); Bindings.subtract(leftEdgeProperty, arrowSizeProperty));
lineCLeft.yProperty().bind( lineCLeft.yProperty().bind(
Bindings.subtract(lineBLeft.yProperty(), arrowSizeProperty)); Bindings.subtract(lineBLeft.yProperty(), arrowSizeProperty));
lineDLeft = new LineTo(); lineDLeft = new LineTo();
lineDLeft.xProperty().bind(leftEdgeProperty); lineDLeft.xProperty().bind(leftEdgeProperty);
lineDLeft.yProperty().bind( lineDLeft.yProperty().bind(
Bindings.subtract(lineCLeft.yProperty(), arrowSizeProperty)); Bindings.subtract(lineCLeft.yProperty(), arrowSizeProperty));
lineELeft = new VLineTo(); lineELeft = new VLineTo();
lineELeft.yProperty().bind( lineELeft.yProperty().bind(
Bindings.add(centerYProperty, arrowSizeProperty)); Bindings.add(centerYProperty, arrowSizeProperty));
lineFLeft = new LineTo(); lineFLeft = new LineTo();
lineFLeft.xProperty().bind( lineFLeft.xProperty().bind(
Bindings.subtract(leftEdgeProperty, arrowSizeProperty)); Bindings.subtract(leftEdgeProperty, arrowSizeProperty));
lineFLeft.yProperty().bind(centerYProperty); lineFLeft.yProperty().bind(centerYProperty);
lineGLeft = new LineTo(); lineGLeft = new LineTo();
lineGLeft.xProperty().bind(leftEdgeProperty); lineGLeft.xProperty().bind(leftEdgeProperty);
lineGLeft.yProperty().bind( lineGLeft.yProperty().bind(
Bindings.subtract(centerYProperty, arrowSizeProperty)); Bindings.subtract(centerYProperty, arrowSizeProperty));
lineHLeft = new VLineTo(); lineHLeft = new VLineTo();
lineHLeft.yProperty().bind( lineHLeft.yProperty().bind(
Bindings.add(Bindings.add(topEdgePlusRadiusProperty, Bindings.add(Bindings.add(topEdgePlusRadiusProperty,
arrowIndentProperty), Bindings.multiply( arrowIndentProperty), Bindings.multiply(
arrowSizeProperty, 2))); arrowSizeProperty, 2)));
lineILeft = new LineTo(); lineILeft = new LineTo();
lineILeft.xProperty().bind( lineILeft.xProperty().bind(
Bindings.subtract(leftEdgeProperty, arrowSizeProperty)); Bindings.subtract(leftEdgeProperty, arrowSizeProperty));
lineILeft.yProperty().bind( lineILeft.yProperty().bind(
Bindings.add(Bindings.add(topEdgePlusRadiusProperty, Bindings.add(Bindings.add(topEdgePlusRadiusProperty,
arrowIndentProperty), arrowSizeProperty)); arrowIndentProperty), arrowSizeProperty));
lineJLeft = new LineTo(); lineJLeft = new LineTo();
lineJLeft.xProperty().bind(leftEdgeProperty); lineJLeft.xProperty().bind(leftEdgeProperty);
lineJLeft.yProperty().bind( lineJLeft.yProperty().bind(
Bindings.add(topEdgePlusRadiusProperty, arrowIndentProperty)); Bindings.add(topEdgePlusRadiusProperty, arrowIndentProperty));
lineKLeft = new VLineTo(); lineKLeft = new VLineTo();
lineKLeft.yProperty().bind(topEdgePlusRadiusProperty); lineKLeft.yProperty().bind(topEdgePlusRadiusProperty);

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.base.controls; package atlantafx.base.controls;
import javafx.geometry.Orientation; import javafx.geometry.Orientation;
@ -6,7 +7,9 @@ import javafx.scene.control.Slider;
import javafx.scene.control.skin.SliderSkin; import javafx.scene.control.skin.SliderSkin;
import javafx.scene.layout.StackPane; import javafx.scene.layout.StackPane;
/** {@link Slider} skin that supports progress color. */ /**
* {@link Slider} skin that supports progress color.
*/
public class ProgressSliderSkin extends SliderSkin { public class ProgressSliderSkin extends SliderSkin {
protected final StackPane thumb; protected final StackPane thumb;
@ -45,7 +48,8 @@ public class ProgressSliderSkin extends SliderSkin {
} else { } else {
progressY = thumb.getLayoutY(); progressY = thumb.getLayoutY();
progressWidth = track.getWidth(); progressWidth = track.getWidth();
progressHeight = track.getLayoutBounds().getMaxY() + track.getLayoutY() - thumb.getLayoutY() - snappedBottomInset(); progressHeight =
track.getLayoutBounds().getMaxY() + track.getLayoutY() - thumb.getLayoutY() - snappedBottomInset();
} }
progressTrack.resizeRelocate(progressX, progressY, progressWidth, progressHeight); progressTrack.resizeRelocate(progressX, progressY, progressWidth, progressHeight);

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.base.controls; package atlantafx.base.controls;
import javafx.beans.property.ObjectProperty; import javafx.beans.property.ObjectProperty;
@ -12,7 +13,8 @@ import javafx.util.StringConverter;
public class RingProgressIndicator extends ProgressIndicator { public class RingProgressIndicator extends ProgressIndicator {
public RingProgressIndicator() { } public RingProgressIndicator() {
}
public RingProgressIndicator(double progress) { public RingProgressIndicator(double progress) {
this(progress, false); this(progress, false);
@ -52,7 +54,8 @@ public class RingProgressIndicator extends ProgressIndicator {
// ~ // ~
protected final ObjectProperty<StringConverter<Double>> stringConverter = new SimpleObjectProperty<>(this, "converter", null); protected final ObjectProperty<StringConverter<Double>> stringConverter =
new SimpleObjectProperty<>(this, "converter", null);
public StringConverter<Double> getStringConverter() { public StringConverter<Double> getStringConverter() {
return stringConverterProperty().get(); return stringConverterProperty().get();
@ -62,7 +65,9 @@ public class RingProgressIndicator extends ProgressIndicator {
this.stringConverterProperty().set(stringConverter); this.stringConverterProperty().set(stringConverter);
} }
/** Optional converter to transform progress value to string. */ /**
* Optional converter to transform progress value to string.
*/
public ObjectProperty<StringConverter<Double>> stringConverterProperty() { public ObjectProperty<StringConverter<Double>> stringConverterProperty() {
return stringConverter; return stringConverter;
} }

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.base.controls; package atlantafx.base.controls;
import java.util.ArrayList; import java.util.ArrayList;
@ -33,7 +34,7 @@ public class RingProgressIndicatorSkin extends SkinBase<RingProgressIndicator> {
protected final Arc progressArc = new Arc(); protected final Arc progressArc = new Arc();
protected final Label progressLabel = new Label(); protected final Label progressLabel = new Label();
protected final RotateTransition transition = new RotateTransition( protected final RotateTransition transition = new RotateTransition(
Duration.seconds(DEFAULT_ANIMATION_TIME), progressArc Duration.seconds(DEFAULT_ANIMATION_TIME), progressArc
); );
public RingProgressIndicatorSkin(RingProgressIndicator indicator) { public RingProgressIndicatorSkin(RingProgressIndicator indicator) {
@ -230,26 +231,27 @@ public class RingProgressIndicatorSkin extends SkinBase<RingProgressIndicator> {
private static class StyleableProperties { private static class StyleableProperties {
private static final CssMetaData<RingProgressIndicator, Number> INDETERMINATE_ANIMATION_TIME = private static final CssMetaData<RingProgressIndicator, Number> INDETERMINATE_ANIMATION_TIME =
new CssMetaData<>("-fx-indeterminate-animation-time", SizeConverter.getInstance(), DEFAULT_ANIMATION_TIME) { new CssMetaData<>("-fx-indeterminate-animation-time", SizeConverter.getInstance(), DEFAULT_ANIMATION_TIME) {
@Override @Override
public boolean isSettable(RingProgressIndicator n) { public boolean isSettable(RingProgressIndicator n) {
return n.getSkin() instanceof RingProgressIndicatorSkin s && return n.getSkin() instanceof RingProgressIndicatorSkin s &&
(s.indeterminateAnimationTime == null || !s.indeterminateAnimationTime.isBound()); (s.indeterminateAnimationTime == null || !s.indeterminateAnimationTime.isBound());
} }
@Override @Override
@SuppressWarnings("RedundantCast") @SuppressWarnings("RedundantCast")
public StyleableProperty<Number> getStyleableProperty(RingProgressIndicator n) { public StyleableProperty<Number> getStyleableProperty(RingProgressIndicator n) {
final RingProgressIndicatorSkin skin = (RingProgressIndicatorSkin) n.getSkin(); final RingProgressIndicatorSkin skin = (RingProgressIndicatorSkin) n.getSkin();
return (StyleableProperty<Number>) (WritableValue<Number>) skin.indeterminateAnimationTimeProperty(); return (StyleableProperty<Number>) (WritableValue<Number>) skin.indeterminateAnimationTimeProperty();
} }
}; };
private static final List<CssMetaData<? extends Styleable, ?>> STYLEABLES; private static final List<CssMetaData<? extends Styleable, ?>> STYLEABLES;
static { static {
final List<CssMetaData<? extends Styleable, ?>> styleables = new ArrayList<>(SkinBase.getClassCssMetaData()); final List<CssMetaData<? extends Styleable, ?>> styleables =
new ArrayList<>(SkinBase.getClassCssMetaData());
styleables.add(INDETERMINATE_ANIMATION_TIME); styleables.add(INDETERMINATE_ANIMATION_TIME);
STYLEABLES = Collections.unmodifiableList(styleables); STYLEABLES = Collections.unmodifiableList(styleables);
} }

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.base.controls; package atlantafx.base.controls;
import javafx.geometry.Orientation; import javafx.geometry.Orientation;

@ -26,6 +26,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package atlantafx.base.controls; package atlantafx.base.controls;
import javafx.beans.property.BooleanProperty; import javafx.beans.property.BooleanProperty;
@ -41,7 +42,9 @@ public class ToggleSwitch extends Labeled {
protected static final String DEFAULT_STYLE_CLASS = "toggle-switch"; protected static final String DEFAULT_STYLE_CLASS = "toggle-switch";
protected static final PseudoClass PSEUDO_CLASS_SELECTED = PseudoClass.getPseudoClass("selected"); protected static final PseudoClass PSEUDO_CLASS_SELECTED = PseudoClass.getPseudoClass("selected");
/** Creates a toggle switch with empty string for its label. */ /**
* Creates a toggle switch with empty string for its label.
*/
public ToggleSwitch() { public ToggleSwitch() {
initialize(); initialize();
} }
@ -64,20 +67,28 @@ public class ToggleSwitch extends Labeled {
// Properties // // Properties //
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
/** Indicates whether this switch is selected. */ /**
* Indicates whether this switch is selected.
*/
private BooleanProperty selected; private BooleanProperty selected;
/** Sets the selected value. */ /**
* Sets the selected value.
*/
public final void setSelected(boolean value) { public final void setSelected(boolean value) {
selectedProperty().set(value); selectedProperty().set(value);
} }
/** Returns whether this Toggle Switch is selected. */ /**
* Returns whether this Toggle Switch is selected.
*/
public final boolean isSelected() { public final boolean isSelected() {
return selected != null && selected.get(); return selected != null && selected.get();
} }
/** Returns the selected property. */ /**
* Returns the selected property.
*/
public final BooleanProperty selectedProperty() { public final BooleanProperty selectedProperty() {
if (selected == null) { if (selected == null) {
selected = new BooleanPropertyBase() { selected = new BooleanPropertyBase() {
@ -117,7 +128,9 @@ public class ToggleSwitch extends Labeled {
} }
} }
/** {@inheritDoc} */ /**
* {@inheritDoc}
*/
@Override @Override
protected Skin<?> createDefaultSkin() { protected Skin<?> createDefaultSkin() {
return new ToggleSwitchSkin(this); return new ToggleSwitchSkin(this);

@ -26,6 +26,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package atlantafx.base.controls; package atlantafx.base.controls;
import java.util.ArrayList; import java.util.ArrayList;
@ -76,8 +77,9 @@ public class ToggleSwitchSkin extends SkinBase<ToggleSwitch> {
thumbArea.setOnMouseReleased(event -> mousePressedOnToggleSwitch(control)); thumbArea.setOnMouseReleased(event -> mousePressedOnToggleSwitch(control));
thumb.setOnMouseReleased(event -> mousePressedOnToggleSwitch(control)); thumb.setOnMouseReleased(event -> mousePressedOnToggleSwitch(control));
control.selectedProperty().addListener((observable, oldValue, newValue) -> { control.selectedProperty().addListener((observable, oldValue, newValue) -> {
if (newValue.booleanValue() != oldValue.booleanValue()) if (newValue.booleanValue() != oldValue.booleanValue()) {
selectedStateChanged(); selectedStateChanged();
}
}); });
} }
@ -206,21 +208,21 @@ public class ToggleSwitchSkin extends SkinBase<ToggleSwitch> {
} }
private static final CssMetaData<ToggleSwitch, Number> THUMB_MOVE_ANIMATION_TIME = private static final CssMetaData<ToggleSwitch, Number> THUMB_MOVE_ANIMATION_TIME =
new CssMetaData<>("-fx-thumb-move-animation-time", SizeConverter.getInstance(), 200) { new CssMetaData<>("-fx-thumb-move-animation-time", SizeConverter.getInstance(), 200) {
@Override @Override
public boolean isSettable(ToggleSwitch toggleSwitch) { public boolean isSettable(ToggleSwitch toggleSwitch) {
final ToggleSwitchSkin skin = (ToggleSwitchSkin) toggleSwitch.getSkin(); final ToggleSwitchSkin skin = (ToggleSwitchSkin) toggleSwitch.getSkin();
return skin.thumbMoveAnimationTime == null || skin.thumbMoveAnimationTime.isBound(); return skin.thumbMoveAnimationTime == null || skin.thumbMoveAnimationTime.isBound();
} }
@Override @Override
@SuppressWarnings("RedundantCast") @SuppressWarnings("RedundantCast")
public StyleableProperty<Number> getStyleableProperty(ToggleSwitch toggleSwitch) { public StyleableProperty<Number> getStyleableProperty(ToggleSwitch toggleSwitch) {
final ToggleSwitchSkin skin = (ToggleSwitchSkin) toggleSwitch.getSkin(); final ToggleSwitchSkin skin = (ToggleSwitchSkin) toggleSwitch.getSkin();
return (StyleableProperty<Number>) (WritableValue<Number>) skin.thumbMoveAnimationTimeProperty(); return (StyleableProperty<Number>) (WritableValue<Number>) skin.thumbMoveAnimationTimeProperty();
} }
}; };
private static final List<CssMetaData<? extends Styleable, ?>> STYLEABLES; private static final List<CssMetaData<? extends Styleable, ?>> STYLEABLES;

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.base.theme; package atlantafx.base.theme;
public final class NordDark implements Theme { public final class NordDark implements Theme {

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.base.theme; package atlantafx.base.theme;
public final class NordLight implements Theme { public final class NordLight implements Theme {

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.base.theme; package atlantafx.base.theme;
public final class PrimerDark implements Theme { public final class PrimerDark implements Theme {

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.base.theme; package atlantafx.base.theme;
public final class PrimerLight implements Theme { public final class PrimerLight implements Theme {

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.base.theme; package atlantafx.base.theme;
import javafx.css.PseudoClass; import javafx.css.PseudoClass;
@ -83,10 +84,12 @@ public final class Styles {
} }
public static void toggleStyleClass(Node node, String styleClass) { public static void toggleStyleClass(Node node, String styleClass) {
if (node == null) if (node == null) {
throw new NullPointerException("Node cannot be null!"); throw new NullPointerException("Node cannot be null!");
if (styleClass == null) }
if (styleClass == null) {
throw new NullPointerException("Style class cannot be null!"); throw new NullPointerException("Style class cannot be null!");
}
int idx = node.getStyleClass().indexOf(styleClass); int idx = node.getStyleClass().indexOf(styleClass);
if (idx > 0) { if (idx > 0) {
@ -97,10 +100,12 @@ public final class Styles {
} }
public static void addStyleClass(Node node, String styleClass, String... excludes) { public static void addStyleClass(Node node, String styleClass, String... excludes) {
if (node == null) if (node == null) {
throw new NullPointerException("Node cannot be null!"); throw new NullPointerException("Node cannot be null!");
if (styleClass == null) }
if (styleClass == null) {
throw new NullPointerException("Style class cannot be null!"); throw new NullPointerException("Style class cannot be null!");
}
if (excludes != null && excludes.length > 0) { if (excludes != null && excludes.length > 0) {
node.getStyleClass().removeAll(excludes); node.getStyleClass().removeAll(excludes);
@ -109,10 +114,12 @@ public final class Styles {
} }
public static void activatePseudoClass(Node node, PseudoClass pseudoClass, PseudoClass... excludes) { public static void activatePseudoClass(Node node, PseudoClass pseudoClass, PseudoClass... excludes) {
if (node == null) if (node == null) {
throw new NullPointerException("Node cannot be null!"); throw new NullPointerException("Node cannot be null!");
if (pseudoClass == null) }
if (pseudoClass == null) {
throw new NullPointerException("PseudoClass cannot be null!"); throw new NullPointerException("PseudoClass cannot be null!");
}
if (excludes != null && excludes.length > 0) { if (excludes != null && excludes.length > 0) {
for (PseudoClass exclude : excludes) { for (PseudoClass exclude : excludes) {

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.base.theme; package atlantafx.base.theme;
import static javafx.application.Application.STYLESHEET_CASPIAN; import static javafx.application.Application.STYLESHEET_CASPIAN;
@ -16,10 +17,12 @@ public interface Theme {
boolean isDarkMode(); boolean isDarkMode();
static Theme of(final String name, final String userAgentStylesheet, final boolean darkMode) { static Theme of(final String name, final String userAgentStylesheet, final boolean darkMode) {
if (name == null) if (name == null) {
throw new NullPointerException("Name cannot be null!"); throw new NullPointerException("Name cannot be null!");
if (userAgentStylesheet == null) }
if (userAgentStylesheet == null) {
throw new NullPointerException("User agent stylesheet cannot be null!"); throw new NullPointerException("User agent stylesheet cannot be null!");
}
return new Theme() { return new Theme() {
@ -41,6 +44,7 @@ public interface Theme {
} }
default boolean isDefault() { default boolean isDefault() {
return STYLESHEET_MODENA.equals(getUserAgentStylesheet()) || STYLESHEET_CASPIAN.equals(getUserAgentStylesheet()); return STYLESHEET_MODENA.equals(getUserAgentStylesheet()) ||
STYLESHEET_CASPIAN.equals(getUserAgentStylesheet());
} }
} }

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.base.util; package atlantafx.base.util;
import java.text.DecimalFormat; import java.text.DecimalFormat;
@ -125,15 +126,15 @@ public class DoubleStringConverter extends StringConverter<Double> {
*/ */
public static DoubleStringConverter createFor(Spinner<Double> spinner) { public static DoubleStringConverter createFor(Spinner<Double> spinner) {
final SpinnerValueFactory.DoubleSpinnerValueFactory factory = final SpinnerValueFactory.DoubleSpinnerValueFactory factory =
(SpinnerValueFactory.DoubleSpinnerValueFactory) spinner.getValueFactory(); (SpinnerValueFactory.DoubleSpinnerValueFactory) spinner.getValueFactory();
final DoubleStringConverter converter = new DoubleStringConverter( final DoubleStringConverter converter = new DoubleStringConverter(
spinner.getEditor(), factory.getMin(), factory.getMax()); spinner.getEditor(), factory.getMin(), factory.getMax());
factory.setConverter(converter); factory.setConverter(converter);
spinner.setTooltip(new Tooltip(String.format( spinner.setTooltip(new Tooltip(String.format(
"Enter a value between %.2f and %.2f", "Enter a value between %.2f and %.2f",
factory.getMin(), factory.getMax()))); factory.getMin(), factory.getMax())));
return converter; return converter;
} }

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.base.util; package atlantafx.base.util;
import javafx.application.Platform; import javafx.application.Platform;
@ -119,15 +120,15 @@ public class IntegerStringConverter extends StringConverter<Integer> {
*/ */
public static IntegerStringConverter createFor(Spinner<Integer> spinner) { public static IntegerStringConverter createFor(Spinner<Integer> spinner) {
final SpinnerValueFactory.IntegerSpinnerValueFactory factory = final SpinnerValueFactory.IntegerSpinnerValueFactory factory =
(SpinnerValueFactory.IntegerSpinnerValueFactory) spinner.getValueFactory(); (SpinnerValueFactory.IntegerSpinnerValueFactory) spinner.getValueFactory();
final IntegerStringConverter converter = new IntegerStringConverter( final IntegerStringConverter converter = new IntegerStringConverter(
spinner.getEditor(), factory.getMin(), factory.getMax()); spinner.getEditor(), factory.getMin(), factory.getMax());
factory.setConverter(converter); factory.setConverter(converter);
spinner.setTooltip(new Tooltip(String.format( spinner.setTooltip(new Tooltip(String.format(
"Enter a value between %d and %d", "Enter a value between %d and %d",
factory.getMin(), factory.getMax()))); factory.getMin(), factory.getMax())));
return converter; return converter;
} }

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.base.util; package atlantafx.base.util;
import java.util.function.UnaryOperator; import java.util.function.UnaryOperator;
@ -25,19 +26,24 @@ public class PasswordTextFormatter extends TextFormatter<String> {
char bullet) { char bullet) {
super(valueConverter, null, filter); super(valueConverter, null, filter);
if (valueConverter == null) if (valueConverter == null) {
throw new NullPointerException("StringConverter cannot be null!"); throw new NullPointerException("StringConverter cannot be null!");
if (filter == null) }
if (filter == null) {
throw new NullPointerException("UnaryOperator cannot be null!"); throw new NullPointerException("UnaryOperator cannot be null!");
if (textField == null) }
if (textField == null) {
throw new NullPointerException("TextField cannot be null!"); throw new NullPointerException("TextField cannot be null!");
}
PasswordFilter passwordFilter = (PasswordFilter) getFilter(); PasswordFilter passwordFilter = (PasswordFilter) getFilter();
passwordFilter.setBullet(bullet); passwordFilter.setBullet(bullet);
passwordFilter.setInitialText(textField.getText()); passwordFilter.setInitialText(textField.getText());
revealPasswordProperty().addListener((obs, old, val) -> { revealPasswordProperty().addListener((obs, old, val) -> {
if (val == null) { return; } if (val == null) {
return;
}
// Force text field update, because converter is only called on focus events by default. // Force text field update, because converter is only called on focus events by default.
// Also, reset caret first, because otherwise its position won't be correct due to // Also, reset caret first, because otherwise its position won't be correct due to

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.base.util; package atlantafx.base.util;
/** /**

@ -12,7 +12,8 @@ public class PasswordTextFormatterTest {
@BeforeAll @BeforeAll
public static void startup() { public static void startup() {
Platform.startup(() -> { }); Platform.startup(() -> {
});
} }
@Test @Test

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler; package atlantafx.sampler;
import static java.lang.Double.MAX_VALUE; import static java.lang.Double.MAX_VALUE;
@ -27,7 +28,9 @@ public class DefaultExceptionHandler implements Thread.UncaughtExceptionHandler
e.printStackTrace(); e.printStackTrace();
var dialog = createExceptionDialog(e); var dialog = createExceptionDialog(e);
if (dialog != null) { dialog.showAndWait(); } if (dialog != null) {
dialog.showAndWait();
}
} }
private Alert createExceptionDialog(Throwable throwable) { private Alert createExceptionDialog(Throwable throwable) {

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler; package atlantafx.sampler;
import java.io.FileInputStream; import java.io.FileInputStream;
@ -50,7 +51,9 @@ public final class FileResource {
public InputStream getInputStream() throws IOException { public InputStream getInputStream() throws IOException {
if (internal) { if (internal) {
var is = anchor.getResourceAsStream(location); var is = anchor.getResourceAsStream(location);
if (is == null) { throw new IOException("Resource not found: " + location); } if (is == null) {
throw new IOException("Resource not found: " + location);
}
return is; return is;
} }
return new FileInputStream(toPath().toFile()); return new FileInputStream(toPath().toFile());

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler; package atlantafx.sampler;
import static java.nio.charset.StandardCharsets.UTF_8; import static java.nio.charset.StandardCharsets.UTF_8;
@ -32,11 +33,11 @@ import javafx.stage.Stage;
public class Launcher extends Application { public class Launcher extends Application {
public static final boolean IS_DEV_MODE = "DEV".equalsIgnoreCase( public static final boolean IS_DEV_MODE = "DEV".equalsIgnoreCase(
Resources.getPropertyOrEnv("atlantafx.mode", "ATLANTAFX_MODE") Resources.getPropertyOrEnv("atlantafx.mode", "ATLANTAFX_MODE")
); );
public static final List<KeyCodeCombination> SUPPORTED_HOTKEYS = List.of( public static final List<KeyCodeCombination> SUPPORTED_HOTKEYS = List.of(
new KeyCodeCombination(KeyCode.F, KeyCombination.CONTROL_DOWN) new KeyCodeCombination(KeyCode.F, KeyCombination.CONTROL_DOWN)
); );
public static void main(String[] args) { public static void main(String[] args) {
@ -91,11 +92,12 @@ public class Launcher extends Application {
private void loadApplicationProperties() { private void loadApplicationProperties() {
Properties properties = new Properties(); Properties properties = new Properties();
try (InputStreamReader in = new InputStreamReader(Resources.getResourceAsStream("application.properties"), UTF_8)) { try (InputStreamReader in = new InputStreamReader(Resources.getResourceAsStream("application.properties"),
UTF_8)) {
properties.load(in); properties.load(in);
properties.forEach((key, value) -> System.setProperty( properties.forEach((key, value) -> System.setProperty(
String.valueOf(key), String.valueOf(key),
String.valueOf(value) String.valueOf(value)
)); ));
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler; package atlantafx.sampler;
import java.io.InputStream; import java.io.InputStream;
@ -14,8 +15,8 @@ public final class Resources {
public static InputStream getResourceAsStream(String resource) { public static InputStream getResourceAsStream(String resource) {
String path = resolve(resource); String path = resolve(resource);
return Objects.requireNonNull( return Objects.requireNonNull(
Launcher.class.getResourceAsStream(resolve(path)), Launcher.class.getResourceAsStream(resolve(path)),
"Resource not found: " + path "Resource not found: " + path
); );
} }

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.event; package atlantafx.sampler.event;
import java.net.URI; import java.net.URI;
@ -18,7 +19,7 @@ public class BrowseEvent extends Event {
@Override @Override
public String toString() { public String toString() {
return "BrowseEvent{" + return "BrowseEvent{" +
"uri=" + uri + "uri=" + uri +
"} " + super.toString(); "} " + super.toString();
} }
} }

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.event; package atlantafx.sampler.event;
import java.util.Map; import java.util.Map;
@ -20,7 +21,8 @@ import java.util.function.Consumer;
@SuppressWarnings({"unchecked", "rawtypes"}) @SuppressWarnings({"unchecked", "rawtypes"})
public final class DefaultEventBus implements EventBus { public final class DefaultEventBus implements EventBus {
public DefaultEventBus() {} public DefaultEventBus() {
}
private final Map<Class<?>, Set<Consumer>> subscribers = new ConcurrentHashMap<>(); private final Map<Class<?>, Set<Consumer>> subscribers = new ConcurrentHashMap<>();
@ -55,9 +57,9 @@ public final class DefaultEventBus implements EventBus {
Objects.requireNonNull(subscriber); Objects.requireNonNull(subscriber);
subscribers.keySet().stream() subscribers.keySet().stream()
.filter(eventType::isAssignableFrom) .filter(eventType::isAssignableFrom)
.map(subscribers::get) .map(subscribers::get)
.forEach(eventSubscribers -> eventSubscribers.remove(subscriber)); .forEach(eventSubscribers -> eventSubscribers.remove(subscriber));
} }
@Override @Override
@ -66,9 +68,9 @@ public final class DefaultEventBus implements EventBus {
Class<?> eventType = event.getClass(); Class<?> eventType = event.getClass();
subscribers.keySet().stream() subscribers.keySet().stream()
.filter(type -> type.isAssignableFrom(eventType)) .filter(type -> type.isAssignableFrom(eventType))
.flatMap(type -> subscribers.get(type).stream()) .flatMap(type -> subscribers.get(type).stream())
.forEach(subscriber -> publish(event, subscriber)); .forEach(subscriber -> publish(event, subscriber));
} }
private <E extends Event> void publish(E event, Consumer<E> subscriber) { private <E extends Event> void publish(E event, Consumer<E> subscriber) {

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.event; package atlantafx.sampler.event;
import java.util.UUID; import java.util.UUID;
@ -7,7 +8,8 @@ public abstract class Event {
protected final UUID id = UUID.randomUUID(); protected final UUID id = UUID.randomUUID();
protected Event() { } protected Event() {
}
public UUID getId() { public UUID getId() {
return id; return id;
@ -15,8 +17,12 @@ public abstract class Event {
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (this == o) { return true; } if (this == o) {
if (!(o instanceof Event event)) { return false; } return true;
}
if (!(o instanceof Event event)) {
return false;
}
return id.equals(event.id); return id.equals(event.id);
} }
@ -28,7 +34,7 @@ public abstract class Event {
@Override @Override
public String toString() { public String toString() {
return "Event{" + return "Event{" +
"id=" + id + "id=" + id +
'}'; '}';
} }
} }

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.event; package atlantafx.sampler.event;
import java.util.function.Consumer; import java.util.function.Consumer;
@ -8,9 +9,9 @@ public interface EventBus {
/** /**
* Subscribe to an event type * Subscribe to an event type
* *
* @param eventType the event type, can be a super class of all events to subscribe. * @param eventType the event type, can be a super class of all events to subscribe.
* @param subscriber the subscriber which will consume the events. * @param subscriber the subscriber which will consume the events.
* @param <T> the event type class. * @param <T> the event type class.
*/ */
<T extends Event> void subscribe(Class<? extends T> eventType, Consumer<T> subscriber); <T extends Event> void subscribe(Class<? extends T> eventType, Consumer<T> subscriber);
@ -24,9 +25,9 @@ public interface EventBus {
/** /**
* Unsubscribe from an event type. * Unsubscribe from an event type.
* *
* @param eventType the event type, can be a super class of all events to unsubscribe. * @param eventType the event type, can be a super class of all events to unsubscribe.
* @param subscriber the subscriber to unsubscribe. * @param subscriber the subscriber to unsubscribe.
* @param <T> the event type class. * @param <T> the event type class.
*/ */
<T extends Event> void unsubscribe(Class<? extends T> eventType, Consumer<T> subscriber); <T extends Event> void unsubscribe(Class<? extends T> eventType, Consumer<T> subscriber);

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.event; package atlantafx.sampler.event;
import javafx.scene.input.KeyCodeCombination; import javafx.scene.input.KeyCodeCombination;
@ -18,7 +19,7 @@ public class HotkeyEvent extends Event {
@Override @Override
public String toString() { public String toString() {
return "HotkeyEvent{" + return "HotkeyEvent{" +
"keys=" + keys + "keys=" + keys +
"} " + super.toString(); "} " + super.toString();
} }
} }

@ -1,8 +1,10 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.event; package atlantafx.sampler.event;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Target; import java.lang.annotation.Target;
@Target(ElementType.METHOD) @Target(ElementType.METHOD)
public @interface Listener {} public @interface Listener {
}

@ -27,7 +27,7 @@ public class ThemeEvent extends Event {
@Override @Override
public String toString() { public String toString() {
return "ThemeEvent{" + return "ThemeEvent{" +
"eventType=" + eventType + "eventType=" + eventType +
"} " + super.toString(); "} " + super.toString();
} }
} }

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.fake; package atlantafx.sampler.fake;
import static atlantafx.sampler.util.Controls.menuItem; import static atlantafx.sampler.util.Controls.menuItem;
@ -27,11 +28,11 @@ public class SampleMenuBar extends MenuBar {
public SampleMenuBar(Faker faker) { public SampleMenuBar(Faker faker) {
getMenus().addAll( getMenus().addAll(
fileMenu(faker), fileMenu(faker),
editMenu(), editMenu(),
viewMenu(), viewMenu(),
toolsMenu(), toolsMenu(),
aboutMenu() aboutMenu()
); );
} }
@ -48,19 +49,19 @@ public class SampleMenuBar extends MenuBar {
openRecentMenu.setMnemonicParsing(true); openRecentMenu.setMnemonicParsing(true);
openRecentMenu.setOnAction(PRINT_SOURCE); openRecentMenu.setOnAction(PRINT_SOURCE);
openRecentMenu.getItems().addAll( openRecentMenu.getItems().addAll(
IntStream.range(0, 10).mapToObj(x -> new MenuItem(faker.file().fileName())).toList() IntStream.range(0, 10).mapToObj(x -> new MenuItem(faker.file().fileName())).toList()
); );
fileMenu.getItems().addAll( fileMenu.getItems().addAll(
newMenu, newMenu,
new SeparatorMenuItem(), new SeparatorMenuItem(),
menuItem("Open", Feather.FOLDER, new KeyCodeCombination(KeyCode.O, CONTROL_DOWN)), menuItem("Open", Feather.FOLDER, new KeyCodeCombination(KeyCode.O, CONTROL_DOWN)),
openRecentMenu, openRecentMenu,
new SeparatorMenuItem(), new SeparatorMenuItem(),
menuItem("Save", Feather.SAVE, new KeyCodeCombination(KeyCode.S, CONTROL_DOWN)), menuItem("Save", Feather.SAVE, new KeyCodeCombination(KeyCode.S, CONTROL_DOWN)),
new MenuItem("Save As"), new MenuItem("Save As"),
new SeparatorMenuItem(), new SeparatorMenuItem(),
new MenuItem("Exit") new MenuItem("Exit")
); );
return fileMenu; return fileMenu;
} }
@ -71,12 +72,12 @@ public class SampleMenuBar extends MenuBar {
editMenu.setOnAction(PRINT_SOURCE); editMenu.setOnAction(PRINT_SOURCE);
editMenu.getItems().addAll( editMenu.getItems().addAll(
menuItem("Undo", Feather.CORNER_DOWN_LEFT, new KeyCodeCombination(KeyCode.Z, CONTROL_DOWN)), menuItem("Undo", Feather.CORNER_DOWN_LEFT, new KeyCodeCombination(KeyCode.Z, CONTROL_DOWN)),
menuItem("Redo", Feather.CORNER_DOWN_RIGHT, new KeyCodeCombination(KeyCode.Y, CONTROL_DOWN)), menuItem("Redo", Feather.CORNER_DOWN_RIGHT, new KeyCodeCombination(KeyCode.Y, CONTROL_DOWN)),
new SeparatorMenuItem(), new SeparatorMenuItem(),
menuItem("Cut", Feather.SCISSORS, new KeyCodeCombination(KeyCode.X, CONTROL_DOWN)), menuItem("Cut", Feather.SCISSORS, new KeyCodeCombination(KeyCode.X, CONTROL_DOWN)),
menuItem("Copy", Feather.COPY, new KeyCodeCombination(KeyCode.C, CONTROL_DOWN), true), menuItem("Copy", Feather.COPY, new KeyCodeCombination(KeyCode.C, CONTROL_DOWN), true),
menuItem("Paste", Feather.CORNER_DOWN_LEFT, new KeyCodeCombination(KeyCode.V, CONTROL_DOWN)) menuItem("Paste", Feather.CORNER_DOWN_LEFT, new KeyCodeCombination(KeyCode.V, CONTROL_DOWN))
); );
return editMenu; return editMenu;
} }
@ -105,12 +106,12 @@ public class SampleMenuBar extends MenuBar {
toggleItem3.setToggleGroup(viewToggleGroup); toggleItem3.setToggleGroup(viewToggleGroup);
viewMenu.getItems().addAll( viewMenu.getItems().addAll(
showToolbarItem, showToolbarItem,
showGridItem, showGridItem,
new SeparatorMenuItem(), new SeparatorMenuItem(),
toggleItem1, toggleItem1,
toggleItem2, toggleItem2,
toggleItem3 toggleItem3
); );
return viewMenu; return viewMenu;
} }
@ -129,21 +130,21 @@ public class SampleMenuBar extends MenuBar {
aboutMenu.setOnAction(PRINT_SOURCE); aboutMenu.setOnAction(PRINT_SOURCE);
var deeplyNestedMenu = new Menu("Very...", null, var deeplyNestedMenu = new Menu("Very...", null,
new Menu("Very...", null, new Menu("Very...", null,
new Menu("Deeply", null, new Menu("Deeply", null,
new Menu("Nested", null, new Menu("Nested", null,
new MenuItem("Menu") new MenuItem("Menu")
)))); ))));
// NOTE: this won't be displayed because right container is reserved for submenu indication // NOTE: this won't be displayed because right container is reserved for submenu indication
deeplyNestedMenu.setAccelerator(new KeyCodeCombination( deeplyNestedMenu.setAccelerator(new KeyCodeCombination(
KeyCode.DIGIT1, SHIFT_DOWN, CONTROL_DOWN) KeyCode.DIGIT1, SHIFT_DOWN, CONTROL_DOWN)
); );
aboutMenu.getItems().addAll( aboutMenu.getItems().addAll(
new MenuItem("Help"), new MenuItem("Help"),
new MenuItem("About"), new MenuItem("About"),
new SeparatorMenuItem(), new SeparatorMenuItem(),
deeplyNestedMenu deeplyNestedMenu
); );
return aboutMenu; return aboutMenu;
} }

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.fake.domain; package atlantafx.sampler.fake.domain;
import java.util.Objects; import java.util.Objects;
@ -28,35 +29,57 @@ public final class Book {
this.isbn = isbn; this.isbn = isbn;
} }
public UUID getId() { return id; } public UUID getId() {
return id;
}
public void setId(UUID id) { this.id = id; } public void setId(UUID id) {
this.id = id;
}
public boolean getState() { return state.get(); } public boolean getState() {
return state.get();
}
public void setState(boolean state) { this.state.set(state); } public void setState(boolean state) {
this.state.set(state);
}
public BooleanProperty stateProperty() { return state; } public BooleanProperty stateProperty() {
return state;
}
public String getAuthor() { return author; } public String getAuthor() {
return author;
}
public void setAuthor(String author) { this.author = author; } public void setAuthor(String author) {
this.author = author;
}
public String getTitle() { return title; } public String getTitle() {
return title;
}
public void setTitle(String title) { this.title = title; } public void setTitle(String title) {
this.title = title;
}
public String getIsbn() { return isbn; } public String getIsbn() {
return isbn;
}
public void setIsbn(String isbn) { this.isbn = isbn; } public void setIsbn(String isbn) {
this.isbn = isbn;
}
public static Book random(Faker faker) { public static Book random(Faker faker) {
return new Book( return new Book(
UUID.randomUUID(), UUID.randomUUID(),
new SimpleBooleanProperty(), new SimpleBooleanProperty(),
faker.book().author(), faker.book().author(),
faker.book().title(), faker.book().title(),
faker.code().isbn10() faker.code().isbn10()
); );
} }

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.fake.domain; package atlantafx.sampler.fake.domain;
import java.util.Objects; import java.util.Objects;
@ -33,31 +34,57 @@ public final class Product {
this.count = count; this.count = count;
} }
public int getId() { return id; } public int getId() {
return id;
}
public void setId(int id) { this.id = id; } public void setId(int id) {
this.id = id;
}
public boolean getState() { return state.get(); } public boolean getState() {
return state.get();
}
public BooleanProperty stateProperty() { return state; } public BooleanProperty stateProperty() {
return state;
}
public void setState(boolean state) { this.state.set(state); } public void setState(boolean state) {
this.state.set(state);
}
public String getBrand() { return brand; } public String getBrand() {
return brand;
}
public void setBrand(String brand) { this.brand = brand; } public void setBrand(String brand) {
this.brand = brand;
}
public String getName() { return name; } public String getName() {
return name;
}
public void setName(String name) { this.name = name; } public void setName(String name) {
this.name = name;
}
public String getPrice() { return price; } public String getPrice() {
return price;
}
public void setPrice(String price) { this.price = price; } public void setPrice(String price) {
this.price = price;
}
public Integer getCount() { return count; } public Integer getCount() {
return count;
}
public void setCount(Integer count) { this.count = count; } public void setCount(Integer count) {
this.count = count;
}
public double getAvailability() { public double getAvailability() {
return count * 1.0 / MAX_STOCK_SIZE; return count * 1.0 / MAX_STOCK_SIZE;
@ -65,12 +92,12 @@ public final class Product {
public static Product random(int id, Faker faker) { public static Product random(int id, Faker faker) {
return new Product( return new Product(
id, id,
new SimpleBooleanProperty(), new SimpleBooleanProperty(),
faker.commerce().brand(), faker.commerce().brand(),
faker.commerce().productName(), faker.commerce().productName(),
faker.commerce().price(), faker.commerce().price(),
faker.random().nextInt(0, MAX_STOCK_SIZE) faker.random().nextInt(0, MAX_STOCK_SIZE)
); );
} }

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.layout; package atlantafx.sampler.layout;
import atlantafx.sampler.util.Containers; import atlantafx.sampler.util.Containers;
@ -14,8 +15,8 @@ public class ApplicationWindow extends AnchorPane {
var body = new StackPane(); var body = new StackPane();
body.getStyleClass().add("body"); body.getStyleClass().add("body");
body.getChildren().setAll( body.getChildren().setAll(
new Overlay(), new Overlay(),
new MainLayer() new MainLayer()
); );
Containers.setAnchors(body, Insets.EMPTY); Containers.setAnchors(body, Insets.EMPTY);

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.layout; package atlantafx.sampler.layout;
import static atlantafx.base.theme.Styles.TEXT_SMALL; import static atlantafx.base.theme.Styles.TEXT_SMALL;
@ -97,16 +98,18 @@ class HeaderBar extends HBox {
var quickConfigBtn = new FontIcon(Material2OutlinedMZ.STYLE); var quickConfigBtn = new FontIcon(Material2OutlinedMZ.STYLE);
quickConfigBtn.mouseTransparentProperty().bind(model.themeChangeToggleProperty().not()); quickConfigBtn.mouseTransparentProperty().bind(model.themeChangeToggleProperty().not());
quickConfigBtn.opacityProperty().bind(Bindings.createDoubleBinding( quickConfigBtn.opacityProperty().bind(Bindings.createDoubleBinding(
() -> model.themeChangeToggleProperty().get() ? 1.0 : 0.5, model.themeChangeToggleProperty() () -> model.themeChangeToggleProperty().get() ? 1.0 : 0.5, model.themeChangeToggleProperty()
)); ));
quickConfigBtn.setOnMouseClicked(e -> { quickConfigBtn.setOnMouseClicked(e -> {
if (quickConfigActionHandler != null) { quickConfigActionHandler.accept(popoverAnchor); } if (quickConfigActionHandler != null) {
quickConfigActionHandler.accept(popoverAnchor);
}
}); });
var sourceCodeBtn = new FontIcon(ICON_CODE); var sourceCodeBtn = new FontIcon(ICON_CODE);
sourceCodeBtn.mouseTransparentProperty().bind(model.sourceCodeToggleProperty().not()); sourceCodeBtn.mouseTransparentProperty().bind(model.sourceCodeToggleProperty().not());
sourceCodeBtn.opacityProperty().bind(Bindings.createDoubleBinding( sourceCodeBtn.opacityProperty().bind(Bindings.createDoubleBinding(
() -> model.sourceCodeToggleProperty().get() ? 1.0 : 0.5, model.sourceCodeToggleProperty() () -> model.sourceCodeToggleProperty().get() ? 1.0 : 0.5, model.sourceCodeToggleProperty()
)); ));
sourceCodeBtn.setOnMouseClicked(e -> model.nextSubLayer()); sourceCodeBtn.setOnMouseClicked(e -> model.nextSubLayer());
@ -133,14 +136,14 @@ class HeaderBar extends HBox {
setPrefHeight(HEADER_HEIGHT); setPrefHeight(HEADER_HEIGHT);
setAlignment(Pos.CENTER_LEFT); setAlignment(Pos.CENTER_LEFT);
getChildren().setAll( getChildren().setAll(
logoBox, logoBox,
titleLabel, titleLabel,
new Spacer(), new Spacer(),
searchField, searchField,
popoverAnchor, popoverAnchor,
quickConfigBtn, quickConfigBtn,
sourceCodeBtn, sourceCodeBtn,
githubLink githubLink
); );
if (IS_DEV_MODE) { if (IS_DEV_MODE) {

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.layout; package atlantafx.sampler.layout;
import static atlantafx.base.controls.Popover.ArrowLocation.TOP_CENTER; import static atlantafx.base.controls.Popover.ArrowLocation.TOP_CENTER;
@ -73,7 +74,9 @@ class MainLayer extends BorderPane {
headerBar.setQuickConfigActionHandler(this::showThemeConfigPopover); headerBar.setQuickConfigActionHandler(this::showThemeConfigPopover);
model.selectedPageProperty().addListener((obs, old, val) -> { model.selectedPageProperty().addListener((obs, old, val) -> {
if (val != null) { loadPage(val); } if (val != null) {
loadPage(val);
}
}); });
model.currentSubLayerProperty().addListener((obs, old, val) -> { model.currentSubLayerProperty().addListener((obs, old, val) -> {
@ -85,7 +88,8 @@ class MainLayer extends BorderPane {
// update code view color theme on app theme change // update code view color theme on app theme change
DefaultEventBus.getInstance().subscribe(ThemeEvent.class, e -> { DefaultEventBus.getInstance().subscribe(ThemeEvent.class, e -> {
if (ThemeManager.getInstance().getTheme() != null && model.currentSubLayerProperty().get() == SubLayer.SOURCE_CODE) { if (ThemeManager.getInstance().getTheme() != null &&
model.currentSubLayerProperty().get() == SubLayer.SOURCE_CODE) {
showSourceCode(); showSourceCode();
} }
}); });
@ -94,15 +98,15 @@ class MainLayer extends BorderPane {
private void loadPage(Class<? extends Page> pageClass) { private void loadPage(Class<? extends Page> pageClass) {
try { try {
final Page prevPage = (Page) subLayerPane.getChildren().stream() final Page prevPage = (Page) subLayerPane.getChildren().stream()
.filter(c -> c instanceof Page) .filter(c -> c instanceof Page)
.findFirst() .findFirst()
.orElse(null); .orElse(null);
final Page nextPage = pageClass.getDeclaredConstructor().newInstance(); final Page nextPage = pageClass.getDeclaredConstructor().newInstance();
model.setPageData( model.setPageData(
nextPage.getName(), nextPage.getName(),
nextPage.canChangeThemeSettings(), nextPage.canChangeThemeSettings(),
nextPage.canDisplaySourceCode() nextPage.canDisplaySourceCode()
); );
// startup, no prev page, no animation // startup, no prev page, no animation
@ -123,7 +127,9 @@ class MainLayer extends BorderPane {
transition.setFromValue(0.0); transition.setFromValue(0.0);
transition.setToValue(1.0); transition.setToValue(1.0);
transition.setOnFinished(t -> { transition.setOnFinished(t -> {
if (nextPage instanceof Pane nextPane) { nextPane.toFront(); } if (nextPage instanceof Pane nextPane) {
nextPane.toFront();
}
}); });
transition.play(); transition.play();
} catch (Exception e) { } catch (Exception e) {

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.layout; package atlantafx.sampler.layout;
import static atlantafx.sampler.layout.MainModel.SubLayer.PAGE; import static atlantafx.sampler.layout.MainModel.SubLayer.PAGE;

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.layout; package atlantafx.sampler.layout;
import atlantafx.sampler.util.Animations; import atlantafx.sampler.util.Animations;
@ -51,8 +52,8 @@ public class Overlay extends StackPane {
scrollPane = new ScrollPane(); scrollPane = new ScrollPane();
Containers.setScrollConstraints(scrollPane, Containers.setScrollConstraints(scrollPane,
ScrollPane.ScrollBarPolicy.AS_NEEDED, true, ScrollPane.ScrollBarPolicy.AS_NEEDED, true,
ScrollPane.ScrollBarPolicy.NEVER, true ScrollPane.ScrollBarPolicy.NEVER, true
); );
scrollPane.setMaxHeight(10_000); // scroll pane won't work without height specified scrollPane.setMaxHeight(10_000); // scroll pane won't work without height specified
@ -67,14 +68,17 @@ public class Overlay extends StackPane {
// hide overlay by pressing ESC (only works when overlay or one of its children has focus, // hide overlay by pressing ESC (only works when overlay or one of its children has focus,
// that's why we requesting it in the toFront()) // that's why we requesting it in the toFront())
addEventHandler(KeyEvent.KEY_PRESSED, e -> { addEventHandler(KeyEvent.KEY_PRESSED, e -> {
if (e.getCode() == KeyCode.ESCAPE) { hideAndConsume.accept(e); } if (e.getCode() == KeyCode.ESCAPE) {
hideAndConsume.accept(e);
}
}); });
// hide overlay by clicking outside content area // hide overlay by clicking outside content area
setOnMouseClicked(e -> { setOnMouseClicked(e -> {
Pane content = getContent(); Pane content = getContent();
Node eventSource = e.getPickResult().getIntersectedNode(); Node eventSource = e.getPickResult().getIntersectedNode();
if (e.getButton() == MouseButton.PRIMARY && content != null && !NodeUtils.isDescendant(content, eventSource)) { if (e.getButton() == MouseButton.PRIMARY && content != null &&
!NodeUtils.isDescendant(content, eventSource)) {
hideAndConsume.accept(e); hideAndConsume.accept(e);
} }
}); });
@ -125,13 +129,15 @@ public class Overlay extends StackPane {
public boolean contains(Pane content) { public boolean contains(Pane content) {
return content != null && return content != null &&
getContentWrapper().getChildren().size() > 0 && getContentWrapper().getChildren().size() > 0 &&
getContentWrapper().getChildren().get(0).equals(content); getContentWrapper().getChildren().get(0).equals(content);
} }
@Override @Override
public void toFront() { public void toFront() {
if (onFrontProperty.get()) { return; } if (onFrontProperty.get()) {
return;
}
super.toFront(); super.toFront();
fadeInTransition.playFromStart(); fadeInTransition.playFromStart();
onFrontProperty.set(true); onFrontProperty.set(true);
@ -139,7 +145,9 @@ public class Overlay extends StackPane {
@Override @Override
public void toBack() { public void toBack() {
if (!onFrontProperty.get()) { return; } if (!onFrontProperty.get()) {
return;
}
super.toBack(); super.toBack();
fadeOutTransition.playFromStart(); fadeOutTransition.playFromStart();
onFrontProperty.set(false); onFrontProperty.set(false);

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.layout; package atlantafx.sampler.layout;
import static javafx.scene.control.ScrollPane.ScrollBarPolicy.AS_NEEDED; import static javafx.scene.control.ScrollPane.ScrollBarPolicy.AS_NEEDED;
@ -180,17 +181,23 @@ class Sidebar extends StackPane {
} }
public Optional<NavLink> findLink(Class<? extends Page> pageClass) { public Optional<NavLink> findLink(Class<? extends Page> pageClass) {
if (pageClass == null) { return Optional.empty(); } if (pageClass == null) {
return Optional.empty();
}
return Optional.ofNullable(registry.get(pageClass)); return Optional.ofNullable(registry.get(pageClass));
} }
public Optional<NavLink> getPrevious() { public Optional<NavLink> getPrevious() {
var current = content.indexOf(registry.get(model.selectedPageProperty().get())); var current = content.indexOf(registry.get(model.selectedPageProperty().get()));
if (!(current > 0)) { return Optional.empty(); } if (!(current > 0)) {
return Optional.empty();
}
for (int i = current - 1; i >= 0; i--) { for (int i = current - 1; i >= 0; i--) {
var r = content.get(i); var r = content.get(i);
if (r instanceof NavLink link) { return Optional.of(link); } if (r instanceof NavLink link) {
return Optional.of(link);
}
} }
return Optional.empty(); return Optional.empty();
@ -198,11 +205,15 @@ class Sidebar extends StackPane {
public Optional<NavLink> getNext() { public Optional<NavLink> getNext() {
var current = content.indexOf(registry.get(model.selectedPageProperty().get())); var current = content.indexOf(registry.get(model.selectedPageProperty().get()));
if (!(current >= 0 && current < content.size() - 1)) { return Optional.empty(); } // has next if (!(current >= 0 && current < content.size() - 1)) {
return Optional.empty();
} // has next
for (int i = current + 1; i < content.size(); i++) { for (int i = current + 1; i < content.size(); i++) {
var r = content.get(i); var r = content.get(i);
if (r instanceof NavLink link) { return Optional.of(link); } if (r instanceof NavLink link) {
return Optional.of(link);
}
} }
return Optional.empty(); return Optional.empty();
@ -210,56 +221,56 @@ class Sidebar extends StackPane {
private ObservableList<Region> create() { private ObservableList<Region> create() {
return FXCollections.observableArrayList( return FXCollections.observableArrayList(
caption("GENERAL"), caption("GENERAL"),
navLink(ThemePage.NAME, ThemePage.class), navLink(ThemePage.NAME, ThemePage.class),
navLink(TypographyPage.NAME, TypographyPage.class), navLink(TypographyPage.NAME, TypographyPage.class),
navLink(IconsPage.NAME, IconsPage.class), navLink(IconsPage.NAME, IconsPage.class),
caption("COMPONENTS"), caption("COMPONENTS"),
navLink(OverviewPage.NAME, OverviewPage.class), navLink(OverviewPage.NAME, OverviewPage.class),
navLink(InputGroupPage.NAME, InputGroupPage.class), navLink(InputGroupPage.NAME, InputGroupPage.class),
new Spacer(10, Orientation.VERTICAL), new Spacer(10, Orientation.VERTICAL),
navLink(AccordionPage.NAME, AccordionPage.class), navLink(AccordionPage.NAME, AccordionPage.class),
navLink(BreadcrumbsPage.NAME, BreadcrumbsPage.class), navLink(BreadcrumbsPage.NAME, BreadcrumbsPage.class),
navLink(ButtonPage.NAME, ButtonPage.class), navLink(ButtonPage.NAME, ButtonPage.class),
navLink(ChartPage.NAME, ChartPage.class), navLink(ChartPage.NAME, ChartPage.class),
navLink(CheckBoxPage.NAME, CheckBoxPage.class), navLink(CheckBoxPage.NAME, CheckBoxPage.class),
navLink(ColorPickerPage.NAME, ColorPickerPage.class), navLink(ColorPickerPage.NAME, ColorPickerPage.class),
navLink(ComboBoxPage.NAME, ComboBoxPage.class, "ChoiceBox"), navLink(ComboBoxPage.NAME, ComboBoxPage.class, "ChoiceBox"),
navLink(CustomTextFieldPage.NAME, CustomTextFieldPage.class), navLink(CustomTextFieldPage.NAME, CustomTextFieldPage.class),
navLink(DatePickerPage.NAME, DatePickerPage.class), navLink(DatePickerPage.NAME, DatePickerPage.class),
navLink(DialogPage.NAME, DialogPage.class), navLink(DialogPage.NAME, DialogPage.class),
navLink(HTMLEditorPage.NAME, HTMLEditorPage.class), navLink(HTMLEditorPage.NAME, HTMLEditorPage.class),
navLink(LabelPage.NAME, LabelPage.class), navLink(LabelPage.NAME, LabelPage.class),
navLink(ListPage.NAME, ListPage.class), navLink(ListPage.NAME, ListPage.class),
navLink(MenuPage.NAME, MenuPage.class), navLink(MenuPage.NAME, MenuPage.class),
navLink(MenuButtonPage.NAME, MenuButtonPage.class, "SplitMenuButton"), navLink(MenuButtonPage.NAME, MenuButtonPage.class, "SplitMenuButton"),
navLink(PaginationPage.NAME, PaginationPage.class), navLink(PaginationPage.NAME, PaginationPage.class),
navLink(PopoverPage.NAME, PopoverPage.class), navLink(PopoverPage.NAME, PopoverPage.class),
navLink(ProgressPage.NAME, ProgressPage.class), navLink(ProgressPage.NAME, ProgressPage.class),
navLink(RadioButtonPage.NAME, RadioButtonPage.class), navLink(RadioButtonPage.NAME, RadioButtonPage.class),
navLink(ScrollPanePage.NAME, ScrollPanePage.class), navLink(ScrollPanePage.NAME, ScrollPanePage.class),
navLink(SeparatorPage.NAME, SeparatorPage.class), navLink(SeparatorPage.NAME, SeparatorPage.class),
navLink(SliderPage.NAME, SliderPage.class), navLink(SliderPage.NAME, SliderPage.class),
navLink(SpinnerPage.NAME, SpinnerPage.class), navLink(SpinnerPage.NAME, SpinnerPage.class),
navLink(SplitPanePage.NAME, SplitPanePage.class), navLink(SplitPanePage.NAME, SplitPanePage.class),
navLink(TablePage.NAME, TablePage.class), navLink(TablePage.NAME, TablePage.class),
navLink(TabPanePage.NAME, TabPanePage.class), navLink(TabPanePage.NAME, TabPanePage.class),
navLink(TextAreaPage.NAME, TextAreaPage.class), navLink(TextAreaPage.NAME, TextAreaPage.class),
navLink(TextFieldPage.NAME, TextFieldPage.class, "PasswordField"), navLink(TextFieldPage.NAME, TextFieldPage.class, "PasswordField"),
navLink(TitledPanePage.NAME, TitledPanePage.class), navLink(TitledPanePage.NAME, TitledPanePage.class),
navLink(ToggleButtonPage.NAME, ToggleButtonPage.class), navLink(ToggleButtonPage.NAME, ToggleButtonPage.class),
navLink(ToggleSwitchPage.NAME, ToggleSwitchPage.class), navLink(ToggleSwitchPage.NAME, ToggleSwitchPage.class),
navLink(ToolBarPage.NAME, ToolBarPage.class), navLink(ToolBarPage.NAME, ToolBarPage.class),
navLink(TooltipPage.NAME, TooltipPage.class), navLink(TooltipPage.NAME, TooltipPage.class),
navLink(TreePage.NAME, TreePage.class), navLink(TreePage.NAME, TreePage.class),
navLink(TreeTablePage.NAME, TreeTablePage.class), navLink(TreeTablePage.NAME, TreeTablePage.class),
caption("SHOWCASE"), caption("SHOWCASE"),
navLink(FileManagerPage.NAME, FileManagerPage.class), navLink(FileManagerPage.NAME, FileManagerPage.class),
navLink(MusicPlayerPage.NAME, MusicPlayerPage.class), navLink(MusicPlayerPage.NAME, MusicPlayerPage.class),
navLink(WidgetCollectionPage.NAME, navLink(WidgetCollectionPage.NAME,
WidgetCollectionPage.class, WidgetCollectionPage.class,
"Card", "Message", "Stepper", "Tag" "Card", "Message", "Stepper", "Tag"
) )
); );
} }
@ -310,7 +321,8 @@ class Sidebar extends StackPane {
public boolean matches(String filter) { public boolean matches(String filter) {
Objects.requireNonNull(filter); Objects.requireNonNull(filter);
return contains(getText(), filter) || searchKeywords.stream().anyMatch(keyword -> contains(keyword, filter)); return contains(getText(), filter) ||
searchKeywords.stream().anyMatch(keyword -> contains(keyword, filter));
} }
private boolean contains(String text, String filter) { private boolean contains(String text, String filter) {

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page; package atlantafx.sampler.page;
import static atlantafx.sampler.util.Containers.setScrollConstraints; import static atlantafx.sampler.util.Containers.setScrollConstraints;
@ -66,12 +67,15 @@ public abstract class AbstractPage extends BorderPane implements Page {
} }
@Override @Override
public void reset() { } public void reset() {
}
@Override @Override
protected void layoutChildren() { protected void layoutChildren() {
super.layoutChildren(); super.layoutChildren();
if (isRendered) { return; } if (isRendered) {
return;
}
isRendered = true; isRendered = true;
onRendered(); onRendered();

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page; package atlantafx.sampler.page;
import static java.nio.charset.StandardCharsets.UTF_8; import static java.nio.charset.StandardCharsets.UTF_8;
@ -43,24 +44,24 @@ public class CodeViewer extends AnchorPane {
var hljsLineNum = Resources.getResourceAsStream(HLJS_LN_LIB)) { var hljsLineNum = Resources.getResourceAsStream(HLJS_LN_LIB)) {
var content = new StringBuilder() var content = new StringBuilder()
.append("<!DOCTYPE html>") // mandatory for line numbers plugin .append("<!DOCTYPE html>") // mandatory for line numbers plugin
.append("<html>") .append("<html>")
.append("<head>") .append("<head>")
.append("<style>").append(theme.getCss()).append("</style>") .append("<style>").append(theme.getCss()).append("</style>")
.append("<style>").append(HLJS_LN_CSS).append("</style>") .append("<style>").append(HLJS_LN_CSS).append("</style>")
.append("<script>").append(new String(hljs.readAllBytes(), UTF_8)).append("</script>") .append("<script>").append(new String(hljs.readAllBytes(), UTF_8)).append("</script>")
.append("<script>").append(new String(hljsLineNum.readAllBytes(), UTF_8)).append("</script>") .append("<script>").append(new String(hljsLineNum.readAllBytes(), UTF_8)).append("</script>")
.append("<script>" + HLJS_SCRIPT + "</script>") .append("<script>" + HLJS_SCRIPT + "</script>")
.append("</head>") .append("</head>")
.append("<body>") .append("<body>")
.append("<pre>") .append("<pre>")
.append("<code class=\"language-java\">") .append("<code class=\"language-java\">")
.append(new String(source.readAllBytes(), UTF_8)) .append(new String(source.readAllBytes(), UTF_8))
.append("</code>") .append("</code>")
.append("</pre>") .append("</pre>")
.append("</body>") .append("</body>")
.append("</html>") .append("</html>")
.toString(); .toString();
webView.setPageFill(Color.TRANSPARENT); webView.setPageFill(Color.TRANSPARENT);
webView.getEngine().loadContent(content); webView.getEngine().loadContent(content);

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page; package atlantafx.sampler.page;
import static atlantafx.base.theme.Styles.BUTTON_CIRCLE; import static atlantafx.base.theme.Styles.BUTTON_CIRCLE;
@ -48,9 +49,9 @@ public abstract class OverlayDialog<T extends Region> extends VBox {
headerBox.getStyleClass().add("header"); headerBox.getStyleClass().add("header");
headerBox.setAlignment(Pos.CENTER_LEFT); headerBox.setAlignment(Pos.CENTER_LEFT);
headerBox.getChildren().setAll( headerBox.getChildren().setAll(
titleLabel, titleLabel,
new Spacer(), new Spacer(),
topCloseBtn topCloseBtn
); );
VBox.setVgrow(headerBox, Priority.NEVER); VBox.setVgrow(headerBox, Priority.NEVER);
@ -63,8 +64,8 @@ public abstract class OverlayDialog<T extends Region> extends VBox {
footerBox.getStyleClass().add("footer"); footerBox.getStyleClass().add("footer");
footerBox.setAlignment(Pos.CENTER_RIGHT); footerBox.setAlignment(Pos.CENTER_RIGHT);
footerBox.getChildren().setAll( footerBox.getChildren().setAll(
new Spacer(), new Spacer(),
bottomCloseBtn bottomCloseBtn
); );
VBox.setVgrow(footerBox, Priority.NEVER); VBox.setVgrow(footerBox, Priority.NEVER);
@ -91,7 +92,7 @@ public abstract class OverlayDialog<T extends Region> extends VBox {
getChildren().set(CONTENT_CHILD_INDEX, content); getChildren().set(CONTENT_CHILD_INDEX, content);
} else { } else {
throw new UnsupportedOperationException("Content cannot be placed because of unexpected children size. " + throw new UnsupportedOperationException("Content cannot be placed because of unexpected children size. " +
"You should override 'OverlayDialog#setContent()' and place it manually."); "You should override 'OverlayDialog#setContent()' and place it manually.");
} }
} }

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page; package atlantafx.sampler.page;
import javafx.scene.Parent; import javafx.scene.Parent;

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page; package atlantafx.sampler.page;
import static atlantafx.base.theme.Styles.BUTTON_CIRCLE; import static atlantafx.base.theme.Styles.BUTTON_CIRCLE;
@ -80,12 +81,16 @@ public class QuickConfigMenu extends StackPane {
} }
private MainMenu getOrCreateMainMenu() { private MainMenu getOrCreateMainMenu() {
if (mainMenu == null) { mainMenu = new MainMenu(navHandler); } if (mainMenu == null) {
mainMenu = new MainMenu(navHandler);
}
return mainMenu; return mainMenu;
} }
private ThemeSelectionMenu getOrCreateThemeSelectionMenu() { private ThemeSelectionMenu getOrCreateThemeSelectionMenu() {
if (themeSelectionMenu == null) { themeSelectionMenu = new ThemeSelectionMenu(navHandler); } if (themeSelectionMenu == null) {
themeSelectionMenu = new ThemeSelectionMenu(navHandler);
}
return themeSelectionMenu; return themeSelectionMenu;
} }
@ -124,10 +129,10 @@ public class QuickConfigMenu extends StackPane {
private final IntegerProperty zoom = new SimpleIntegerProperty(DEFAULT_ZOOM); private final IntegerProperty zoom = new SimpleIntegerProperty(DEFAULT_ZOOM);
private final BooleanBinding canZoomIn = Bindings.createBooleanBinding( private final BooleanBinding canZoomIn = Bindings.createBooleanBinding(
() -> SUPPORTED_ZOOM.indexOf(zoom.get()) < SUPPORTED_ZOOM.size() - 1, zoom () -> SUPPORTED_ZOOM.indexOf(zoom.get()) < SUPPORTED_ZOOM.size() - 1, zoom
); );
private final BooleanBinding canZoomOut = Bindings.createBooleanBinding( private final BooleanBinding canZoomOut = Bindings.createBooleanBinding(
() -> SUPPORTED_ZOOM.indexOf(zoom.get()) >= 1, zoom () -> SUPPORTED_ZOOM.indexOf(zoom.get()) >= 1, zoom
); );
public MainMenu(Consumer<String> navHandler) { public MainMenu(Consumer<String> navHandler) {
@ -178,11 +183,11 @@ public class QuickConfigMenu extends StackPane {
// ~ // ~
getChildren().setAll( getChildren().setAll(
themeSelectionMenu, themeSelectionMenu,
new Separator(), new Separator(),
accentSelector, accentSelector,
new Separator(), new Separator(),
zoomBox zoomBox
); );
} }
@ -234,8 +239,8 @@ public class QuickConfigMenu extends StackPane {
@Override @Override
public void update() { public void update() {
items.forEach(item -> item.pseudoClassStateChanged( items.forEach(item -> item.pseudoClassStateChanged(
SELECTED, SELECTED,
Objects.equals(item.getUserData(), ThemeManager.getInstance().getTheme().getName()) Objects.equals(item.getUserData(), ThemeManager.getInstance().getTheme().getName())
)); ));
} }

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page; package atlantafx.sampler.page;
import java.util.Objects; import java.util.Objects;

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page.components; package atlantafx.sampler.page.components;
import static atlantafx.base.theme.Styles.DENSE; import static atlantafx.base.theme.Styles.DENSE;
@ -31,7 +32,9 @@ public class AccordionPage extends AbstractPage {
public static final String NAME = "Accordion"; public static final String NAME = "Accordion";
@Override @Override
public String getName() { return NAME; } public String getName() {
return NAME;
}
private final BooleanProperty expandedProperty = new SimpleBooleanProperty(true); private final BooleanProperty expandedProperty = new SimpleBooleanProperty(true);
private final BooleanProperty animatedProperty = new SimpleBooleanProperty(true); private final BooleanProperty animatedProperty = new SimpleBooleanProperty(true);
@ -43,8 +46,8 @@ public class AccordionPage extends AbstractPage {
accordion = createPlayground(); accordion = createPlayground();
var sample = new SampleBlock( var sample = new SampleBlock(
"Playground", "Playground",
new VBox(SampleBlock.BLOCK_VGAP, createControls(), accordion) new VBox(SampleBlock.BLOCK_VGAP, createControls(), accordion)
); );
sample.setFillHeight(true); sample.setFillHeight(true);
setUserContent(sample); setUserContent(sample);
@ -61,20 +64,20 @@ public class AccordionPage extends AbstractPage {
var denseToggle = new ToggleSwitch("Dense"); var denseToggle = new ToggleSwitch("Dense");
denseToggle.selectedProperty().addListener( denseToggle.selectedProperty().addListener(
(obs, old, val) -> accordion.getPanes().forEach(p -> toggleStyleClass(p, DENSE)) (obs, old, val) -> accordion.getPanes().forEach(p -> toggleStyleClass(p, DENSE))
); );
var altIconToggle = new ToggleSwitch("Alt icon"); var altIconToggle = new ToggleSwitch("Alt icon");
altIconToggle.selectedProperty().addListener( altIconToggle.selectedProperty().addListener(
(obs, old, val) -> accordion.getPanes().forEach(p -> toggleStyleClass(p, Tweaks.ALT_ICON)) (obs, old, val) -> accordion.getPanes().forEach(p -> toggleStyleClass(p, Tweaks.ALT_ICON))
); );
var controls = new HBox( var controls = new HBox(
BLOCK_HGAP, BLOCK_HGAP,
animatedToggle, animatedToggle,
expandedToggle, expandedToggle,
denseToggle, denseToggle,
altIconToggle altIconToggle
); );
controls.setAlignment(Pos.CENTER); controls.setAlignment(Pos.CENTER);
controls.setPadding(new Insets(0, 0, 0, 2)); controls.setPadding(new Insets(0, 0, 0, 2));
@ -101,8 +104,8 @@ public class AccordionPage extends AbstractPage {
disabledBlock.setDisable(true); disabledBlock.setDisable(true);
var imageBlock = new TitledPane("_Image", new VBox(10, var imageBlock = new TitledPane("_Image", new VBox(10,
new ImageView(new Image(Resources.getResourceAsStream("images/20_min_adventure.jpg"))), new ImageView(new Image(Resources.getResourceAsStream("images/20_min_adventure.jpg"))),
new TextFlow(new Text(FAKER.rickAndMorty().quote())) new TextFlow(new Text(FAKER.rickAndMorty().quote()))
)); ));
imageBlock.animatedProperty().bind(animatedProperty); imageBlock.animatedProperty().bind(animatedProperty);
imageBlock.setMnemonicParsing(true); imageBlock.setMnemonicParsing(true);
@ -110,10 +113,10 @@ public class AccordionPage extends AbstractPage {
// ~ // ~
var accordion = new Accordion( var accordion = new Accordion(
textBlock, textBlock,
scrollableTextBlock, scrollableTextBlock,
disabledBlock, disabledBlock,
imageBlock imageBlock
); );
// prevents accordion from being completely collapsed // prevents accordion from being completely collapsed

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page.components; package atlantafx.sampler.page.components;
import atlantafx.base.controls.Breadcrumbs; import atlantafx.base.controls.Breadcrumbs;
@ -25,15 +26,17 @@ public class BreadcrumbsPage extends AbstractPage {
private static final int CRUMB_COUNT = 5; private static final int CRUMB_COUNT = 5;
@Override @Override
public String getName() { return NAME; } public String getName() {
return NAME;
}
public BreadcrumbsPage() { public BreadcrumbsPage() {
super(); super();
setUserContent(new VBox( setUserContent(new VBox(
Page.PAGE_VGAP, Page.PAGE_VGAP,
basicSample(), basicSample(),
customCrumbSample(), customCrumbSample(),
customDividerSample() customDividerSample()
)); ));
} }
@ -54,7 +57,9 @@ public class BreadcrumbsPage extends AbstractPage {
private SampleBlock customDividerSample() { private SampleBlock customDividerSample() {
Callback<BreadCrumbItem<String>, ? extends Node> dividerFactory = item -> { Callback<BreadCrumbItem<String>, ? extends Node> dividerFactory = item -> {
if (item == null) { return new Label("", new FontIcon(Material2AL.HOME)); } if (item == null) {
return new Label("", new FontIcon(Material2AL.HOME));
}
return !item.isLast() ? new Label("", new FontIcon(Material2AL.CHEVRON_RIGHT)) : null; return !item.isLast() ? new Label("", new FontIcon(Material2AL.CHEVRON_RIGHT)) : null;
}; };
@ -64,7 +69,7 @@ public class BreadcrumbsPage extends AbstractPage {
private HBox createBreadcrumbs(Callback<BreadCrumbItem<String>, ButtonBase> crumbFactory, private HBox createBreadcrumbs(Callback<BreadCrumbItem<String>, ButtonBase> crumbFactory,
Callback<BreadCrumbItem<String>, ? extends Node> dividerFactory) { Callback<BreadCrumbItem<String>, ? extends Node> dividerFactory) {
BreadCrumbItem<String> model = Breadcrumbs.buildTreeModel( BreadCrumbItem<String> model = Breadcrumbs.buildTreeModel(
generate(() -> FAKER.science().element(), CRUMB_COUNT).toArray(String[]::new) generate(() -> FAKER.science().element(), CRUMB_COUNT).toArray(String[]::new)
); );
var nextBtn = new Button("Next"); var nextBtn = new Button("Next");
@ -72,8 +77,12 @@ public class BreadcrumbsPage extends AbstractPage {
var breadcrumbs = new Breadcrumbs<>(model); var breadcrumbs = new Breadcrumbs<>(model);
breadcrumbs.setSelectedCrumb(getAncestor(model, CRUMB_COUNT / 2)); breadcrumbs.setSelectedCrumb(getAncestor(model, CRUMB_COUNT / 2));
if (crumbFactory != null) { breadcrumbs.setCrumbFactory(crumbFactory); } if (crumbFactory != null) {
if (dividerFactory != null) { breadcrumbs.setDividerFactory(dividerFactory); } breadcrumbs.setCrumbFactory(crumbFactory);
}
if (dividerFactory != null) {
breadcrumbs.setDividerFactory(dividerFactory);
}
nextBtn.setOnAction(e -> { nextBtn.setOnAction(e -> {
BreadCrumbItem<String> selected = breadcrumbs.getSelectedCrumb(); BreadCrumbItem<String> selected = breadcrumbs.getSelectedCrumb();

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page.components; package atlantafx.sampler.page.components;
import static atlantafx.base.theme.Styles.ACCENT; import static atlantafx.base.theme.Styles.ACCENT;
@ -119,8 +120,8 @@ public class ButtonPage extends AbstractPage {
flatDangerBtn.getStyleClass().addAll(BUTTON_ICON, FLAT, DANGER); flatDangerBtn.getStyleClass().addAll(BUTTON_ICON, FLAT, DANGER);
var content = new HBox(BLOCK_HGAP, var content = new HBox(BLOCK_HGAP,
basicBtn, accentBtn, successBtn, dangerBtn, basicBtn, accentBtn, successBtn, dangerBtn,
flatAccentBtn, flatSuccessBtn, flatDangerBtn flatAccentBtn, flatSuccessBtn, flatDangerBtn
); );
return new SampleBlock("Icon", content); return new SampleBlock("Icon", content);
} }
@ -155,8 +156,8 @@ public class ButtonPage extends AbstractPage {
flatDangerBtn.setShape(new Circle(50)); flatDangerBtn.setShape(new Circle(50));
var content = new HBox(BLOCK_HGAP, var content = new HBox(BLOCK_HGAP,
basicBtn, accentBtn, successBtn, dangerBtn, basicBtn, accentBtn, successBtn, dangerBtn,
flatAccentBtn, flatSuccessBtn, flatDangerBtn flatAccentBtn, flatSuccessBtn, flatDangerBtn
); );
return new SampleBlock("Circular", content); return new SampleBlock("Circular", content);
} }
@ -215,22 +216,22 @@ public class ButtonPage extends AbstractPage {
var btn = new Button("DO SOMETHING!"); var btn = new Button("DO SOMETHING!");
btn.getStyleClass().addAll(SUCCESS, LARGE); btn.getStyleClass().addAll(SUCCESS, LARGE);
btn.setStyle(""" btn.setStyle("""
-color-button-bg: linear-gradient(to bottom right, -color-success-emphasis, darkblue); -color-button-bg: linear-gradient(to bottom right, -color-success-emphasis, darkblue);
-color-button-bg-hover: -color-button-bg; -color-button-bg-hover: -color-button-bg;
-color-button-bg-focused: -color-button-bg; -color-button-bg-focused: -color-button-bg;
-color-button-bg-pressed: -color-button-bg; -color-button-bg-pressed: -color-button-bg;
"""); """);
var iconBtn = new Button("", new FontIcon(Material2AL.FAVORITE)); var iconBtn = new Button("", new FontIcon(Material2AL.FAVORITE));
iconBtn.getStyleClass().addAll("favorite-button", BUTTON_CIRCLE, FLAT, DANGER); iconBtn.getStyleClass().addAll("favorite-button", BUTTON_CIRCLE, FLAT, DANGER);
new CSSFragment(""" new CSSFragment("""
.favorite-button.button >.ikonli-font-icon { .favorite-button.button >.ikonli-font-icon {
-fx-fill: linear-gradient(to bottom right, pink, -color-danger-emphasis); -fx-fill: linear-gradient(to bottom right, pink, -color-danger-emphasis);
-fx-icon-color: linear-gradient(to bottom right, pink, -color-danger-emphasis); -fx-icon-color: linear-gradient(to bottom right, pink, -color-danger-emphasis);
-fx-font-size: 32px; -fx-font-size: 32px;
-fx-icon-size: 32px; -fx-icon-size: 32px;
} }
""").addTo(iconBtn); """).addTo(iconBtn);
var content = new HBox(BLOCK_HGAP, btn, iconBtn); var content = new HBox(BLOCK_HGAP, btn, iconBtn);
content.setAlignment(Pos.CENTER_LEFT); content.setAlignment(Pos.CENTER_LEFT);

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page.components; package atlantafx.sampler.page.components;
import atlantafx.base.controls.Spacer; import atlantafx.base.controls.Spacer;
@ -39,7 +40,9 @@ public class ChartPage extends AbstractPage {
public static final String NAME = "Chart"; public static final String NAME = "Chart";
@Override @Override
public String getName() { return NAME; } public String getName() {
return NAME;
}
private final BorderPane chartWrapper = new BorderPane(); private final BorderPane chartWrapper = new BorderPane();
private final ComboBox<Example> exampleSelect = new ComboBox<>(); private final ComboBox<Example> exampleSelect = new ComboBox<>();
@ -47,7 +50,7 @@ public class ChartPage extends AbstractPage {
public ChartPage() { public ChartPage() {
super(); super();
setUserContent(new VBox( setUserContent(new VBox(
new SampleBlock("Playground", createPlayground()) new SampleBlock("Playground", createPlayground())
)); ));
} }
@ -55,7 +58,9 @@ public class ChartPage extends AbstractPage {
exampleSelect.setMaxWidth(Double.MAX_VALUE); exampleSelect.setMaxWidth(Double.MAX_VALUE);
exampleSelect.getItems().setAll(Example.values()); exampleSelect.getItems().setAll(Example.values());
exampleSelect.getSelectionModel().selectedItemProperty().addListener((obs, old, val) -> { exampleSelect.getSelectionModel().selectedItemProperty().addListener((obs, old, val) -> {
if (val == null) { return; } if (val == null) {
return;
}
Chart newChart = createChart(val); Chart newChart = createChart(val);
@ -78,7 +83,9 @@ public class ChartPage extends AbstractPage {
var disableToggle = new ToggleSwitch("Disable"); var disableToggle = new ToggleSwitch("Disable");
disableToggle.selectedProperty().addListener((obs, old, val) -> findDisplayedChart().ifPresent(ch -> { disableToggle.selectedProperty().addListener((obs, old, val) -> findDisplayedChart().ifPresent(ch -> {
if (val != null) { ch.setDisable(val); } if (val != null) {
ch.setDisable(val);
}
})); }));
var controls = new HBox(disableToggle); var controls = new HBox(disableToggle);
@ -86,9 +93,9 @@ public class ChartPage extends AbstractPage {
VBox playground = new VBox(SampleBlock.BLOCK_VGAP); VBox playground = new VBox(SampleBlock.BLOCK_VGAP);
playground.getChildren().setAll( playground.getChildren().setAll(
new HBox(new Label("Select an example:"), new Spacer(), disableToggle), new HBox(new Label("Select an example:"), new Spacer(), disableToggle),
exampleSelect, exampleSelect,
chartWrapper chartWrapper
); );
return playground; return playground;
@ -102,20 +109,36 @@ public class ChartPage extends AbstractPage {
private Optional<Chart> findDisplayedChart() { private Optional<Chart> findDisplayedChart() {
return chartWrapper.getChildren().size() > 0 ? return chartWrapper.getChildren().size() > 0 ?
Optional.of((Chart) chartWrapper.getChildren().get(0)) : Optional.of((Chart) chartWrapper.getChildren().get(0)) :
Optional.empty(); Optional.empty();
} }
private Chart createChart(Example example) { private Chart createChart(Example example) {
switch (example) { switch (example) {
case AREA_CHART -> { return areaChart(false); } case AREA_CHART -> {
case BAR_CHART -> { return barChart(false); } return areaChart(false);
case BUBBLE_CHART -> { return bubbleChart(); } }
case LINE_CHART -> { return lineChart(); } case BAR_CHART -> {
case PIE_CHART -> { return pieChart(); } return barChart(false);
case SCATTER_CHART -> { return scatterChart(); } }
case STACKED_AREA_CHART -> { return areaChart(true); } case BUBBLE_CHART -> {
case STACKED_BAR_CHART -> { return barChart(true); } return bubbleChart();
}
case LINE_CHART -> {
return lineChart();
}
case PIE_CHART -> {
return pieChart();
}
case SCATTER_CHART -> {
return scatterChart();
}
case STACKED_AREA_CHART -> {
return areaChart(true);
}
case STACKED_BAR_CHART -> {
return barChart(true);
}
default -> throw new IllegalArgumentException("Unexpected enum value: " + example); default -> throw new IllegalArgumentException("Unexpected enum value: " + example);
} }
} }
@ -131,13 +154,13 @@ public class ChartPage extends AbstractPage {
var april = new XYChart.Series<Number, Number>(); var april = new XYChart.Series<Number, Number>();
april.setName("April"); april.setName("April");
IntStream.range(1, 30).forEach(i -> april.getData().add( IntStream.range(1, 30).forEach(i -> april.getData().add(
new XYChart.Data<>(i, FAKER.random().nextInt(15, 30)) new XYChart.Data<>(i, FAKER.random().nextInt(15, 30))
)); ));
var may = new XYChart.Series<Number, Number>(); var may = new XYChart.Series<Number, Number>();
may.setName("May"); may.setName("May");
IntStream.range(1, 30).forEach(i -> may.getData().add( IntStream.range(1, 30).forEach(i -> may.getData().add(
new XYChart.Data<>(i, FAKER.random().nextInt(15, 30)) new XYChart.Data<>(i, FAKER.random().nextInt(15, 30))
)); ));
var chart = stacked ? new StackedAreaChart<>(x, y) : new AreaChart<>(x, y); var chart = stacked ? new StackedAreaChart<>(x, y) : new AreaChart<>(x, y);
@ -151,8 +174,8 @@ public class ChartPage extends AbstractPage {
private Chart barChart(boolean stacked) { private Chart barChart(boolean stacked) {
final var rnd = FAKER.random(); final var rnd = FAKER.random();
final var countries = IntStream.range(0, 5).boxed() final var countries = IntStream.range(0, 5).boxed()
.map(i -> FAKER.country().countryCode3().toUpperCase()) .map(i -> FAKER.country().countryCode3().toUpperCase())
.toList(); .toList();
var x = new CategoryAxis(); var x = new CategoryAxis();
x.setLabel("Country"); x.setLabel("Country");
@ -163,19 +186,19 @@ public class ChartPage extends AbstractPage {
var january = new XYChart.Series<String, Number>(); var january = new XYChart.Series<String, Number>();
january.setName("January"); january.setName("January");
IntStream.range(0, countries.size()).forEach(i -> january.getData().add( IntStream.range(0, countries.size()).forEach(i -> january.getData().add(
new XYChart.Data<>(countries.get(i), rnd.nextInt(10, 80)) new XYChart.Data<>(countries.get(i), rnd.nextInt(10, 80))
)); ));
var february = new XYChart.Series<String, Number>(); var february = new XYChart.Series<String, Number>();
february.setName("February"); february.setName("February");
IntStream.range(0, countries.size()).forEach(i -> february.getData().add( IntStream.range(0, countries.size()).forEach(i -> february.getData().add(
new XYChart.Data<>(countries.get(i), rnd.nextInt(10, 80)) new XYChart.Data<>(countries.get(i), rnd.nextInt(10, 80))
)); ));
var march = new XYChart.Series<String, Number>(); var march = new XYChart.Series<String, Number>();
march.setName("March"); march.setName("March");
IntStream.range(0, countries.size()).forEach(i -> march.getData().add( IntStream.range(0, countries.size()).forEach(i -> march.getData().add(
new XYChart.Data<>(countries.get(i), rnd.nextInt(10, 80)) new XYChart.Data<>(countries.get(i), rnd.nextInt(10, 80))
)); ));
var chart = stacked ? new StackedBarChart<>(x, y) : new BarChart<>(x, y); var chart = stacked ? new StackedBarChart<>(x, y) : new BarChart<>(x, y);
@ -198,13 +221,13 @@ public class ChartPage extends AbstractPage {
var series1 = new XYChart.Series<Number, Number>(); var series1 = new XYChart.Series<Number, Number>();
series1.setName(FAKER.commerce().productName()); series1.setName(FAKER.commerce().productName());
IntStream.range(1, 10).forEach(i -> series1.getData().add( IntStream.range(1, 10).forEach(i -> series1.getData().add(
new XYChart.Data<>(rnd.nextInt(1, 53), rnd.nextInt(10, 80), rnd.nextDouble(1, 10)) new XYChart.Data<>(rnd.nextInt(1, 53), rnd.nextInt(10, 80), rnd.nextDouble(1, 10))
)); ));
var series2 = new XYChart.Series<Number, Number>(); var series2 = new XYChart.Series<Number, Number>();
series2.setName(FAKER.commerce().productName()); series2.setName(FAKER.commerce().productName());
IntStream.range(1, 10).forEach(i -> series2.getData().add( IntStream.range(1, 10).forEach(i -> series2.getData().add(
new XYChart.Data<>(rnd.nextInt(1, 53), rnd.nextInt(10, 80), rnd.nextDouble(1, 10)) new XYChart.Data<>(rnd.nextInt(1, 53), rnd.nextInt(10, 80), rnd.nextDouble(1, 10))
)); ));
var chart = new BubbleChart<>(x, y); var chart = new BubbleChart<>(x, y);
@ -227,13 +250,13 @@ public class ChartPage extends AbstractPage {
var series1 = new XYChart.Series<String, Number>(); var series1 = new XYChart.Series<String, Number>();
series1.setName(FAKER.stock().nsdqSymbol()); series1.setName(FAKER.stock().nsdqSymbol());
IntStream.range(1, 12).forEach(i -> series1.getData().add( IntStream.range(1, 12).forEach(i -> series1.getData().add(
new XYChart.Data<>(Month.of(i).getDisplayName(TextStyle.SHORT, Locale.getDefault()), rnd.nextInt(10, 80)) new XYChart.Data<>(Month.of(i).getDisplayName(TextStyle.SHORT, Locale.getDefault()), rnd.nextInt(10, 80))
)); ));
var series2 = new XYChart.Series<String, Number>(); var series2 = new XYChart.Series<String, Number>();
series2.setName(FAKER.stock().nsdqSymbol()); series2.setName(FAKER.stock().nsdqSymbol());
IntStream.range(1, 12).forEach(i -> series2.getData().add( IntStream.range(1, 12).forEach(i -> series2.getData().add(
new XYChart.Data<>(Month.of(i).getDisplayName(TextStyle.SHORT, Locale.getDefault()), rnd.nextInt(10, 80)) new XYChart.Data<>(Month.of(i).getDisplayName(TextStyle.SHORT, Locale.getDefault()), rnd.nextInt(10, 80))
)); ));
var chart = new LineChart<>(x, y); var chart = new LineChart<>(x, y);
@ -247,11 +270,11 @@ public class ChartPage extends AbstractPage {
final var rnd = FAKER.random(); final var rnd = FAKER.random();
ObservableList<PieChart.Data> data = FXCollections.observableArrayList( ObservableList<PieChart.Data> data = FXCollections.observableArrayList(
new PieChart.Data(FAKER.food().fruit(), rnd.nextInt(10, 30)), new PieChart.Data(FAKER.food().fruit(), rnd.nextInt(10, 30)),
new PieChart.Data(FAKER.food().fruit(), rnd.nextInt(10, 30)), new PieChart.Data(FAKER.food().fruit(), rnd.nextInt(10, 30)),
new PieChart.Data(FAKER.food().fruit(), rnd.nextInt(10, 30)), new PieChart.Data(FAKER.food().fruit(), rnd.nextInt(10, 30)),
new PieChart.Data(FAKER.food().fruit(), rnd.nextInt(10, 30)), new PieChart.Data(FAKER.food().fruit(), rnd.nextInt(10, 30)),
new PieChart.Data(FAKER.food().fruit(), rnd.nextInt(10, 30)) new PieChart.Data(FAKER.food().fruit(), rnd.nextInt(10, 30))
); );
var chart = new PieChart(data); var chart = new PieChart(data);
@ -273,13 +296,13 @@ public class ChartPage extends AbstractPage {
var series1 = new XYChart.Series<Number, Number>(); var series1 = new XYChart.Series<Number, Number>();
series1.setName("Equities"); series1.setName("Equities");
IntStream.range(1, 10).forEach(i -> series1.getData().add( IntStream.range(1, 10).forEach(i -> series1.getData().add(
new XYChart.Data<>(rnd.nextDouble(0, 10), rnd.nextDouble(-100, 500)) new XYChart.Data<>(rnd.nextDouble(0, 10), rnd.nextDouble(-100, 500))
)); ));
var series2 = new XYChart.Series<Number, Number>(); var series2 = new XYChart.Series<Number, Number>();
series2.setName("Mutual funds"); series2.setName("Mutual funds");
IntStream.range(1, 10).forEach(i -> series2.getData().add( IntStream.range(1, 10).forEach(i -> series2.getData().add(
new XYChart.Data<>(rnd.nextDouble(0, 10), rnd.nextDouble(-100, 500)) new XYChart.Data<>(rnd.nextDouble(0, 10), rnd.nextDouble(-100, 500))
)); ));
var chart = new ScatterChart<>(x, y); var chart = new ScatterChart<>(x, y);
@ -311,9 +334,9 @@ public class ChartPage extends AbstractPage {
public static Example find(String name) { public static Example find(String name) {
return Arrays.stream(Example.values()) return Arrays.stream(Example.values())
.filter(example -> Objects.equals(example.getName(), name)) .filter(example -> Objects.equals(example.getName(), name))
.findFirst() .findFirst()
.orElse(null); .orElse(null);
} }
} }
} }

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page.components; package atlantafx.sampler.page.components;
import atlantafx.sampler.page.AbstractPage; import atlantafx.sampler.page.AbstractPage;
@ -13,7 +14,9 @@ public class CheckBoxPage extends AbstractPage {
public static final String NAME = "CheckBox"; public static final String NAME = "CheckBox";
@Override @Override
public String getName() { return NAME; } public String getName() {
return NAME;
}
private CheckBox basicCheck; private CheckBox basicCheck;
private CheckBox indeterminateCheck; private CheckBox indeterminateCheck;
@ -25,10 +28,10 @@ public class CheckBoxPage extends AbstractPage {
private void createView() { private void createView() {
setUserContent(new FlowPane( setUserContent(new FlowPane(
PAGE_HGAP, PAGE_VGAP, PAGE_HGAP, PAGE_VGAP,
basicSample(), basicSample(),
indeterminateSample(), indeterminateSample(),
disabledSample() disabledSample()
)); ));
} }
@ -57,8 +60,8 @@ public class CheckBoxPage extends AbstractPage {
indeterminateCheck.setDisable(true); indeterminateCheck.setDisable(true);
return new SampleBlock( return new SampleBlock(
"Disabled", "Disabled",
new HBox(SampleBlock.BLOCK_HGAP, basicCheck, indeterminateCheck) new HBox(SampleBlock.BLOCK_HGAP, basicCheck, indeterminateCheck)
); );
} }
@ -68,20 +71,22 @@ public class CheckBoxPage extends AbstractPage {
var normalBox = basicCheck.lookup(".box"); var normalBox = basicCheck.lookup(".box");
var indeterminateBox = indeterminateCheck.lookup(".box"); var indeterminateBox = indeterminateCheck.lookup(".box");
if (normalBox == null || indeterminateBox == null) { return; } if (normalBox == null || indeterminateBox == null) {
return;
}
// force layout to obtain node bounds // force layout to obtain node bounds
((StackPane) normalBox).layout(); ((StackPane) normalBox).layout();
((StackPane) indeterminateBox).layout(); ((StackPane) indeterminateBox).layout();
System.out.printf("Basic: height = %.2f , width = %.2f\n", System.out.printf("Basic: height = %.2f , width = %.2f\n",
normalBox.getBoundsInParent().getHeight(), normalBox.getBoundsInParent().getHeight(),
normalBox.getBoundsInParent().getWidth() normalBox.getBoundsInParent().getWidth()
); );
System.out.printf("Indeterminate: height = %.2f , width = %.2f\n", System.out.printf("Indeterminate: height = %.2f , width = %.2f\n",
indeterminateBox.getBoundsInParent().getHeight(), indeterminateBox.getBoundsInParent().getHeight(),
indeterminateBox.getBoundsInParent().getWidth() indeterminateBox.getBoundsInParent().getWidth()
); );
} }
} }

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page.components; package atlantafx.sampler.page.components;
import static atlantafx.sampler.page.SampleBlock.BLOCK_HGAP; import static atlantafx.sampler.page.SampleBlock.BLOCK_HGAP;
@ -21,12 +22,14 @@ public class ColorPickerPage extends AbstractPage {
public static final String NAME = "ColorPicker"; public static final String NAME = "ColorPicker";
@Override @Override
public String getName() { return NAME; } public String getName() {
return NAME;
}
public ColorPickerPage() { public ColorPickerPage() {
super(); super();
setUserContent(new VBox( setUserContent(new VBox(
new SampleBlock("Playground", createPlayground()) new SampleBlock("Playground", createPlayground())
)); ));
} }
@ -38,7 +41,9 @@ public class ColorPickerPage extends AbstractPage {
labelToggle.setSelected(true); labelToggle.setSelected(true);
labelToggle.selectedProperty().addListener((obs, old, val) -> { labelToggle.selectedProperty().addListener((obs, old, val) -> {
colorPicker.setStyle("-fx-color-label-visible: false;"); colorPicker.setStyle("-fx-color-label-visible: false;");
if (val) { colorPicker.setStyle("-fx-color-label-visible: true;"); } if (val) {
colorPicker.setStyle("-fx-color-label-visible: true;");
}
}); });
var disableToggle = new ToggleSwitch(); var disableToggle = new ToggleSwitch();
@ -56,9 +61,9 @@ public class ColorPickerPage extends AbstractPage {
grid.add(disableToggle, 2, 2); grid.add(disableToggle, 2, 2);
grid.getColumnConstraints().setAll( grid.getColumnConstraints().setAll(
new ColumnConstraints(200), new ColumnConstraints(200),
new ColumnConstraints(), new ColumnConstraints(),
new ColumnConstraints() new ColumnConstraints()
); );
return grid; return grid;
@ -78,11 +83,13 @@ public class ColorPickerPage extends AbstractPage {
var choice = new ChoiceBox<String>(); var choice = new ChoiceBox<String>();
choice.getItems().setAll(optDefault, optButton, optSplitButton); choice.getItems().setAll(optDefault, optButton, optSplitButton);
choice.getSelectionModel().selectedItemProperty().addListener((obs, old, val) -> { choice.getSelectionModel().selectedItemProperty().addListener((obs, old, val) -> {
if (val == null) { return; } if (val == null) {
return;
}
colorPicker.getStyleClass().removeAll( colorPicker.getStyleClass().removeAll(
ColorPicker.STYLE_CLASS_BUTTON, ColorPicker.STYLE_CLASS_BUTTON,
ColorPicker.STYLE_CLASS_SPLIT_BUTTON ColorPicker.STYLE_CLASS_SPLIT_BUTTON
); );
if (optButton.equals(val)) { if (optButton.equals(val)) {

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page.components; package atlantafx.sampler.page.components;
import static atlantafx.base.theme.Styles.STATE_DANGER; import static atlantafx.base.theme.Styles.STATE_DANGER;
@ -32,12 +33,14 @@ public class ComboBoxPage extends AbstractPage {
private static final int PREF_WIDTH = 200; private static final int PREF_WIDTH = 200;
@Override @Override
public String getName() { return NAME; } public String getName() {
return NAME;
}
public ComboBoxPage() { public ComboBoxPage() {
super(); super();
setUserContent(new VBox( setUserContent(new VBox(
new SampleBlock("Examples", createPlayground()) new SampleBlock("Examples", createPlayground())
)); ));
} }
@ -73,8 +76,8 @@ public class ComboBoxPage extends AbstractPage {
// with icons // with icons
var badges = IntStream.range(0, 5).boxed() var badges = IntStream.range(0, 5).boxed()
.map(i -> new Badge(FAKER.hipster().word(), randomIcon())) .map(i -> new Badge(FAKER.hipster().word(), randomIcon()))
.collect(Collectors.toCollection(FXCollections::observableArrayList)); .collect(Collectors.toCollection(FXCollections::observableArrayList));
var badgeCombo = new ComboBox<>(badges); var badgeCombo = new ComboBox<>(badges);
badgeCombo.setPrefWidth(PREF_WIDTH); badgeCombo.setPrefWidth(PREF_WIDTH);
badgeCombo.setButtonCell(new BadgeCell()); badgeCombo.setButtonCell(new BadgeCell());
@ -165,7 +168,9 @@ public class ComboBoxPage extends AbstractPage {
private ComboBox<String> createComboBoxWith(Consumer<ComboBox<String>> mutator) { private ComboBox<String> createComboBoxWith(Consumer<ComboBox<String>> mutator) {
var c = new ComboBox<String>(); var c = new ComboBox<String>();
c.setPrefWidth(PREF_WIDTH); c.setPrefWidth(PREF_WIDTH);
if (mutator != null) { mutator.accept(c); } if (mutator != null) {
mutator.accept(c);
}
return c; return c;
} }
@ -176,7 +181,9 @@ public class ComboBoxPage extends AbstractPage {
private ChoiceBox<String> createChoiceBoxWith(Consumer<ChoiceBox<String>> mutator) { private ChoiceBox<String> createChoiceBoxWith(Consumer<ChoiceBox<String>> mutator) {
var c = new ChoiceBox<String>(); var c = new ChoiceBox<String>();
c.setPrefWidth(PREF_WIDTH); c.setPrefWidth(PREF_WIDTH);
if (mutator != null) { mutator.accept(c); } if (mutator != null) {
mutator.accept(c);
}
return c; return c;
} }
@ -187,7 +194,8 @@ public class ComboBoxPage extends AbstractPage {
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
@SuppressWarnings("unused") @SuppressWarnings("unused")
private record Badge(String text, Ikon icon) { } private record Badge(String text, Ikon icon) {
}
private static class BadgeCell extends ListCell<Badge> { private static class BadgeCell extends ListCell<Badge> {

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page.components; package atlantafx.sampler.page.components;
import static atlantafx.base.theme.Styles.STATE_DANGER; import static atlantafx.base.theme.Styles.STATE_DANGER;
@ -19,18 +20,20 @@ public class CustomTextFieldPage extends AbstractPage {
private static final int PREF_WIDTH = 120; private static final int PREF_WIDTH = 120;
@Override @Override
public String getName() { return NAME; } public String getName() {
return NAME;
}
public CustomTextFieldPage() { public CustomTextFieldPage() {
super(); super();
setUserContent(new FlowPane( setUserContent(new FlowPane(
PAGE_HGAP, PAGE_VGAP, PAGE_HGAP, PAGE_VGAP,
leftIconSample(), leftIconSample(),
rightIconSample(), rightIconSample(),
bothIconsSample(), bothIconsSample(),
successSample(), successSample(),
dangerSample(), dangerSample(),
passwordSample() passwordSample()
)); ));
} }

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page.components; package atlantafx.sampler.page.components;
import static atlantafx.base.theme.Styles.BUTTON_ICON; import static atlantafx.base.theme.Styles.BUTTON_ICON;
@ -53,19 +54,21 @@ public class DatePickerPage extends AbstractPage {
private static final int INLINE_DATE_PICKER_COL = 0; private static final int INLINE_DATE_PICKER_COL = 0;
private static final int INLINE_DATE_PICKER_ROW = 4; private static final int INLINE_DATE_PICKER_ROW = 4;
private static final CSSFragment NO_YEAR_MONTH_STYLE = new CSSFragment(""" private static final CSSFragment NO_YEAR_MONTH_STYLE = new CSSFragment("""
.date-picker-popup >.month-year-pane { .date-picker-popup >.month-year-pane {
visibility: hidden; visibility: hidden;
-fx-min-width: 0; -fx-min-width: 0;
-fx-pref-width: 0; -fx-pref-width: 0;
-fx-max-width: 0; -fx-max-width: 0;
-fx-min-height: 0; -fx-min-height: 0;
-fx-pref-height: 0; -fx-pref-height: 0;
-fx-max-height: 0; -fx-max-height: 0;
} }
"""); """);
@Override @Override
public String getName() { return NAME; } public String getName() {
return NAME;
}
private final BooleanProperty weekNumProperty = new SimpleBooleanProperty(); private final BooleanProperty weekNumProperty = new SimpleBooleanProperty();
private final BooleanProperty showClockProperty = new SimpleBooleanProperty(); private final BooleanProperty showClockProperty = new SimpleBooleanProperty();
@ -78,7 +81,7 @@ public class DatePickerPage extends AbstractPage {
public DatePickerPage() { public DatePickerPage() {
super(); super();
setUserContent(new VBox( setUserContent(new VBox(
new SampleBlock("Playground", createPlayground()) new SampleBlock("Playground", createPlayground())
)); ));
} }
@ -114,14 +117,14 @@ public class DatePickerPage extends AbstractPage {
var chronologyToggle = new ToggleSwitch("Second chronology"); var chronologyToggle = new ToggleSwitch("Second chronology");
chronologyToggle.selectedProperty().addListener( chronologyToggle.selectedProperty().addListener(
(obs, old, val) -> popupDatePicker.setChronology(val ? HijrahChronology.INSTANCE : null) (obs, old, val) -> popupDatePicker.setChronology(val ? HijrahChronology.INSTANCE : null)
); );
var editableToggle = new ToggleSwitch("Editable"); var editableToggle = new ToggleSwitch("Editable");
editableProperty.bind(editableToggle.selectedProperty()); editableProperty.bind(editableToggle.selectedProperty());
// clear selected value to demonstrate prompt text // clear selected value to demonstrate prompt text
editableProperty.addListener( editableProperty.addListener(
(obs, old, val) -> popupDatePicker.setValue(val ? null : TODAY) (obs, old, val) -> popupDatePicker.setValue(val ? null : TODAY)
); );
var offPastDatesToggle = new ToggleSwitch("No past dates"); var offPastDatesToggle = new ToggleSwitch("No past dates");
@ -140,14 +143,14 @@ public class DatePickerPage extends AbstractPage {
disableProperty.bind(disablePickerToggle.selectedProperty()); disableProperty.bind(disablePickerToggle.selectedProperty());
var controls = new VBox( var controls = new VBox(
BLOCK_VGAP, BLOCK_VGAP,
weekNumToggle, weekNumToggle,
showClockToggle, showClockToggle,
showYearMonthToggle, showYearMonthToggle,
chronologyToggle, chronologyToggle,
editableToggle, editableToggle,
offPastDatesToggle, offPastDatesToggle,
disablePickerToggle disablePickerToggle
); );
controls.setAlignment(Pos.CENTER_RIGHT); controls.setAlignment(Pos.CENTER_RIGHT);
@ -193,7 +196,7 @@ public class DatePickerPage extends AbstractPage {
datePicker.setBottomNode(colorSelector); datePicker.setBottomNode(colorSelector);
datePicker.topNodeProperty().bind(Bindings.createObjectBinding( datePicker.topNodeProperty().bind(Bindings.createObjectBinding(
() -> showClockProperty.get() ? clock : null, showClockProperty) () -> showClockProperty.get() ? clock : null, showClockProperty)
); );
return datePicker; return datePicker;
@ -205,13 +208,17 @@ public class DatePickerPage extends AbstractPage {
@Override @Override
public String toString(LocalDate localDate) { public String toString(LocalDate localDate) {
if (localDate == null) { return ""; } if (localDate == null) {
return "";
}
return DATE_FORMATTER.format(localDate); return DATE_FORMATTER.format(localDate);
} }
@Override @Override
public LocalDate fromString(String dateString) { public LocalDate fromString(String dateString) {
if (dateString == null || dateString.trim().isEmpty()) { return null; } if (dateString == null || dateString.trim().isEmpty()) {
return null;
}
try { try {
return LocalDate.parse(dateString, DATE_FORMATTER); return LocalDate.parse(dateString, DATE_FORMATTER);
} catch (Exception e) { } catch (Exception e) {
@ -233,26 +240,26 @@ public class DatePickerPage extends AbstractPage {
public Clock() { public Clock() {
var clockLabel = new Label( var clockLabel = new Label(
TIME_FORMATTER.format(LocalTime.now(ZoneId.systemDefault())) TIME_FORMATTER.format(LocalTime.now(ZoneId.systemDefault()))
); );
clockLabel.getStyleClass().add(Styles.TITLE_2); clockLabel.getStyleClass().add(Styles.TITLE_2);
var dateLabel = new Label( var dateLabel = new Label(
DateTimeFormatter.ofPattern("EEEE, LLLL dd, yyyy").format(LocalDate.now(ZoneId.systemDefault())) DateTimeFormatter.ofPattern("EEEE, LLLL dd, yyyy").format(LocalDate.now(ZoneId.systemDefault()))
); );
setStyle(""" setStyle("""
-fx-border-width: 0 0 0.5 0; -fx-border-width: 0 0 0.5 0;
-fx-border-color: -color-border-default;""" -fx-border-color: -color-border-default;"""
); );
setSpacing(BLOCK_VGAP); setSpacing(BLOCK_VGAP);
getChildren().setAll(clockLabel, dateLabel); getChildren().setAll(clockLabel, dateLabel);
var t = new Timeline(new KeyFrame( var t = new Timeline(new KeyFrame(
Duration.seconds(1), Duration.seconds(1),
e -> clockLabel.setText( e -> clockLabel.setText(
TIME_FORMATTER.format(LocalTime.now(ZoneId.systemDefault())) TIME_FORMATTER.format(LocalTime.now(ZoneId.systemDefault()))
) )
)); ));
t.setCycleCount(Animation.INDEFINITE); t.setCycleCount(Animation.INDEFINITE);
t.playFromStart(); t.playFromStart();
@ -277,16 +284,20 @@ public class DatePickerPage extends AbstractPage {
resetBtn.setOnAction(e -> style.set(null)); resetBtn.setOnAction(e -> style.set(null));
style.addListener((obs, old, val) -> { style.addListener((obs, old, val) -> {
if (old != null) { old.removeFrom(parent); } if (old != null) {
if (val != null) { val.addTo(parent); } old.removeFrom(parent);
}
if (val != null) {
val.addTo(parent);
}
}); });
setAlignment(Pos.CENTER); setAlignment(Pos.CENTER);
getChildren().setAll( getChildren().setAll(
colorButton("-color-accent-emphasis", "-color-fg-emphasis"), colorButton("-color-accent-emphasis", "-color-fg-emphasis"),
colorButton("-color-success-emphasis", "-color-fg-emphasis"), colorButton("-color-success-emphasis", "-color-fg-emphasis"),
colorButton("-color-danger-emphasis", "-color-fg-emphasis"), colorButton("-color-danger-emphasis", "-color-fg-emphasis"),
resetBtn resetBtn
); );
getStyleClass().add("color-selector"); getStyleClass().add("color-selector");
} }
@ -305,19 +316,19 @@ public class DatePickerPage extends AbstractPage {
private void updateStyle(String bgColorName, String fgColorName) { private void updateStyle(String bgColorName, String fgColorName) {
style.set(new CSSFragment(String.format(""" style.set(new CSSFragment(String.format("""
.date-picker-popup { .date-picker-popup {
-color-date-border: %s; -color-date-border: %s;
-color-date-month-year-bg: %s; -color-date-month-year-bg: %s;
-color-date-month-year-fg: %s; -color-date-month-year-fg: %s;
} }
.date-picker-popup >.top-node { .date-picker-popup >.top-node {
-fx-background-color: %s; -fx-background-color: %s;
-color-fg-default: %s; -color-fg-default: %s;
-color-border-default: %s; -color-border-default: %s;
-fx-border-color: %s; -fx-border-color: %s;
}""", }""",
bgColorName, bgColorName, fgColorName, bgColorName, bgColorName, fgColorName,
bgColorName, fgColorName, fgColorName, fgColorName bgColorName, fgColorName, fgColorName, fgColorName
))); )));
} }
} }

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page.components; package atlantafx.sampler.page.components;
import static atlantafx.sampler.page.SampleBlock.BLOCK_HGAP; import static atlantafx.sampler.page.SampleBlock.BLOCK_HGAP;
@ -37,7 +38,9 @@ public class DialogPage extends AbstractPage {
public static final String NAME = "Dialog"; public static final String NAME = "Dialog";
@Override @Override
public String getName() { return NAME; } public String getName() {
return NAME;
}
private final BooleanProperty showHeaderProperty = new SimpleBooleanProperty(true); private final BooleanProperty showHeaderProperty = new SimpleBooleanProperty(true);
private final BooleanProperty minDecorationsProperty = new SimpleBooleanProperty(true); private final BooleanProperty minDecorationsProperty = new SimpleBooleanProperty(true);
@ -60,21 +63,21 @@ public class DialogPage extends AbstractPage {
controls.setAlignment(Pos.CENTER); controls.setAlignment(Pos.CENTER);
var samples = new FlowPane( var samples = new FlowPane(
PAGE_HGAP, PAGE_VGAP, PAGE_HGAP, PAGE_VGAP,
infoDialogSample(), infoDialogSample(),
warningDialogSample(), warningDialogSample(),
errorDialogSample(), errorDialogSample(),
exceptionDialogSample(), exceptionDialogSample(),
confirmationDialogSample(), confirmationDialogSample(),
textInputDialogSample(), textInputDialogSample(),
choiceDialogSample() choiceDialogSample()
); );
setUserContent(new VBox( setUserContent(new VBox(
10, 10,
controls, controls,
new Separator(Orientation.HORIZONTAL), new Separator(Orientation.HORIZONTAL),
samples samples
)); ));
} }

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page.components; package atlantafx.sampler.page.components;
import static atlantafx.sampler.page.SampleBlock.BLOCK_VGAP; import static atlantafx.sampler.page.SampleBlock.BLOCK_VGAP;
@ -25,7 +26,9 @@ public class HTMLEditorPage extends AbstractPage {
public static final String NAME = "HTMLEditor"; public static final String NAME = "HTMLEditor";
@Override @Override
public String getName() { return NAME; } public String getName() {
return NAME;
}
private HTMLEditor editor = createEditor(); private HTMLEditor editor = createEditor();
@ -46,9 +49,9 @@ public class HTMLEditorPage extends AbstractPage {
private SampleBlock editorSample() { private SampleBlock editorSample() {
var description = new Text( var description = new Text(
"HTMLEditor toolbar buttons use images from 'com/sun/javafx/scene/control/skin/modena'. " + "HTMLEditor toolbar buttons use images from 'com/sun/javafx/scene/control/skin/modena'. " +
"In opposite, since AtlantaFX themes are also distributed as single CSS files, it contains no images. " + "In opposite, since AtlantaFX themes are also distributed as single CSS files, it contains no images. " +
"Unfortunately reusing Modena resources isn't possible, because the package isn't opened in OpenJFX 'module-info'." "Unfortunately reusing Modena resources isn't possible, because the package isn't opened in OpenJFX 'module-info'."
); );
var fixToggle = new ToggleSwitch("Apply Fix"); var fixToggle = new ToggleSwitch("Apply Fix");
@ -84,15 +87,15 @@ public class HTMLEditorPage extends AbstractPage {
Theme samplerTheme = tm.getTheme(); Theme samplerTheme = tm.getTheme();
HighlightJSTheme hlTheme = tm.getMatchingSourceCodeHighlightTheme(samplerTheme); HighlightJSTheme hlTheme = tm.getMatchingSourceCodeHighlightTheme(samplerTheme);
return "<!DOCTYPE html>" + return "<!DOCTYPE html>" +
"<html>" + "<html>" +
"<body style=\"" + "<body style=\"" +
"background-color:" + hlTheme.getBackground() + ";" + "background-color:" + hlTheme.getBackground() + ";" +
"color:" + hlTheme.getForeground() + ";" + "color:" + hlTheme.getForeground() + ";" +
"font-family:" + tm.getFontFamily() + ";" + "font-family:" + tm.getFontFamily() + ";" +
"font-size:" + tm.getFontSize() + "px;" + "font-size:" + tm.getFontSize() + "px;" +
"\">" + "\">" +
String.join("<br/><br/>", FAKER.lorem().paragraphs(10)) + String.join("<br/><br/>", FAKER.lorem().paragraphs(10)) +
"</body>" + "</body>" +
"</html>"; "</html>";
} }
} }

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page.components; package atlantafx.sampler.page.components;
import static atlantafx.base.theme.Styles.BUTTON_ICON; import static atlantafx.base.theme.Styles.BUTTON_ICON;
@ -28,15 +29,17 @@ public class InputGroupPage extends AbstractPage {
public static final String NAME = "Input Group"; public static final String NAME = "Input Group";
@Override @Override
public String getName() { return NAME; } public String getName() {
return NAME;
}
public InputGroupPage() { public InputGroupPage() {
super(); super();
setUserContent(new VBox( setUserContent(new VBox(
Page.PAGE_VGAP, Page.PAGE_VGAP,
expandingHBox(httpMethodSample(), passwordSample()), expandingHBox(httpMethodSample(), passwordSample()),
expandingHBox(networkSample(), dropdownSample()), expandingHBox(networkSample(), dropdownSample()),
labelSample() labelSample()
)); ));
} }
@ -156,10 +159,10 @@ public class InputGroupPage extends AbstractPage {
// ~ // ~
var flowPane = new FlowPane( var flowPane = new FlowPane(
BLOCK_HGAP, BLOCK_VGAP, BLOCK_HGAP, BLOCK_VGAP,
sample1, sample1,
sample2, sample2,
sample3 sample3
); );
return new SampleBlock("Label & TextField", flowPane); return new SampleBlock("Label & TextField", flowPane);

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page.components; package atlantafx.sampler.page.components;
import static atlantafx.sampler.page.SampleBlock.BLOCK_HGAP; import static atlantafx.sampler.page.SampleBlock.BLOCK_HGAP;
@ -18,7 +19,9 @@ public class LabelPage extends AbstractPage {
public static final String NAME = "Label"; public static final String NAME = "Label";
@Override @Override
public String getName() { return NAME; } public String getName() {
return NAME;
}
public LabelPage() { public LabelPage() {
super(); super();
@ -27,8 +30,8 @@ public class LabelPage extends AbstractPage {
private void createView() { private void createView() {
setUserContent(new VBox( setUserContent(new VBox(
PAGE_VGAP, PAGE_VGAP,
expandingHBox(colorSample()) expandingHBox(colorSample())
)); ));
} }
@ -54,14 +57,14 @@ public class LabelPage extends AbstractPage {
subtleLabel.getStyleClass().add(Styles.TEXT_SUBTLE); subtleLabel.getStyleClass().add(Styles.TEXT_SUBTLE);
var content = new VBox( var content = new VBox(
BLOCK_VGAP, BLOCK_VGAP,
new Label("You can also use pseudo-classes to set Label color."), new Label("You can also use pseudo-classes to set Label color."),
new Label("Note that icon inherits label color by default."), new Label("Note that icon inherits label color by default."),
new FlowPane( new FlowPane(
BLOCK_HGAP, BLOCK_VGAP, BLOCK_HGAP, BLOCK_VGAP,
defaultLabel, accentLabel, successLabel, warningLabel, dangerLabel, defaultLabel, accentLabel, successLabel, warningLabel, dangerLabel,
mutedLabel, subtleLabel mutedLabel, subtleLabel
)); ));
return new SampleBlock("Colors", content); return new SampleBlock("Colors", content);
} }

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page.components; package atlantafx.sampler.page.components;
import static atlantafx.base.theme.Styles.ACCENT; import static atlantafx.base.theme.Styles.ACCENT;
@ -45,7 +46,9 @@ public class ListPage extends AbstractPage {
public static final String NAME = "ListView"; public static final String NAME = "ListView";
@Override @Override
public String getName() { return NAME; } public String getName() {
return NAME;
}
private final List<Book> dataList = generate(() -> Book.random(FAKER), 50); private final List<Book> dataList = generate(() -> Book.random(FAKER), 50);
private final StringConverter<Book> bookStringConverter = new BookStringConverter(dataList); private final StringConverter<Book> bookStringConverter = new BookStringConverter(dataList);
@ -62,20 +65,26 @@ public class ListPage extends AbstractPage {
private VBox createPlayground() { private VBox createPlayground() {
var borderedToggle = new ToggleSwitch("Bordered"); var borderedToggle = new ToggleSwitch("Bordered");
borderedToggle.selectedProperty().addListener((obs, old, value) -> toggleListProperty(lv -> toggleStyleClass(lv, BORDERED))); borderedToggle.selectedProperty()
.addListener((obs, old, value) -> toggleListProperty(lv -> toggleStyleClass(lv, BORDERED)));
var denseToggle = new ToggleSwitch("Dense"); var denseToggle = new ToggleSwitch("Dense");
denseToggle.selectedProperty().addListener((obs, old, value) -> toggleListProperty(lv -> toggleStyleClass(lv, DENSE))); denseToggle.selectedProperty()
.addListener((obs, old, value) -> toggleListProperty(lv -> toggleStyleClass(lv, DENSE)));
var stripedToggle = new ToggleSwitch("Striped"); var stripedToggle = new ToggleSwitch("Striped");
stripedToggle.selectedProperty().addListener((obs, old, value) -> toggleListProperty(lv -> toggleStyleClass(lv, STRIPED))); stripedToggle.selectedProperty()
.addListener((obs, old, value) -> toggleListProperty(lv -> toggleStyleClass(lv, STRIPED)));
var edge2edgeToggle = new ToggleSwitch("Edge to edge"); var edge2edgeToggle = new ToggleSwitch("Edge to edge");
edge2edgeToggle.selectedProperty().addListener((obs, old, value) -> toggleListProperty(lv -> toggleStyleClass(lv, Tweaks.EDGE_TO_EDGE))); edge2edgeToggle.selectedProperty()
.addListener((obs, old, value) -> toggleListProperty(lv -> toggleStyleClass(lv, Tweaks.EDGE_TO_EDGE)));
var disableToggle = new ToggleSwitch("Disable"); var disableToggle = new ToggleSwitch("Disable");
disableToggle.selectedProperty().addListener((obs, old, val) -> findDisplayedList().ifPresent(lv -> { disableToggle.selectedProperty().addListener((obs, old, val) -> findDisplayedList().ifPresent(lv -> {
if (val != null) { lv.setDisable(val); } if (val != null) {
lv.setDisable(val);
}
})); }));
var controls = new HBox(BLOCK_HGAP, borderedToggle, denseToggle, stripedToggle, edge2edgeToggle); var controls = new HBox(BLOCK_HGAP, borderedToggle, denseToggle, stripedToggle, edge2edgeToggle);
@ -84,11 +93,11 @@ public class ListPage extends AbstractPage {
VBox.setVgrow(listWrapper, Priority.ALWAYS); VBox.setVgrow(listWrapper, Priority.ALWAYS);
var playground = new VBox( var playground = new VBox(
BLOCK_VGAP, BLOCK_VGAP,
new HBox(new Label("Select an example:"), new Spacer(), disableToggle), new HBox(new Label("Select an example:"), new Spacer(), disableToggle),
exampleSelect, exampleSelect,
listWrapper, listWrapper,
controls controls
); );
playground.setMinHeight(100); playground.setMinHeight(100);
@ -101,7 +110,9 @@ public class ListPage extends AbstractPage {
select.getItems().setAll(Example.values()); select.getItems().setAll(Example.values());
select.getSelectionModel().selectedItemProperty().addListener((obs, old, val) -> { select.getSelectionModel().selectedItemProperty().addListener((obs, old, val) -> {
if (val == null) { return; } if (val == null) {
return;
}
ListView<?> newList = createList(val); ListView<?> newList = createList(val);
@ -139,24 +150,38 @@ public class ListPage extends AbstractPage {
private Optional<ListView<?>> findDisplayedList() { private Optional<ListView<?>> findDisplayedList() {
return listWrapper.getChildren().size() > 0 ? return listWrapper.getChildren().size() > 0 ?
Optional.of((ListView<?>) listWrapper.getChildren().get(0)) : Optional.of((ListView<?>) listWrapper.getChildren().get(0)) :
Optional.empty(); Optional.empty();
} }
private void toggleListProperty(Consumer<ListView<?>> consumer) { private void toggleListProperty(Consumer<ListView<?>> consumer) {
findDisplayedList().ifPresent(lv -> { findDisplayedList().ifPresent(lv -> {
if (consumer != null) { consumer.accept(lv); } if (consumer != null) {
consumer.accept(lv);
}
}); });
} }
private ListView<?> createList(Example example) { private ListView<?> createList(Example example) {
switch (example) { switch (example) {
case TEXT -> { return stringList(); } case TEXT -> {
case EDITABLE -> { return editableList(); } return stringList();
case CHECK_BOX -> { return checkBoxList(); } }
case CHOICE_BOX -> { return choiceBoxList(); } case EDITABLE -> {
case COMBO_BOX -> { return comboBoxList(); } return editableList();
case NESTED_CONTROLS -> { return nestedControlsList(); } }
case CHECK_BOX -> {
return checkBoxList();
}
case CHOICE_BOX -> {
return choiceBoxList();
}
case COMBO_BOX -> {
return comboBoxList();
}
case NESTED_CONTROLS -> {
return nestedControlsList();
}
default -> throw new IllegalArgumentException("Unexpected enum value: " + example); default -> throw new IllegalArgumentException("Unexpected enum value: " + example);
} }
} }
@ -172,8 +197,8 @@ public class ListPage extends AbstractPage {
lv.setEditable(true); lv.setEditable(true);
lv.setCellFactory(TextFieldListCell.forListView()); lv.setCellFactory(TextFieldListCell.forListView());
lv.getItems().setAll( lv.getItems().setAll(
// small size to see the empty cells // small size to see the empty cells
dataList.stream().limit(5).map(bookStringConverter::toString).collect(Collectors.toList()) dataList.stream().limit(5).map(bookStringConverter::toString).collect(Collectors.toList())
); );
return lv; return lv;
} }
@ -188,7 +213,8 @@ public class ListPage extends AbstractPage {
private ListView<Book> choiceBoxList() { private ListView<Book> choiceBoxList() {
var lv = new ListView<Book>(); var lv = new ListView<Book>();
lv.setEditable(true); lv.setEditable(true);
lv.setCellFactory(ChoiceBoxListCell.forListView(bookStringConverter, dataList.subList(0, 10).toArray(Book[]::new))); lv.setCellFactory(
ChoiceBoxListCell.forListView(bookStringConverter, dataList.subList(0, 10).toArray(Book[]::new)));
lv.getItems().setAll(dataList.stream().limit(10).collect(Collectors.toList())); lv.getItems().setAll(dataList.stream().limit(10).collect(Collectors.toList()));
return lv; return lv;
} }
@ -196,7 +222,8 @@ public class ListPage extends AbstractPage {
private ListView<Book> comboBoxList() { private ListView<Book> comboBoxList() {
var lv = new ListView<Book>(); var lv = new ListView<Book>();
lv.setEditable(true); lv.setEditable(true);
lv.setCellFactory(ComboBoxListCell.forListView(bookStringConverter, dataList.subList(0, 10).toArray(Book[]::new))); lv.setCellFactory(
ComboBoxListCell.forListView(bookStringConverter, dataList.subList(0, 10).toArray(Book[]::new)));
lv.getItems().setAll(dataList.stream().limit(10).collect(Collectors.toList())); lv.getItems().setAll(dataList.stream().limit(10).collect(Collectors.toList()));
return lv; return lv;
} }
@ -230,9 +257,9 @@ public class ListPage extends AbstractPage {
public static Example find(String name) { public static Example find(String name) {
return Arrays.stream(Example.values()) return Arrays.stream(Example.values())
.filter(example -> Objects.equals(example.getName(), name)) .filter(example -> Objects.equals(example.getName(), name))
.findFirst() .findFirst()
.orElse(null); .orElse(null);
} }
} }
@ -246,22 +273,26 @@ public class ListPage extends AbstractPage {
@Override @Override
public String toString(Book book) { public String toString(Book book) {
if (book == null) { return null; } if (book == null) {
return null;
}
return String.format("\"%s\" by %s", book.getTitle(), book.getAuthor()); return String.format("\"%s\" by %s", book.getTitle(), book.getAuthor());
} }
@Override @Override
public Book fromString(String s) { public Book fromString(String s) {
if (s == null) { return null; } if (s == null) {
return null;
}
int sep = s.indexOf("\" by"); int sep = s.indexOf("\" by");
String title = s.substring(1, sep); String title = s.substring(1, sep);
String author = s.substring(sep + "\" by".length()); String author = s.substring(sep + "\" by".length());
return dataList.stream() return dataList.stream()
.filter(b -> Objects.equals(b.getTitle(), title) && Objects.equals(b.getAuthor(), author)) .filter(b -> Objects.equals(b.getTitle(), title) && Objects.equals(b.getAuthor(), author))
.findFirst() .findFirst()
.orElse(null); .orElse(null);
} }
} }
@ -280,11 +311,11 @@ public class ListPage extends AbstractPage {
purchaseBtn.setGraphic(new FontIcon(Feather.SHOPPING_CART)); purchaseBtn.setGraphic(new FontIcon(Feather.SHOPPING_CART));
root = new HBox(5, root = new HBox(5,
titleLabel, titleLabel,
new Label(" by"), new Label(" by"),
authorLink, authorLink,
new Spacer(), new Spacer(),
purchaseBtn purchaseBtn
); );
root.setAlignment(Pos.CENTER_LEFT); root.setAlignment(Pos.CENTER_LEFT);
} }

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page.components; package atlantafx.sampler.page.components;
import static atlantafx.base.theme.Styles.ACCENT; import static atlantafx.base.theme.Styles.ACCENT;
@ -32,16 +33,18 @@ public class MenuButtonPage extends AbstractPage {
private static final int PREF_WIDTH = 150; private static final int PREF_WIDTH = 150;
@Override @Override
public String getName() { return NAME; } public String getName() {
return NAME;
}
public MenuButtonPage() { public MenuButtonPage() {
super(); super();
setUserContent(new VBox( setUserContent(new VBox(
Page.PAGE_VGAP, Page.PAGE_VGAP,
expandingHBox(basicSample(), iconOnlySample()), expandingHBox(basicSample(), iconOnlySample()),
expandingHBox(coloredSample(), outlinedSample()), expandingHBox(coloredSample(), outlinedSample()),
expandingHBox(popupSideSample(), noArrowSample()), expandingHBox(popupSideSample(), noArrowSample()),
disabledSample() disabledSample()
)); ));
} }
@ -272,7 +275,7 @@ public class MenuButtonPage extends AbstractPage {
@SuppressWarnings("SameParameterValue") @SuppressWarnings("SameParameterValue")
private MenuItem[] createItems(int count) { private MenuItem[] createItems(int count) {
return IntStream.range(0, count) return IntStream.range(0, count)
.mapToObj(i -> new MenuItem(FAKER.babylon5().character())) .mapToObj(i -> new MenuItem(FAKER.babylon5().character()))
.toArray(MenuItem[]::new); .toArray(MenuItem[]::new);
} }
} }

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page.components; package atlantafx.sampler.page.components;
import static javafx.scene.input.KeyCombination.CONTROL_DOWN; import static javafx.scene.input.KeyCombination.CONTROL_DOWN;
@ -23,13 +24,15 @@ public class MenuPage extends AbstractPage {
public static final String NAME = "Menu"; public static final String NAME = "Menu";
@Override @Override
public String getName() { return NAME; } public String getName() {
return NAME;
}
public MenuPage() { public MenuPage() {
super(); super();
setUserContent(new VBox(Page.PAGE_VGAP, setUserContent(new VBox(Page.PAGE_VGAP,
menuBarSample(), menuBarSample(),
contextMenuExample() contextMenuExample()
)); ));
} }
@ -40,19 +43,21 @@ public class MenuPage extends AbstractPage {
private SampleBlock contextMenuExample() { private SampleBlock contextMenuExample() {
var contextMenu = new ContextMenu(); var contextMenu = new ContextMenu();
var undoItem = Controls.menuItem("_Undo", Feather.CORNER_DOWN_LEFT, new KeyCodeCombination(KeyCode.Z, CONTROL_DOWN)); var undoItem =
Controls.menuItem("_Undo", Feather.CORNER_DOWN_LEFT, new KeyCodeCombination(KeyCode.Z, CONTROL_DOWN));
undoItem.setMnemonicParsing(true); undoItem.setMnemonicParsing(true);
var redoItem = Controls.menuItem("_Redo", Feather.CORNER_DOWN_RIGHT, new KeyCodeCombination(KeyCode.Y, CONTROL_DOWN)); var redoItem =
Controls.menuItem("_Redo", Feather.CORNER_DOWN_RIGHT, new KeyCodeCombination(KeyCode.Y, CONTROL_DOWN));
redoItem.setMnemonicParsing(true); redoItem.setMnemonicParsing(true);
contextMenu.getItems().addAll( contextMenu.getItems().addAll(
undoItem, undoItem,
redoItem, redoItem,
new SeparatorMenuItem(), new SeparatorMenuItem(),
Controls.menuItem("Cut", Feather.SCISSORS, new KeyCodeCombination(KeyCode.X, CONTROL_DOWN)), Controls.menuItem("Cut", Feather.SCISSORS, new KeyCodeCombination(KeyCode.X, CONTROL_DOWN)),
Controls.menuItem("Copy", Feather.COPY, new KeyCodeCombination(KeyCode.C, CONTROL_DOWN)), Controls.menuItem("Copy", Feather.COPY, new KeyCodeCombination(KeyCode.C, CONTROL_DOWN)),
Controls.menuItem("Paste", null, new KeyCodeCombination(KeyCode.V, CONTROL_DOWN)) Controls.menuItem("Paste", null, new KeyCodeCombination(KeyCode.V, CONTROL_DOWN))
); );
var content = new Label("Right-Click Here"); var content = new Label("Right-Click Here");

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page.components; package atlantafx.sampler.page.components;
import static atlantafx.base.theme.Styles.ACCENT; import static atlantafx.base.theme.Styles.ACCENT;
@ -55,19 +56,21 @@ public class OverviewPage extends AbstractPage {
private static final int COMBO_BOX_WIDTH = 150; private static final int COMBO_BOX_WIDTH = 150;
@Override @Override
public String getName() { return NAME; } public String getName() {
return NAME;
}
public OverviewPage() { public OverviewPage() {
super(); super();
setUserContent(new VBox( setUserContent(new VBox(
PAGE_VGAP, PAGE_VGAP,
buttonSample(), buttonSample(),
expandingHBox(iconButtonSample(), dropdownMenuSample()), expandingHBox(iconButtonSample(), dropdownMenuSample()),
expandingHBox(checkBoxSample(), radioButtonSample(), toggleSwitchSample()), expandingHBox(checkBoxSample(), radioButtonSample(), toggleSwitchSample()),
comboBoxSample(), comboBoxSample(),
sliderSample(), sliderSample(),
expandingHBox(textFieldSample(), spinnerSample()), expandingHBox(textFieldSample(), spinnerSample()),
textAreaSample() textAreaSample()
)); ));
} }
@ -306,7 +309,9 @@ public class OverviewPage extends AbstractPage {
boolean selected, boolean selected,
String... styleClasses) { String... styleClasses) {
var toggleButton = new ToggleButton(text); var toggleButton = new ToggleButton(text);
if (group != null) { toggleButton.setToggleGroup(group); } if (group != null) {
toggleButton.setToggleGroup(group);
}
toggleButton.setSelected(selected); toggleButton.setSelected(selected);
toggleButton.getStyleClass().addAll(styleClasses); toggleButton.getStyleClass().addAll(styleClasses);
@ -315,7 +320,7 @@ public class OverviewPage extends AbstractPage {
private MenuItem[] createMenuItems() { private MenuItem[] createMenuItems() {
return IntStream.range(0, 5) return IntStream.range(0, 5)
.mapToObj(i -> new MenuItem(FAKER.babylon5().character())) .mapToObj(i -> new MenuItem(FAKER.babylon5().character()))
.toArray(MenuItem[]::new); .toArray(MenuItem[]::new);
} }
} }

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page.components; package atlantafx.sampler.page.components;
import static atlantafx.sampler.page.SampleBlock.BLOCK_HGAP; import static atlantafx.sampler.page.SampleBlock.BLOCK_HGAP;
@ -23,12 +24,14 @@ public class PaginationPage extends AbstractPage {
private static final int PREF_CONTROL_WIDTH = 120; private static final int PREF_CONTROL_WIDTH = 120;
@Override @Override
public String getName() { return NAME; } public String getName() {
return NAME;
}
public PaginationPage() { public PaginationPage() {
super(); super();
setUserContent(new VBox( setUserContent(new VBox(
new SampleBlock("Playground", createPlayground()) new SampleBlock("Playground", createPlayground())
)); ));
} }
@ -57,18 +60,22 @@ public class PaginationPage extends AbstractPage {
var bulletToggle = new ToggleSwitch(); var bulletToggle = new ToggleSwitch();
bulletToggle.selectedProperty().addListener( bulletToggle.selectedProperty().addListener(
(obs, old, val) -> Styles.toggleStyleClass(pagination, Pagination.STYLE_CLASS_BULLET) (obs, old, val) -> Styles.toggleStyleClass(pagination, Pagination.STYLE_CLASS_BULLET)
); );
var showArrowsToggle = new ToggleSwitch(); var showArrowsToggle = new ToggleSwitch();
showArrowsToggle.selectedProperty().addListener((obs, old, val) -> { showArrowsToggle.selectedProperty().addListener((obs, old, val) -> {
if (val != null) { pagination.setStyle(String.format("-fx-arrows-visible: %s;", val)); } if (val != null) {
pagination.setStyle(String.format("-fx-arrows-visible: %s;", val));
}
}); });
showArrowsToggle.setSelected(true); showArrowsToggle.setSelected(true);
var showPageInfoToggle = new ToggleSwitch(); var showPageInfoToggle = new ToggleSwitch();
showPageInfoToggle.selectedProperty().addListener((obs, old, val) -> { showPageInfoToggle.selectedProperty().addListener((obs, old, val) -> {
if (val != null) { pagination.setStyle(String.format("-fx-page-information-visible: %s;", val)); } if (val != null) {
pagination.setStyle(String.format("-fx-page-information-visible: %s;", val));
}
}); });
showPageInfoToggle.setSelected(true); showPageInfoToggle.setSelected(true);

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page.components; package atlantafx.sampler.page.components;
import static atlantafx.sampler.page.SampleBlock.BLOCK_HGAP; import static atlantafx.sampler.page.SampleBlock.BLOCK_HGAP;
@ -31,13 +32,15 @@ public class PopoverPage extends AbstractPage {
public static final String NAME = "Popover"; public static final String NAME = "Popover";
@Override @Override
public String getName() { return NAME; } public String getName() {
return NAME;
}
public PopoverPage() { public PopoverPage() {
super(); super();
setUserContent(new VBox(Page.PAGE_VGAP, setUserContent(new VBox(Page.PAGE_VGAP,
new HBox(PAGE_HGAP, textSample(), datePickerSample(), dialogSample()), new HBox(PAGE_HGAP, textSample(), datePickerSample(), dialogSample()),
positionSample() positionSample()
)); ));
} }
@ -64,14 +67,14 @@ public class PopoverPage extends AbstractPage {
var link = createHyperlink("Click me"); var link = createHyperlink("Click me");
link.setOnAction(e -> popover.show(link)); link.setOnAction(e -> popover.show(link));
new CSSFragment(""" new CSSFragment("""
.popover .date-picker-popup { .popover .date-picker-popup {
-color-date-border: transparent; -color-date-border: transparent;
-color-date-bg: transparent; -color-date-bg: transparent;
-color-date-day-bg: transparent; -color-date-day-bg: transparent;
-color-date-month-year-bg: transparent; -color-date-month-year-bg: transparent;
-color-date-day-bg-hover: -color-bg-subtle; -color-date-day-bg-hover: -color-bg-subtle;
} }
""" """
).addTo(link); ).addTo(link);
return new SampleBlock("Date Picker", link); return new SampleBlock("Date Picker", link);
@ -86,7 +89,8 @@ public class PopoverPage extends AbstractPage {
var icon = new FontIcon(Feather.ALERT_TRIANGLE); var icon = new FontIcon(Feather.ALERT_TRIANGLE);
icon.setIconSize(32); // not always works icon.setIconSize(32); // not always works
icon.setStyle("-fx-icon-size:32px;-fx-icon-color:-color-warning-fg;-fx-fill:-color-warning-fg;" + icon.getStyle()); icon.setStyle(
"-fx-icon-size:32px;-fx-icon-color:-color-warning-fg;-fx-fill:-color-warning-fg;" + icon.getStyle());
var label = new Label(FAKER.chuckNorris().fact(), icon); var label = new Label(FAKER.chuckNorris().fact(), icon);
label.setStyle("-fx-graphic-text-gap:10;"); label.setStyle("-fx-graphic-text-gap:10;");

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page.components; package atlantafx.sampler.page.components;
import static atlantafx.base.theme.Styles.BUTTON_CIRCLE; import static atlantafx.base.theme.Styles.BUTTON_CIRCLE;
@ -46,7 +47,9 @@ public class ProgressPage extends AbstractPage {
public static final String NAME = "Progress"; public static final String NAME = "Progress";
@Override @Override
public String getName() { return NAME; } public String getName() {
return NAME;
}
public ProgressPage() { public ProgressPage() {
super(); super();
@ -69,11 +72,11 @@ public class ProgressPage extends AbstractPage {
private SampleBlock basicBarSample() { private SampleBlock basicBarSample() {
var flowPane = new FlowPane( var flowPane = new FlowPane(
BLOCK_HGAP, BLOCK_VGAP, BLOCK_HGAP, BLOCK_VGAP,
createBar(0, false), createBar(0, false),
createBar(0.5, false), createBar(0.5, false),
createBar(1, false), createBar(1, false),
createBar(0.5, true) createBar(0.5, true)
); );
flowPane.setAlignment(Pos.CENTER_LEFT); flowPane.setAlignment(Pos.CENTER_LEFT);
@ -82,11 +85,11 @@ public class ProgressPage extends AbstractPage {
private SampleBlock basicIndicatorSample() { private SampleBlock basicIndicatorSample() {
var flowPane = new FlowPane( var flowPane = new FlowPane(
BLOCK_HGAP, BLOCK_VGAP, BLOCK_HGAP, BLOCK_VGAP,
createIndicator(0, false), createIndicator(0, false),
createIndicator(0.5, false), createIndicator(0.5, false),
createIndicator(1, false), createIndicator(1, false),
createIndicator(0.5, true) createIndicator(0.5, true)
); );
flowPane.setAlignment(Pos.TOP_LEFT); flowPane.setAlignment(Pos.TOP_LEFT);
@ -95,10 +98,10 @@ public class ProgressPage extends AbstractPage {
private SampleBlock barSizeSample() { private SampleBlock barSizeSample() {
var container = new VBox( var container = new VBox(
BLOCK_VGAP, BLOCK_VGAP,
new HBox(20, createBar(0.5, false, SMALL), new Text("small")), new HBox(20, createBar(0.5, false, SMALL), new Text("small")),
new HBox(20, createBar(0.5, false, MEDIUM), new Text("medium")), new HBox(20, createBar(0.5, false, MEDIUM), new Text("medium")),
new HBox(20, createBar(0.5, false, LARGE), new Text("large")) new HBox(20, createBar(0.5, false, LARGE), new Text("large"))
); );
container.setAlignment(Pos.TOP_LEFT); container.setAlignment(Pos.TOP_LEFT);
container.getChildren().forEach(c -> ((HBox) c).setAlignment(Pos.CENTER_LEFT)); container.getChildren().forEach(c -> ((HBox) c).setAlignment(Pos.CENTER_LEFT));
@ -179,52 +182,52 @@ public class ProgressPage extends AbstractPage {
grid.setHgap(40); grid.setHgap(40);
grid.setVgap(BLOCK_VGAP); grid.setVgap(BLOCK_VGAP);
grid.getColumnConstraints().setAll( grid.getColumnConstraints().setAll(
new ColumnConstraints(-1, -1, -1, Priority.NEVER, HPos.CENTER, true), new ColumnConstraints(-1, -1, -1, Priority.NEVER, HPos.CENTER, true),
new ColumnConstraints(-1, -1, -1, Priority.NEVER, HPos.CENTER, true), new ColumnConstraints(-1, -1, -1, Priority.NEVER, HPos.CENTER, true),
new ColumnConstraints(-1, -1, -1, Priority.NEVER, HPos.CENTER, true) new ColumnConstraints(-1, -1, -1, Priority.NEVER, HPos.CENTER, true)
); );
grid.getRowConstraints().setAll( grid.getRowConstraints().setAll(
new RowConstraints(-1, -1, -1, Priority.ALWAYS, VPos.CENTER, true), new RowConstraints(-1, -1, -1, Priority.ALWAYS, VPos.CENTER, true),
new RowConstraints(-1, -1, -1, Priority.NEVER, VPos.CENTER, true) new RowConstraints(-1, -1, -1, Priority.NEVER, VPos.CENTER, true)
); );
var barToggle = new ToggleButton("Start"); var barToggle = new ToggleButton("Start");
barToggle.textProperty().bind(Bindings.createStringBinding( barToggle.textProperty().bind(Bindings.createStringBinding(
() -> barToggle.isSelected() ? "Stop" : "Start", barToggle.selectedProperty()) () -> barToggle.isSelected() ? "Stop" : "Start", barToggle.selectedProperty())
); );
var bar = createBar(0, false); var bar = createBar(0, false);
bar.progressProperty().bind(Bindings.createDoubleBinding( bar.progressProperty().bind(Bindings.createDoubleBinding(
() -> barToggle.isSelected() ? -1d : 0d, barToggle.selectedProperty()) () -> barToggle.isSelected() ? -1d : 0d, barToggle.selectedProperty())
); );
grid.add(bar, 0, 0); grid.add(bar, 0, 0);
grid.add(barToggle, 0, 1); grid.add(barToggle, 0, 1);
var indicatorToggle = new ToggleButton("Start"); var indicatorToggle = new ToggleButton("Start");
indicatorToggle.textProperty().bind(Bindings.createStringBinding( indicatorToggle.textProperty().bind(Bindings.createStringBinding(
() -> indicatorToggle.isSelected() ? "Stop" : "Start", indicatorToggle.selectedProperty()) () -> indicatorToggle.isSelected() ? "Stop" : "Start", indicatorToggle.selectedProperty())
); );
var indicator = createIndicator(0, false); var indicator = createIndicator(0, false);
indicator.setPrefSize(75, 75); indicator.setPrefSize(75, 75);
indicator.progressProperty().bind(Bindings.createDoubleBinding( indicator.progressProperty().bind(Bindings.createDoubleBinding(
() -> indicatorToggle.isSelected() ? -1d : 0d, indicatorToggle.selectedProperty()) () -> indicatorToggle.isSelected() ? -1d : 0d, indicatorToggle.selectedProperty())
); );
grid.add(indicator, 1, 0); grid.add(indicator, 1, 0);
grid.add(indicatorToggle, 1, 1); grid.add(indicatorToggle, 1, 1);
var ringToggle = new ToggleButton("Start"); var ringToggle = new ToggleButton("Start");
ringToggle.textProperty().bind(Bindings.createStringBinding( ringToggle.textProperty().bind(Bindings.createStringBinding(
() -> ringToggle.isSelected() ? "Stop" : "Start", ringToggle.selectedProperty()) () -> ringToggle.isSelected() ? "Stop" : "Start", ringToggle.selectedProperty())
); );
var ring = new RingProgressIndicator(0, false); var ring = new RingProgressIndicator(0, false);
ring.setMinSize(75, 75); ring.setMinSize(75, 75);
ring.progressProperty().bind(Bindings.createDoubleBinding( ring.progressProperty().bind(Bindings.createDoubleBinding(
() -> ringToggle.isSelected() ? -1d : 0d, ringToggle.selectedProperty()) () -> ringToggle.isSelected() ? -1d : 0d, ringToggle.selectedProperty())
); );
grid.add(ring, 2, 0); grid.add(ring, 2, 0);
grid.add(ringToggle, 2, 1); grid.add(ringToggle, 2, 1);
return new SampleBlock("Indeterminate", grid, return new SampleBlock("Indeterminate", grid,
"Animated JavaFX progress indicators aren't cheap. They can consume quite a lot of CPU time." "Animated JavaFX progress indicators aren't cheap. They can consume quite a lot of CPU time."
); );
} }
@ -256,7 +259,9 @@ public class ProgressPage extends AbstractPage {
content.setPrefHeight(200); content.setPrefHeight(200);
bar.progressProperty().addListener((obs, old, val) -> { bar.progressProperty().addListener((obs, old, val) -> {
if (val == null) { return; } if (val == null) {
return;
}
if (val.floatValue() > 0.80) { if (val.floatValue() > 0.80) {
barStack.pseudoClassStateChanged(stateDanger, true); barStack.pseudoClassStateChanged(stateDanger, true);
@ -266,17 +271,17 @@ public class ProgressPage extends AbstractPage {
}); });
new CSSFragment(""" new CSSFragment("""
.example:state-success .progress-bar { .example:state-success .progress-bar {
-color-progress-bar-fill: -color-success-emphasis; -color-progress-bar-fill: -color-success-emphasis;
} }
.example:state-danger .progress-bar { .example:state-danger .progress-bar {
-color-progress-bar-fill: -color-danger-emphasis; -color-progress-bar-fill: -color-danger-emphasis;
} }
.example:state-success .label, .example:state-success .label,
.example:state-danger .label { .example:state-danger .label {
-fx-text-fill: -color-fg-emphasis; -fx-text-fill: -color-fg-emphasis;
} }
""").addTo(content); """).addTo(content);
runBtn.setOnAction(e1 -> { runBtn.setOnAction(e1 -> {
var task = new Task<Void>() { var task = new Task<Void>() {

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page.components; package atlantafx.sampler.page.components;
import static atlantafx.sampler.page.SampleBlock.BLOCK_VGAP; import static atlantafx.sampler.page.SampleBlock.BLOCK_VGAP;
@ -16,15 +17,17 @@ public class RadioButtonPage extends AbstractPage {
public static final String NAME = "RadioButton"; public static final String NAME = "RadioButton";
@Override @Override
public String getName() { return NAME; } public String getName() {
return NAME;
}
public RadioButtonPage() { public RadioButtonPage() {
super(); super();
setUserContent(new FlowPane( setUserContent(new FlowPane(
Page.PAGE_HGAP, Page.PAGE_VGAP, Page.PAGE_HGAP, Page.PAGE_VGAP,
basicSample(), basicSample(),
groupSample(), groupSample(),
disabledSample() disabledSample()
)); ));
} }

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page.components; package atlantafx.sampler.page.components;
import atlantafx.sampler.page.AbstractPage; import atlantafx.sampler.page.AbstractPage;
@ -17,16 +18,18 @@ public class ScrollPanePage extends AbstractPage {
private static final int SPACING = 1; private static final int SPACING = 1;
@Override @Override
public String getName() { return NAME; } public String getName() {
return NAME;
}
public ScrollPanePage() { public ScrollPanePage() {
super(); super();
setUserContent(new FlowPane( setUserContent(new FlowPane(
Page.PAGE_VGAP, Page.PAGE_HGAP, Page.PAGE_VGAP, Page.PAGE_HGAP,
horizontalScrollSample(), horizontalScrollSample(),
verticalScrollSample(), verticalScrollSample(),
gridScrollSample(), gridScrollSample(),
disabledSample() disabledSample()
)); ));
} }
@ -35,8 +38,8 @@ public class ScrollPanePage extends AbstractPage {
scrollPane.setMaxHeight(100); scrollPane.setMaxHeight(100);
scrollPane.setMaxWidth(300); scrollPane.setMaxWidth(300);
scrollPane.setContent(new HBox(SPACING, scrollPane.setContent(new HBox(SPACING,
createRegion(200, 100, "-color-success-emphasis"), createRegion(200, 100, "-color-success-emphasis"),
createRegion(200, 100, "-color-danger-emphasis") createRegion(200, 100, "-color-danger-emphasis")
)); ));
scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.NEVER); scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
@ -48,8 +51,8 @@ public class ScrollPanePage extends AbstractPage {
scrollPane.setMaxHeight(100); scrollPane.setMaxHeight(100);
scrollPane.setMaxWidth(300); scrollPane.setMaxWidth(300);
scrollPane.setContent(new VBox(SPACING, scrollPane.setContent(new VBox(SPACING,
createRegion(300, 75, "-color-success-emphasis"), createRegion(300, 75, "-color-success-emphasis"),
createRegion(300, 75, "-color-danger-emphasis") createRegion(300, 75, "-color-danger-emphasis")
)); ));
scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER); scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page.components; package atlantafx.sampler.page.components;
import static javafx.geometry.Orientation.HORIZONTAL; import static javafx.geometry.Orientation.HORIZONTAL;
@ -25,29 +26,31 @@ public final class SeparatorPage extends AbstractPage {
private static final int PANE_SIZE = 100; private static final int PANE_SIZE = 100;
@Override @Override
public String getName() { return NAME; } public String getName() {
return NAME;
}
public SeparatorPage() { public SeparatorPage() {
super(); super();
setUserContent(new FlowPane( setUserContent(new FlowPane(
Page.PAGE_HGAP, Page.PAGE_VGAP, Page.PAGE_HGAP, Page.PAGE_VGAP,
orientationSample(), orientationSample(),
sizeSample() sizeSample()
)); ));
} }
private SampleBlock orientationSample() { private SampleBlock orientationSample() {
var hBox = new HBox( var hBox = new HBox(
createPane("Left", VERTICAL), createPane("Left", VERTICAL),
new Separator(VERTICAL), new Separator(VERTICAL),
createPane("Right", VERTICAL) createPane("Right", VERTICAL)
); );
hBox.setAlignment(CENTER); hBox.setAlignment(CENTER);
var vBox = new VBox( var vBox = new VBox(
createPane("Top", HORIZONTAL), createPane("Top", HORIZONTAL),
new Separator(HORIZONTAL), new Separator(HORIZONTAL),
createPane("Bottom", HORIZONTAL) createPane("Bottom", HORIZONTAL)
); );
vBox.setAlignment(CENTER); vBox.setAlignment(CENTER);
@ -58,27 +61,27 @@ public final class SeparatorPage extends AbstractPage {
var smallSep = new Separator(VERTICAL); var smallSep = new Separator(VERTICAL);
smallSep.getStyleClass().add(Styles.SMALL); smallSep.getStyleClass().add(Styles.SMALL);
var smallBox = new HBox( var smallBox = new HBox(
createPane("Left", VERTICAL), createPane("Left", VERTICAL),
smallSep, smallSep,
createPane("Right", VERTICAL) createPane("Right", VERTICAL)
); );
smallBox.setAlignment(CENTER); smallBox.setAlignment(CENTER);
var mediumSep = new Separator(VERTICAL); var mediumSep = new Separator(VERTICAL);
mediumSep.getStyleClass().add(Styles.MEDIUM); mediumSep.getStyleClass().add(Styles.MEDIUM);
var mediumBox = new HBox( var mediumBox = new HBox(
createPane("Left", VERTICAL), createPane("Left", VERTICAL),
mediumSep, mediumSep,
createPane("Right", VERTICAL) createPane("Right", VERTICAL)
); );
mediumBox.setAlignment(CENTER); mediumBox.setAlignment(CENTER);
var largeSep = new Separator(VERTICAL); var largeSep = new Separator(VERTICAL);
largeSep.getStyleClass().add(Styles.LARGE); largeSep.getStyleClass().add(Styles.LARGE);
var largeBox = new HBox( var largeBox = new HBox(
createPane("Left", VERTICAL), createPane("Left", VERTICAL),
largeSep, largeSep,
createPane("Right", VERTICAL) createPane("Right", VERTICAL)
); );
largeBox.setAlignment(CENTER); largeBox.setAlignment(CENTER);

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page.components; package atlantafx.sampler.page.components;
import static javafx.geometry.Orientation.VERTICAL; import static javafx.geometry.Orientation.VERTICAL;
@ -20,16 +21,18 @@ public class SliderPage extends AbstractPage {
private static final int SPACING = 20; private static final int SPACING = 20;
@Override @Override
public String getName() { return NAME; } public String getName() {
return NAME;
}
public SliderPage() { public SliderPage() {
super(); super();
setUserContent(new FlowPane( setUserContent(new FlowPane(
Page.PAGE_HGAP, Page.PAGE_VGAP, Page.PAGE_HGAP, Page.PAGE_VGAP,
basicSample(), basicSample(),
smallSample(), smallSample(),
largeSample(), largeSample(),
disabledSample() disabledSample()
)); ));
} }

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page.components; package atlantafx.sampler.page.components;
import atlantafx.base.util.IntegerStringConverter; import atlantafx.base.util.IntegerStringConverter;
@ -14,19 +15,21 @@ public final class SpinnerPage extends AbstractPage {
private static final int PREF_WIDTH = 120; private static final int PREF_WIDTH = 120;
@Override @Override
public String getName() { return NAME; } public String getName() {
return NAME;
}
public SpinnerPage() { public SpinnerPage() {
super(); super();
setUserContent(new FlowPane( setUserContent(new FlowPane(
Page.PAGE_HGAP, Page.PAGE_VGAP, Page.PAGE_HGAP, Page.PAGE_VGAP,
basicSample(), basicSample(),
arrowsLeftVerticalSample(), arrowsLeftVerticalSample(),
arrowsLeftHorizontalSample(), arrowsLeftHorizontalSample(),
arrowsRightHorizontalSample(), arrowsRightHorizontalSample(),
arrowsSplitHorizontalSample(), arrowsSplitHorizontalSample(),
arrowsSplitVerticalSample(), arrowsSplitVerticalSample(),
disabledSample() disabledSample()
)); ));
} }

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page.components; package atlantafx.sampler.page.components;
import atlantafx.sampler.page.AbstractPage; import atlantafx.sampler.page.AbstractPage;
@ -18,16 +19,18 @@ public class SplitPanePage extends AbstractPage {
public static final String NAME = "SplitPane"; public static final String NAME = "SplitPane";
@Override @Override
public String getName() { return NAME; } public String getName() {
return NAME;
}
public SplitPanePage() { public SplitPanePage() {
super(); super();
setUserContent(new FlowPane( setUserContent(new FlowPane(
Page.PAGE_VGAP, Page.PAGE_HGAP, Page.PAGE_VGAP, Page.PAGE_HGAP,
hSplitSample(), hSplitSample(),
vSplitSample(), vSplitSample(),
disabledSample(), disabledSample(),
gridSample() gridSample()
)); ));
} }
@ -68,8 +71,12 @@ public class SplitPanePage extends AbstractPage {
doubleSplitPane.setOrientation(Orientation.VERTICAL); doubleSplitPane.setOrientation(Orientation.VERTICAL);
doubleSplitPane.setDividerPositions(0.5); doubleSplitPane.setDividerPositions(0.5);
doubleSplitPane.getItems().setAll( doubleSplitPane.getItems().setAll(
new VBox(topSplitPane) {{ setAlignment(Pos.CENTER); }}, new VBox(topSplitPane) {{
new VBox(bottomSplitPane) {{ setAlignment(Pos.CENTER); }} setAlignment(Pos.CENTER);
}},
new VBox(bottomSplitPane) {{
setAlignment(Pos.CENTER);
}}
); );
doubleSplitPane.setMinSize(400, 200); doubleSplitPane.setMinSize(400, 200);
doubleSplitPane.setMaxSize(400, 200); doubleSplitPane.setMaxSize(400, 200);

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page.components; package atlantafx.sampler.page.components;
import static atlantafx.base.theme.Styles.ACCENT; import static atlantafx.base.theme.Styles.ACCENT;
@ -38,7 +39,9 @@ public class TabPanePage extends AbstractPage {
private static final double TAB_MIN_HEIGHT = 60; private static final double TAB_MIN_HEIGHT = 60;
@Override @Override
public String getName() { return NAME; } public String getName() {
return NAME;
}
private Side tabSide = Side.TOP; private Side tabSide = Side.TOP;
private boolean fullWidth = false; private boolean fullWidth = false;
@ -122,7 +125,9 @@ public class TabPanePage extends AbstractPage {
var floatingToggle = new ToggleSwitch(); var floatingToggle = new ToggleSwitch();
floatingToggle.selectedProperty().addListener((obs, old, val) -> { floatingToggle.selectedProperty().addListener((obs, old, val) -> {
if (val != null) { Styles.toggleStyleClass(tabs, TabPane.STYLE_CLASS_FLOATING); } if (val != null) {
Styles.toggleStyleClass(tabs, TabPane.STYLE_CLASS_FLOATING);
}
}); });
var animatedToggle = new ToggleSwitch(); var animatedToggle = new ToggleSwitch();
@ -148,7 +153,9 @@ public class TabPanePage extends AbstractPage {
var disableToggle = new ToggleSwitch(); var disableToggle = new ToggleSwitch();
disableToggle.selectedProperty().addListener((obs, old, val) -> { disableToggle.selectedProperty().addListener((obs, old, val) -> {
if (val != null) { tabs.setDisable(val); } if (val != null) {
tabs.setDisable(val);
}
}); });
var togglesGrid = new GridPane(); var togglesGrid = new GridPane();
@ -176,10 +183,10 @@ public class TabPanePage extends AbstractPage {
// == LAYOUT == // == LAYOUT ==
var controls = new HBox(40, var controls = new HBox(40,
new Spacer(), new Spacer(),
buttonsPane, buttonsPane,
togglesGrid, togglesGrid,
new Spacer() new Spacer()
); );
controls.setAlignment(Pos.CENTER); controls.setAlignment(Pos.CENTER);
@ -208,16 +215,16 @@ public class TabPanePage extends AbstractPage {
if (tabs.getSide() == Side.TOP || tabs.getSide() == Side.BOTTOM) { if (tabs.getSide() == Side.TOP || tabs.getSide() == Side.BOTTOM) {
tabs.tabMinWidthProperty().bind(borderPane.widthProperty() tabs.tabMinWidthProperty().bind(borderPane.widthProperty()
.subtract(18) // .control-buttons-tab width .subtract(18) // .control-buttons-tab width
.divide(tabs.getTabs().size()) .divide(tabs.getTabs().size())
.subtract(28) // .tab paddings .subtract(28) // .tab paddings
); );
} }
if (tabs.getSide() == Side.LEFT || tabs.getSide() == Side.RIGHT) { if (tabs.getSide() == Side.LEFT || tabs.getSide() == Side.RIGHT) {
tabs.tabMinWidthProperty().bind(borderPane.heightProperty() tabs.tabMinWidthProperty().bind(borderPane.heightProperty()
.subtract(18) // same as above .subtract(18) // same as above
.divide(tabs.getTabs().size()) .divide(tabs.getTabs().size())
.subtract(28) .subtract(28)
); );
} }
} }
@ -231,16 +238,18 @@ public class TabPanePage extends AbstractPage {
// like disabled. To prevent it from closing one can use "black hole" // like disabled. To prevent it from closing one can use "black hole"
// event handler. #javafx-bug // event handler. #javafx-bug
tabs.getTabs().addAll( tabs.getTabs().addAll(
createRandomTab(), createRandomTab(),
createRandomTab(), createRandomTab(),
createRandomTab() createRandomTab()
); );
return tabs; return tabs;
} }
private void rotateTabs(BorderPane borderPane, TabPane tabs, Side side) { private void rotateTabs(BorderPane borderPane, TabPane tabs, Side side) {
if (tabSide == side) { return; } if (tabSide == side) {
return;
}
borderPane.getChildren().removeAll(tabs); borderPane.getChildren().removeAll(tabs);
tabSide = side; tabSide = side;

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page.components; package atlantafx.sampler.page.components;
import static atlantafx.base.theme.Styles.BORDERED; import static atlantafx.base.theme.Styles.BORDERED;
@ -59,12 +60,14 @@ public class TablePage extends AbstractPage {
public static final String NAME = "TableView"; public static final String NAME = "TableView";
@Override @Override
public String getName() { return NAME; } public String getName() {
return NAME;
}
private TableView<Product> table; private TableView<Product> table;
private final List<Product> dataList = IntStream.range(1, 51).boxed() private final List<Product> dataList = IntStream.range(1, 51).boxed()
.map(i -> Product.random(i, FAKER)) .map(i -> Product.random(i, FAKER))
.toList(); .toList();
public TablePage() { public TablePage() {
super(); super();
@ -88,7 +91,7 @@ public class TablePage extends AbstractPage {
var edge2edgeToggle = new ToggleSwitch("Edge to edge"); var edge2edgeToggle = new ToggleSwitch("Edge to edge");
edge2edgeToggle.selectedProperty().addListener( edge2edgeToggle.selectedProperty().addListener(
(obs, old, value) -> toggleStyleClass(table, Tweaks.EDGE_TO_EDGE) (obs, old, value) -> toggleStyleClass(table, Tweaks.EDGE_TO_EDGE)
); );
var maxRowCount = 100; var maxRowCount = 100;
@ -99,14 +102,14 @@ public class TablePage extends AbstractPage {
rowCountBox.setAlignment(Pos.CENTER_LEFT); rowCountBox.setAlignment(Pos.CENTER_LEFT);
var footer = new HBox( var footer = new HBox(
BLOCK_HGAP, BLOCK_HGAP,
new Spacer(), new Spacer(),
bordersToggle, bordersToggle,
denseToggle, denseToggle,
stripesToggle, stripesToggle,
edge2edgeToggle, edge2edgeToggle,
new Spacer(), new Spacer(),
rowCountBox rowCountBox
); );
footer.setAlignment(Pos.CENTER_LEFT); footer.setAlignment(Pos.CENTER_LEFT);
@ -114,8 +117,8 @@ public class TablePage extends AbstractPage {
var filteredData = new FilteredList<>(observableArrayList(dataList)); var filteredData = new FilteredList<>(observableArrayList(dataList));
filteredData.predicateProperty().bind(Bindings.createObjectBinding( filteredData.predicateProperty().bind(Bindings.createObjectBinding(
() -> product -> product.getId() <= rowCountChoice.getValue(), () -> product -> product.getId() <= rowCountChoice.getValue(),
rowCountChoice.valueProperty() rowCountChoice.valueProperty()
)); ));
var sortedData = new SortedList<>(filteredData); var sortedData = new SortedList<>(filteredData);
@ -161,15 +164,17 @@ public class TablePage extends AbstractPage {
var disableToggle = new ToggleSwitch("Disable"); var disableToggle = new ToggleSwitch("Disable");
disableToggle.selectedProperty().addListener((obs, old, val) -> { disableToggle.selectedProperty().addListener((obs, old, val) -> {
if (val != null) { table.setDisable(val); } if (val != null) {
table.setDisable(val);
}
}); });
var header = new HBox( var header = new HBox(
createTablePropertiesMenu(table), createTablePropertiesMenu(table),
new Spacer(), new Spacer(),
alignBox, alignBox,
new Spacer(), new Spacer(),
disableToggle disableToggle
); );
header.setAlignment(Pos.CENTER_LEFT); header.setAlignment(Pos.CENTER_LEFT);
@ -194,8 +199,8 @@ public class TablePage extends AbstractPage {
indexCol.setCellFactory(col -> { indexCol.setCellFactory(col -> {
TableCell<Product, String> cell = new TableCell<>(); TableCell<Product, String> cell = new TableCell<>();
StringBinding value = Bindings.when(cell.emptyProperty()) StringBinding value = Bindings.when(cell.emptyProperty())
.then("") .then("")
.otherwise(cell.indexProperty().add(1).asString()); .otherwise(cell.indexProperty().add(1).asString());
cell.textProperty().bind(value); cell.textProperty().bind(value);
return cell; return cell;
}); });
@ -208,14 +213,14 @@ public class TablePage extends AbstractPage {
var brandCol = new TableColumn<Product, String>("Brand 🖉"); var brandCol = new TableColumn<Product, String>("Brand 🖉");
brandCol.setCellValueFactory(new PropertyValueFactory<>("brand")); brandCol.setCellValueFactory(new PropertyValueFactory<>("brand"));
brandCol.setCellFactory(ChoiceBoxTableCell.forTableColumn( brandCol.setCellFactory(ChoiceBoxTableCell.forTableColumn(
generate(() -> FAKER.commerce().brand(), 10).toArray(String[]::new) generate(() -> FAKER.commerce().brand(), 10).toArray(String[]::new)
)); ));
brandCol.setEditable(true); brandCol.setEditable(true);
var nameCol = new TableColumn<Product, String>("Name 🖉"); var nameCol = new TableColumn<Product, String>("Name 🖉");
nameCol.setCellValueFactory(new PropertyValueFactory<>("name")); nameCol.setCellValueFactory(new PropertyValueFactory<>("name"));
nameCol.setCellFactory(ComboBoxTableCell.forTableColumn( nameCol.setCellFactory(ComboBoxTableCell.forTableColumn(
generate(() -> FAKER.commerce().productName(), 10).toArray(String[]::new) generate(() -> FAKER.commerce().productName(), 10).toArray(String[]::new)
)); ));
nameCol.setEditable(true); nameCol.setEditable(true);
@ -298,16 +303,16 @@ public class TablePage extends AbstractPage {
return new MenuButton("Properties") {{ return new MenuButton("Properties") {{
getItems().setAll( getItems().setAll(
resizePolicyCaption, resizePolicyCaption,
unconstrainedResizeItem, unconstrainedResizeItem,
constrainedResizeItem, constrainedResizeItem,
selectionModeCaption, selectionModeCaption,
singleSelectionItem, singleSelectionItem,
multiSelectionItem, multiSelectionItem,
new SeparatorMenuItem(), new SeparatorMenuItem(),
editCellsItem, editCellsItem,
cellSelectionItem, cellSelectionItem,
menuButtonItem menuButtonItem
); );
}}; }};
} }

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page.components; package atlantafx.sampler.page.components;
import static atlantafx.base.theme.Styles.STATE_DANGER; import static atlantafx.base.theme.Styles.STATE_DANGER;
@ -18,19 +19,21 @@ public class TextAreaPage extends AbstractPage {
private static final double CONTROL_HEIGHT = 120; private static final double CONTROL_HEIGHT = 120;
@Override @Override
public String getName() { return NAME; } public String getName() {
return NAME;
}
public TextAreaPage() { public TextAreaPage() {
super(); super();
setUserContent(new FlowPane( setUserContent(new FlowPane(
PAGE_HGAP, PAGE_VGAP, PAGE_HGAP, PAGE_VGAP,
basicSample(), basicSample(),
promptSample(), promptSample(),
scrollSample(), scrollSample(),
readonlySample(), readonlySample(),
successSample(), successSample(),
dangerSample(), dangerSample(),
disabledSample() disabledSample()
)); ));
} }
@ -48,7 +51,7 @@ public class TextAreaPage extends AbstractPage {
private SampleBlock scrollSample() { private SampleBlock scrollSample() {
var textArea = createTextArea( var textArea = createTextArea(
Stream.generate(() -> FAKER.lorem().paragraph()).limit(10).collect(Collectors.joining("\n")) Stream.generate(() -> FAKER.lorem().paragraph()).limit(10).collect(Collectors.joining("\n"))
); );
textArea.setWrapText(false); textArea.setWrapText(false);
return new SampleBlock("Scrolling", textArea); return new SampleBlock("Scrolling", textArea);

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page.components; package atlantafx.sampler.page.components;
import static atlantafx.base.theme.Styles.LARGE; import static atlantafx.base.theme.Styles.LARGE;
@ -21,16 +22,18 @@ public class TextFieldPage extends AbstractPage {
public static final String NAME = "TextField"; public static final String NAME = "TextField";
@Override @Override
public String getName() { return NAME; } public String getName() {
return NAME;
}
public TextFieldPage() { public TextFieldPage() {
super(); super();
setUserContent(new VBox( setUserContent(new VBox(
PAGE_VGAP, PAGE_VGAP,
expandingHBox(basicSample(), promptSample(), passwordSample()), expandingHBox(basicSample(), promptSample(), passwordSample()),
expandingHBox(readonlySample(), successSample(), dangerSample()), expandingHBox(readonlySample(), successSample(), dangerSample()),
expandingHBox(sizeSample(), roundedSample()), expandingHBox(sizeSample(), roundedSample()),
disabledSample() disabledSample()
)); ));
} }

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page.components; package atlantafx.sampler.page.components;
import static atlantafx.base.theme.Styles.DENSE; import static atlantafx.base.theme.Styles.DENSE;
@ -35,7 +36,9 @@ public class TitledPanePage extends AbstractPage {
private static final String ELEVATED_PREFIX = "elevated-"; private static final String ELEVATED_PREFIX = "elevated-";
@Override @Override
public String getName() { return NAME; } public String getName() {
return NAME;
}
public TitledPanePage() { public TitledPanePage() {
super(); super();
@ -44,17 +47,17 @@ public class TitledPanePage extends AbstractPage {
private void createView() { private void createView() {
var samples = new HBox( var samples = new HBox(
PAGE_HGAP, PAGE_HGAP,
interactivePane(), interactivePane(),
disabledPane(), disabledPane(),
untitledPane() untitledPane()
); );
samples.getChildren().forEach(c -> ((TitledPane) c).setPrefSize(500, 120)); samples.getChildren().forEach(c -> ((TitledPane) c).setPrefSize(500, 120));
setUserContent(new VBox( setUserContent(new VBox(
Page.PAGE_VGAP, Page.PAGE_VGAP,
createPlayground(), createPlayground(),
samples samples
)); ));
} }
@ -80,11 +83,15 @@ public class TitledPanePage extends AbstractPage {
elevationSlider.setMaxWidth(150); elevationSlider.setMaxWidth(150);
elevationSlider.valueProperty().addListener((obs, old, val) -> { elevationSlider.valueProperty().addListener((obs, old, val) -> {
playground.getStyleClass().removeAll( playground.getStyleClass().removeAll(
playground.getStyleClass().stream().filter(c -> c.startsWith(ELEVATED_PREFIX)).toList() playground.getStyleClass().stream().filter(c -> c.startsWith(ELEVATED_PREFIX)).toList()
); );
if (val == null) { return; } if (val == null) {
return;
}
int level = val.intValue(); int level = val.intValue();
if (level > 0) { playground.getStyleClass().add(ELEVATED_PREFIX + level); } if (level > 0) {
playground.getStyleClass().add(ELEVATED_PREFIX + level);
}
}); });
// NOTE: // NOTE:
@ -108,8 +115,8 @@ public class TitledPanePage extends AbstractPage {
toggles.setVgap(10); toggles.setVgap(10);
toggles.setHgap(BLOCK_HGAP); toggles.setHgap(BLOCK_HGAP);
toggles.getColumnConstraints().setAll( toggles.getColumnConstraints().setAll(
new ColumnConstraints(-1, -1, -1, NEVER, RIGHT, false), new ColumnConstraints(-1, -1, -1, NEVER, RIGHT, false),
new ColumnConstraints(-1, -1, -1, NEVER, RIGHT, false) new ColumnConstraints(-1, -1, -1, NEVER, RIGHT, false)
); );
toggles.add(collapseToggle, 0, 0); toggles.add(collapseToggle, 0, 0);
toggles.add(animateToggle, 1, 0); toggles.add(animateToggle, 1, 0);
@ -121,10 +128,10 @@ public class TitledPanePage extends AbstractPage {
controls.setFillHeight(false); controls.setFillHeight(false);
controls.setAlignment(Pos.CENTER_LEFT); controls.setAlignment(Pos.CENTER_LEFT);
controls.getChildren().setAll( controls.getChildren().setAll(
new Label("Elevation"), new Label("Elevation"),
elevationSlider, elevationSlider,
new Spacer(), new Spacer(),
toggles toggles
); );
var content = new VBox(BLOCK_VGAP, textFlow, controls); var content = new VBox(BLOCK_VGAP, textFlow, controls);

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page.components; package atlantafx.sampler.page.components;
import static atlantafx.base.theme.Styles.BUTTON_ICON; import static atlantafx.base.theme.Styles.BUTTON_ICON;
@ -25,7 +26,9 @@ public class ToggleButtonPage extends AbstractPage {
public static final String NAME = "ToggleButton"; public static final String NAME = "ToggleButton";
@Override @Override
public String getName() { return NAME; } public String getName() {
return NAME;
}
public ToggleButtonPage() { public ToggleButtonPage() {
super(); super();
@ -61,8 +64,8 @@ public class ToggleButtonPage extends AbstractPage {
var twoButtonGroup = new ToggleGroup(); var twoButtonGroup = new ToggleGroup();
var twoButtonBox = new HBox( var twoButtonBox = new HBox(
toggleButton(".left-pill", null, twoButtonGroup, true, LEFT_PILL), toggleButton(".left-pill", null, twoButtonGroup, true, LEFT_PILL),
toggleButton(".right-pill", null, twoButtonGroup, false, RIGHT_PILL) toggleButton(".right-pill", null, twoButtonGroup, false, RIGHT_PILL)
); );
return new SampleBlock("Basic", new HBox(BLOCK_HGAP, threeButtonBox, twoButtonBox)); return new SampleBlock("Basic", new HBox(BLOCK_HGAP, threeButtonBox, twoButtonBox));
@ -91,14 +94,16 @@ public class ToggleButtonPage extends AbstractPage {
}); });
var wizard = new HBox( var wizard = new HBox(
prevBtn, prevBtn,
toggleButton("Music", Feather.MUSIC, group, true, CENTER_PILL), toggleButton("Music", Feather.MUSIC, group, true, CENTER_PILL),
toggleButton("Images", Feather.IMAGE, group, false, CENTER_PILL), toggleButton("Images", Feather.IMAGE, group, false, CENTER_PILL),
toggleButton("Videos", Feather.VIDEO, group, false, CENTER_PILL), toggleButton("Videos", Feather.VIDEO, group, false, CENTER_PILL),
nextBtn nextBtn
); );
group.selectedToggleProperty().addListener((obs, old, val) -> { group.selectedToggleProperty().addListener((obs, old, val) -> {
if (val == null) { old.setSelected(true); } if (val == null) {
old.setSelected(true);
}
}); });
return new SampleBlock("Wizard", wizard); return new SampleBlock("Wizard", wizard);
@ -106,9 +111,9 @@ public class ToggleButtonPage extends AbstractPage {
private SampleBlock iconOnlySample() { private SampleBlock iconOnlySample() {
var icons = new HBox( var icons = new HBox(
toggleButton("", Feather.BOLD, null, true, BUTTON_ICON, LEFT_PILL), toggleButton("", Feather.BOLD, null, true, BUTTON_ICON, LEFT_PILL),
toggleButton("", Feather.ITALIC, null, false, BUTTON_ICON, CENTER_PILL), toggleButton("", Feather.ITALIC, null, false, BUTTON_ICON, CENTER_PILL),
toggleButton("", Feather.UNDERLINE, null, false, BUTTON_ICON, RIGHT_PILL) toggleButton("", Feather.UNDERLINE, null, false, BUTTON_ICON, RIGHT_PILL)
); );
return new SampleBlock("Icon only", icons); return new SampleBlock("Icon only", icons);
@ -117,9 +122,9 @@ public class ToggleButtonPage extends AbstractPage {
private SampleBlock disabledSample() { private SampleBlock disabledSample() {
var group = new ToggleGroup(); var group = new ToggleGroup();
var content = new HBox( var content = new HBox(
toggleButton(".left-pill", null, group, false, LEFT_PILL), toggleButton(".left-pill", null, group, false, LEFT_PILL),
toggleButton(".center-pill", null, group, false, CENTER_PILL), toggleButton(".center-pill", null, group, false, CENTER_PILL),
toggleButton(".right-pill", null, group, true, RIGHT_PILL) toggleButton(".right-pill", null, group, true, RIGHT_PILL)
); );
content.getChildren().get(0).setDisable(true); content.getChildren().get(0).setDisable(true);
content.getChildren().get(1).setDisable(true); content.getChildren().get(1).setDisable(true);

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page.components; package atlantafx.sampler.page.components;
import atlantafx.base.controls.ToggleSwitch; import atlantafx.base.controls.ToggleSwitch;
@ -12,13 +13,15 @@ public class ToggleSwitchPage extends AbstractPage {
public static final String NAME = "ToggleSwitch"; public static final String NAME = "ToggleSwitch";
@Override @Override
public String getName() { return NAME; } public String getName() {
return NAME;
}
public ToggleSwitchPage() { public ToggleSwitchPage() {
super(); super();
setUserContent(new FlowPane( setUserContent(new FlowPane(
Page.PAGE_HGAP, Page.PAGE_VGAP, Page.PAGE_HGAP, Page.PAGE_VGAP,
basicSample() basicSample()
)); ));
} }

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page.components; package atlantafx.sampler.page.components;
import static atlantafx.base.theme.Styles.ACCENT; import static atlantafx.base.theme.Styles.ACCENT;
@ -57,7 +58,9 @@ public class ToolBarPage extends AbstractPage {
public static final String NAME = "ToolBar"; public static final String NAME = "ToolBar";
@Override @Override
public String getName() { return NAME; } public String getName() {
return NAME;
}
private Side toolbarPos = Side.TOP; private Side toolbarPos = Side.TOP;
@ -149,7 +152,9 @@ public class ToolBarPage extends AbstractPage {
var disableToggle = new ToggleSwitch(); var disableToggle = new ToggleSwitch();
disableToggle.selectedProperty().addListener((obs, old, val) -> { disableToggle.selectedProperty().addListener((obs, old, val) -> {
if (val != null) { toolbar.setDisable(val); } if (val != null) {
toolbar.setDisable(val);
}
}); });
var togglesGrid = new GridPane(); var togglesGrid = new GridPane();
@ -178,13 +183,17 @@ public class ToolBarPage extends AbstractPage {
} }
private void rotateToolbar(BorderPane borderPane, ToolBar toolbar, Side pos) { private void rotateToolbar(BorderPane borderPane, ToolBar toolbar, Side pos) {
if (toolbarPos == pos) { return; } if (toolbarPos == pos) {
return;
}
var topBar = (TopBar) borderPane.getTop(); var topBar = (TopBar) borderPane.getTop();
toolbarPos = pos; toolbarPos = pos;
boolean changed = borderPane.getChildren().removeAll(toolbar); boolean changed = borderPane.getChildren().removeAll(toolbar);
if (!changed) { topBar.removeToolBar(); } if (!changed) {
topBar.removeToolBar();
}
// WARNING: // WARNING:
// Rotating existing buttons seems tempting, but it won't work. // Rotating existing buttons seems tempting, but it won't work.
@ -270,7 +279,8 @@ public class ToolBarPage extends AbstractPage {
} }
public static MenuItem[] createItems(int count) { public static MenuItem[] createItems(int count) {
return IntStream.range(0, count).mapToObj(i -> new MenuItem(FAKER.babylon5().character())).toArray(MenuItem[]::new); return IntStream.range(0, count).mapToObj(i -> new MenuItem(FAKER.babylon5().character()))
.toArray(MenuItem[]::new);
} }
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page.components; package atlantafx.sampler.page.components;
import static atlantafx.sampler.page.SampleBlock.BLOCK_HGAP; import static atlantafx.sampler.page.SampleBlock.BLOCK_HGAP;
@ -23,17 +24,19 @@ public class TooltipPage extends AbstractPage {
public static final String NAME = "Tooltip"; public static final String NAME = "Tooltip";
@Override @Override
public String getName() { return NAME; } public String getName() {
return NAME;
}
public TooltipPage() { public TooltipPage() {
super(); super();
setUserContent(new VBox(Page.PAGE_VGAP, setUserContent(new VBox(Page.PAGE_VGAP,
expandingHBox( expandingHBox(
basicSample(), basicSample(),
textWrapSample(), textWrapSample(),
indefiniteSample() indefiniteSample()
), ),
positionSample() positionSample()
)); ));
} }
@ -83,14 +86,14 @@ public class TooltipPage extends AbstractPage {
bottomRightLabel.setTooltip(createTooltip("Bottom Right", AnchorLocation.WINDOW_TOP_LEFT)); bottomRightLabel.setTooltip(createTooltip("Bottom Right", AnchorLocation.WINDOW_TOP_LEFT));
var flowPane = new FlowPane( var flowPane = new FlowPane(
BLOCK_HGAP, BLOCK_VGAP, BLOCK_HGAP, BLOCK_VGAP,
topLeftLabel, topLeftLabel,
new Separator(VERTICAL), new Separator(VERTICAL),
topRightLabel, topRightLabel,
new Separator(VERTICAL), new Separator(VERTICAL),
bottomLeftLabel, bottomLeftLabel,
new Separator(VERTICAL), new Separator(VERTICAL),
bottomRightLabel bottomRightLabel
); );
return new SampleBlock("Position", flowPane); return new SampleBlock("Position", flowPane);

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page.components; package atlantafx.sampler.page.components;
import static atlantafx.base.theme.Styles.DENSE; import static atlantafx.base.theme.Styles.DENSE;
@ -38,10 +39,12 @@ public class TreePage extends AbstractPage {
public static final String NAME = "TreeView"; public static final String NAME = "TreeView";
private static final int MAX_TREE_DEPTH = 3; private static final int MAX_TREE_DEPTH = 3;
private static final int[] TREE_DICE = { -1, 0, 1 }; private static final int[] TREE_DICE = {-1, 0, 1};
@Override @Override
public String getName() { return NAME; } public String getName() {
return NAME;
}
private final BorderPane treeWrapper = new BorderPane(); private final BorderPane treeWrapper = new BorderPane();
private final ComboBox<Example> exampleSelect = createExampleSelect(); private final ComboBox<Example> exampleSelect = createExampleSelect();
@ -57,28 +60,32 @@ public class TreePage extends AbstractPage {
private VBox createPlayground() { private VBox createPlayground() {
var denseToggle = new ToggleSwitch("Dense"); var denseToggle = new ToggleSwitch("Dense");
denseToggle.selectedProperty().addListener( denseToggle.selectedProperty().addListener(
(obs, old, value) -> findDisplayedTree().ifPresent(tv -> toggleStyleClass(tv, DENSE)) (obs, old, value) -> findDisplayedTree().ifPresent(tv -> toggleStyleClass(tv, DENSE))
); );
var showRootToggle = new ToggleSwitch("Show root"); var showRootToggle = new ToggleSwitch("Show root");
showRootToggle.selectedProperty().addListener((obs, old, val) -> findDisplayedTree().ifPresent(tv -> { showRootToggle.selectedProperty().addListener((obs, old, val) -> findDisplayedTree().ifPresent(tv -> {
if (val != null) { tv.setShowRoot(val); } if (val != null) {
tv.setShowRoot(val);
}
})); }));
showRootToggle.setSelected(true); showRootToggle.setSelected(true);
var altIconToggle = new ToggleSwitch("Alt icon"); var altIconToggle = new ToggleSwitch("Alt icon");
altIconToggle.selectedProperty().addListener((obs, old, val) -> altIconToggle.selectedProperty().addListener((obs, old, val) ->
findDisplayedTree().ifPresent(tv -> toggleStyleClass(tv, Tweaks.ALT_ICON)) findDisplayedTree().ifPresent(tv -> toggleStyleClass(tv, Tweaks.ALT_ICON))
); );
var edge2edgeToggle = new ToggleSwitch("Edge to edge"); var edge2edgeToggle = new ToggleSwitch("Edge to edge");
edge2edgeToggle.selectedProperty().addListener( edge2edgeToggle.selectedProperty().addListener(
(obs, old, val) -> findDisplayedTree().ifPresent(tv -> toggleStyleClass(tv, Tweaks.EDGE_TO_EDGE)) (obs, old, val) -> findDisplayedTree().ifPresent(tv -> toggleStyleClass(tv, Tweaks.EDGE_TO_EDGE))
); );
var disableToggle = new ToggleSwitch("Disable"); var disableToggle = new ToggleSwitch("Disable");
disableToggle.selectedProperty().addListener((obs, old, val) -> findDisplayedTree().ifPresent(tv -> { disableToggle.selectedProperty().addListener((obs, old, val) -> findDisplayedTree().ifPresent(tv -> {
if (val != null) { tv.setDisable(val); } if (val != null) {
tv.setDisable(val);
}
})); }));
var controls = new HBox(BLOCK_HGAP, denseToggle, showRootToggle, altIconToggle, edge2edgeToggle); var controls = new HBox(BLOCK_HGAP, denseToggle, showRootToggle, altIconToggle, edge2edgeToggle);
@ -87,11 +94,11 @@ public class TreePage extends AbstractPage {
VBox.setVgrow(treeWrapper, Priority.ALWAYS); VBox.setVgrow(treeWrapper, Priority.ALWAYS);
var playground = new VBox( var playground = new VBox(
BLOCK_VGAP, BLOCK_VGAP,
new HBox(new Label("Select an example:"), new Spacer(), disableToggle), new HBox(new Label("Select an example:"), new Spacer(), disableToggle),
exampleSelect, exampleSelect,
treeWrapper, treeWrapper,
controls controls
); );
playground.setMinHeight(100); playground.setMinHeight(100);
@ -103,7 +110,9 @@ public class TreePage extends AbstractPage {
select.setMaxWidth(Double.MAX_VALUE); select.setMaxWidth(Double.MAX_VALUE);
select.getItems().setAll(Example.values()); select.getItems().setAll(Example.values());
select.getSelectionModel().selectedItemProperty().addListener((obs, old, val) -> { select.getSelectionModel().selectedItemProperty().addListener((obs, old, val) -> {
if (val == null) { return; } if (val == null) {
return;
}
TreeView<String> newTree = createTree(val); TreeView<String> newTree = createTree(val);
@ -142,24 +151,38 @@ public class TreePage extends AbstractPage {
private Optional<TreeView<?>> findDisplayedTree() { private Optional<TreeView<?>> findDisplayedTree() {
return treeWrapper.getChildren().size() > 0 ? return treeWrapper.getChildren().size() > 0 ?
Optional.of((TreeView<?>) treeWrapper.getChildren().get(0)) : Optional.of((TreeView<?>) treeWrapper.getChildren().get(0)) :
Optional.empty(); Optional.empty();
} }
private TreeView<String> createTree(Example example) { private TreeView<String> createTree(Example example) {
switch (example) { switch (example) {
case TEXT -> { return stringTree(); } case TEXT -> {
case GRAPHIC -> { return graphicTree(); } return stringTree();
case EDITABLE -> { return editableTree(); } }
case CHECK_BOX -> { return checkBoxTree(); } case GRAPHIC -> {
case CHOICE_BOX -> { return choiceBoxTree(); } return graphicTree();
case COMBO_BOX -> { return comboBoxTree(); } }
case EDITABLE -> {
return editableTree();
}
case CHECK_BOX -> {
return checkBoxTree();
}
case CHOICE_BOX -> {
return choiceBoxTree();
}
case COMBO_BOX -> {
return comboBoxTree();
}
default -> throw new IllegalArgumentException("Unexpected enum value: " + example); default -> throw new IllegalArgumentException("Unexpected enum value: " + example);
} }
} }
private <T> void generateTree(TreeItem<T> parent, Supplier<TreeItem<T>> supplier, int limit, int depth) { private <T> void generateTree(TreeItem<T> parent, Supplier<TreeItem<T>> supplier, int limit, int depth) {
if (limit == 0) { return; } if (limit == 0) {
return;
}
var item = supplier.get(); var item = supplier.get();
parent.getChildren().add(item); parent.getChildren().add(item);
@ -239,7 +262,7 @@ public class TreePage extends AbstractPage {
var tree = new TreeView<String>(); var tree = new TreeView<String>();
tree.setCellFactory(ChoiceBoxTreeCell.forTreeView( tree.setCellFactory(ChoiceBoxTreeCell.forTreeView(
generate(() -> FAKER.internet().domainWord(), 10).toArray(String[]::new) generate(() -> FAKER.internet().domainWord(), 10).toArray(String[]::new)
)); ));
tree.setEditable(true); tree.setEditable(true);
@ -255,7 +278,7 @@ public class TreePage extends AbstractPage {
var tree = new TreeView<String>(); var tree = new TreeView<String>();
tree.setCellFactory(ComboBoxTreeCell.forTreeView( tree.setCellFactory(ComboBoxTreeCell.forTreeView(
generate(() -> FAKER.internet().domainWord(), 10).toArray(String[]::new) generate(() -> FAKER.internet().domainWord(), 10).toArray(String[]::new)
)); ));
tree.setEditable(true); tree.setEditable(true);
@ -287,9 +310,9 @@ public class TreePage extends AbstractPage {
public static Example find(String name) { public static Example find(String name) {
return Arrays.stream(Example.values()) return Arrays.stream(Example.values())
.filter(example -> Objects.equals(example.getName(), name)) .filter(example -> Objects.equals(example.getName(), name))
.findFirst() .findFirst()
.orElse(null); .orElse(null);
} }
} }
} }

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page.components; package atlantafx.sampler.page.components;
import static atlantafx.base.theme.Styles.BORDERED; import static atlantafx.base.theme.Styles.BORDERED;
@ -50,7 +51,9 @@ public class TreeTablePage extends AbstractPage {
public static final String NAME = "TreeTableView"; public static final String NAME = "TreeTableView";
@Override @Override
public String getName() { return NAME; } public String getName() {
return NAME;
}
private TreeTableView<Product> treeTable; private TreeTableView<Product> treeTable;
@ -79,7 +82,7 @@ public class TreeTablePage extends AbstractPage {
var edge2edgeToggle = new ToggleSwitch("Edge to edge"); var edge2edgeToggle = new ToggleSwitch("Edge to edge");
edge2edgeToggle.selectedProperty().addListener( edge2edgeToggle.selectedProperty().addListener(
(obs, old, value) -> toggleStyleClass(treeTable, Tweaks.EDGE_TO_EDGE) (obs, old, value) -> toggleStyleClass(treeTable, Tweaks.EDGE_TO_EDGE)
); );
var footer = new HBox(BLOCK_HGAP, bordersToggle, denseToggle, stripesToggle, altIconToggle, edge2edgeToggle); var footer = new HBox(BLOCK_HGAP, bordersToggle, denseToggle, stripesToggle, altIconToggle, edge2edgeToggle);
@ -98,7 +101,7 @@ public class TreeTablePage extends AbstractPage {
var group = new TreeItem<>(groupVal); var group = new TreeItem<>(groupVal);
group.getChildren().setAll( group.getChildren().setAll(
createTreeItems(idx * 100, FAKER.random().nextInt(5, 10), brand) createTreeItems(idx * 100, FAKER.random().nextInt(5, 10), brand)
); );
root.getChildren().add(group); root.getChildren().add(group);
} }
@ -143,15 +146,17 @@ public class TreeTablePage extends AbstractPage {
var disableToggle = new ToggleSwitch("Disable"); var disableToggle = new ToggleSwitch("Disable");
disableToggle.selectedProperty().addListener((obs, old, val) -> { disableToggle.selectedProperty().addListener((obs, old, val) -> {
if (val != null) { treeTable.setDisable(val); } if (val != null) {
treeTable.setDisable(val);
}
}); });
var header = new HBox( var header = new HBox(
createPropertiesMenu(treeTable), createPropertiesMenu(treeTable),
new Spacer(), new Spacer(),
alignBox, alignBox,
new Spacer(), new Spacer(),
disableToggle disableToggle
); );
header.setAlignment(Pos.CENTER_LEFT); header.setAlignment(Pos.CENTER_LEFT);
@ -165,9 +170,9 @@ public class TreeTablePage extends AbstractPage {
private List<TreeItem<Product>> createTreeItems(int startId, int count, String brand) { private List<TreeItem<Product>> createTreeItems(int startId, int count, String brand) {
return IntStream.range(startId, startId + count + 1).boxed() return IntStream.range(startId, startId + count + 1).boxed()
.map(id -> Product.random(id, brand, FAKER)) .map(id -> Product.random(id, brand, FAKER))
.map(TreeItem::new) .map(TreeItem::new)
.toList(); .toList();
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -189,7 +194,7 @@ public class TreeTablePage extends AbstractPage {
idCol.setCellValueFactory(cell -> { idCol.setCellValueFactory(cell -> {
Product product = cell.getValue().getValue(); Product product = cell.getValue().getValue();
return new SimpleStringProperty( return new SimpleStringProperty(
product != null && product.getId() != 0 ? String.valueOf(product.getId()) : "" product != null && product.getId() != 0 ? String.valueOf(product.getId()) : ""
); );
}); });
idCol.setEditable(false); idCol.setEditable(false);
@ -198,14 +203,14 @@ public class TreeTablePage extends AbstractPage {
var brandCol = new TreeTableColumn<Product, String>("Brand 🖉"); var brandCol = new TreeTableColumn<Product, String>("Brand 🖉");
brandCol.setCellValueFactory(new TreeItemPropertyValueFactory<>("brand")); brandCol.setCellValueFactory(new TreeItemPropertyValueFactory<>("brand"));
brandCol.setCellFactory(ChoiceBoxTreeTableCell.forTreeTableColumn( brandCol.setCellFactory(ChoiceBoxTreeTableCell.forTreeTableColumn(
generate(() -> FAKER.commerce().brand(), 10).toArray(String[]::new) generate(() -> FAKER.commerce().brand(), 10).toArray(String[]::new)
)); ));
brandCol.setEditable(true); brandCol.setEditable(true);
var nameCol = new TreeTableColumn<Product, String>("Name 🖉"); var nameCol = new TreeTableColumn<Product, String>("Name 🖉");
nameCol.setCellValueFactory(new TreeItemPropertyValueFactory<>("name")); nameCol.setCellValueFactory(new TreeItemPropertyValueFactory<>("name"));
nameCol.setCellFactory(ComboBoxTreeTableCell.forTreeTableColumn( nameCol.setCellFactory(ComboBoxTreeTableCell.forTreeTableColumn(
generate(() -> FAKER.commerce().productName(), 10).toArray(String[]::new) generate(() -> FAKER.commerce().productName(), 10).toArray(String[]::new)
)); ));
nameCol.setEditable(true); nameCol.setEditable(true);
nameCol.setMinWidth(200); nameCol.setMinWidth(200);
@ -281,17 +286,17 @@ public class TreeTablePage extends AbstractPage {
return new MenuButton("Properties") {{ return new MenuButton("Properties") {{
getItems().setAll( getItems().setAll(
resizePolicyCaption, resizePolicyCaption,
unconstrainedResizeItem, unconstrainedResizeItem,
constrainedResizeItem, constrainedResizeItem,
selectionModeCaption, selectionModeCaption,
singleSelectionItem, singleSelectionItem,
multiSelectionItem, multiSelectionItem,
new SeparatorMenuItem(), new SeparatorMenuItem(),
showRootItem, showRootItem,
editCellsItem, editCellsItem,
cellSelectionItem, cellSelectionItem,
menuButtonItem menuButtonItem
); );
}}; }};
} }

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page.general; package atlantafx.sampler.page.general;
import static atlantafx.base.theme.Styles.BUTTON_ICON; import static atlantafx.base.theme.Styles.BUTTON_ICON;
@ -28,10 +29,10 @@ public class AccentColorSelector extends HBox {
setAlignment(Pos.CENTER_LEFT); setAlignment(Pos.CENTER_LEFT);
getChildren().setAll( getChildren().setAll(
colorButton(AccentColor.primerPurple()), colorButton(AccentColor.primerPurple()),
colorButton(AccentColor.primerPink()), colorButton(AccentColor.primerPink()),
colorButton(AccentColor.primerCoral()), colorButton(AccentColor.primerCoral()),
resetBtn resetBtn
); );
getStyleClass().add("color-selector"); getStyleClass().add("color-selector");
} }

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page.general; package atlantafx.sampler.page.general;
import static atlantafx.sampler.util.Controls.hyperlink; import static atlantafx.sampler.util.Controls.hyperlink;
@ -47,25 +48,26 @@ class ColorPalette extends VBox {
var noteText = new VBox(6); var noteText = new VBox(6);
noteText.getChildren().setAll( noteText.getChildren().setAll(
new TextFlow( new TextFlow(
new Text("Color contrast between text and its background must meet "), new Text("Color contrast between text and its background must meet "),
hyperlink("required WCAG standards", hyperlink(
URI.create("https://www.w3.org/WAI/WCAG21/Understanding/contrast-minimum.html") "required WCAG standards",
), URI.create("https://www.w3.org/WAI/WCAG21/Understanding/contrast-minimum.html")
new Text(":")
), ),
new Text(" • 4.5:1 for normal text"), new Text(":")
new Text(" • 3:1 for large text (>24px)"), ),
new Text(" • 3:1 for UI elements and graphics"), new Text(" • 4.5:1 for normal text"),
new Text(" • no contrast requirement for decorative and disabled elements"), new Text(" • 3:1 for large text (>24px)"),
new Text(), new Text(" • 3:1 for UI elements and graphics"),
new Text("Click on any color block to observe and modify color combination via built-in contrast checker.") new Text(" • no contrast requirement for decorative and disabled elements"),
new Text(),
new Text("Click on any color block to observe and modify color combination via built-in contrast checker.")
); );
var colorGrid = colorGrid(); var colorGrid = colorGrid();
backgroundProperty().addListener((obs, old, val) -> bgBaseColor.set( backgroundProperty().addListener((obs, old, val) -> bgBaseColor.set(
val != null && !val.getFills().isEmpty() ? (Color) val.getFills().get(0).getFill() : Color.WHITE val != null && !val.getFills().isEmpty() ? (Color) val.getFills().get(0).getFill() : Color.WHITE
)); ));
getChildren().setAll(headerBox, noteText, colorGrid); getChildren().setAll(headerBox, noteText, colorGrid);
@ -86,7 +88,9 @@ class ColorPalette extends VBox {
grid.add(colorBlock("-color-fg-default", "-color-accent-muted", "-color-accent-emphasis"), 2, 1); grid.add(colorBlock("-color-fg-default", "-color-accent-muted", "-color-accent-emphasis"), 2, 1);
grid.add(colorBlock("-color-accent-fg", "-color-accent-subtle", "-color-accent-emphasis"), 3, 1); grid.add(colorBlock("-color-accent-fg", "-color-accent-subtle", "-color-accent-emphasis"), 3, 1);
grid.add(colorBlock("-color-fg-emphasis", "-color-neutral-emphasis-plus", "-color-neutral-emphasis-plus"), 0, 2); grid.add(
colorBlock("-color-fg-emphasis", "-color-neutral-emphasis-plus", "-color-neutral-emphasis-plus"), 0, 2
);
grid.add(colorBlock("-color-fg-emphasis", "-color-neutral-emphasis", "-color-neutral-emphasis"), 1, 2); grid.add(colorBlock("-color-fg-emphasis", "-color-neutral-emphasis", "-color-neutral-emphasis"), 1, 2);
grid.add(colorBlock("-color-fg-default", "-color-neutral-muted", "-color-neutral-emphasis"), 2, 2); grid.add(colorBlock("-color-fg-default", "-color-neutral-muted", "-color-neutral-emphasis"), 2, 2);
grid.add(colorBlock("-color-fg-default", "-color-neutral-subtle", "-color-neutral-emphasis"), 3, 2); grid.add(colorBlock("-color-fg-default", "-color-neutral-subtle", "-color-neutral-emphasis"), 3, 2);

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page.general; package atlantafx.sampler.page.general;
import static atlantafx.base.theme.Styles.TITLE_3; import static atlantafx.base.theme.Styles.TITLE_3;
@ -64,7 +65,7 @@ class ColorPaletteBlock extends VBox {
colorRectangle = new AnchorPane(); colorRectangle = new AnchorPane();
colorRectangle.setStyle( colorRectangle.setStyle(
String.format("-fx-background-color:%s;-fx-border-color:%s;", bgColorName, borderColorName) String.format("-fx-background-color:%s;-fx-border-color:%s;", bgColorName, borderColorName)
); );
colorRectangle.getStyleClass().add("rectangle"); colorRectangle.getStyleClass().add("rectangle");
colorRectangle.getChildren().setAll(contrastRatioText, contrastLevelLabel, editIcon); colorRectangle.getChildren().setAll(contrastRatioText, contrastLevelLabel, editIcon);
@ -78,7 +79,7 @@ class ColorPaletteBlock extends VBox {
toggleHover(true); toggleHover(true);
editIcon.setFill(getColorLuminance(flattenColor(bgBaseColor.get(), bgFill)) < LUMINANCE_THRESHOLD ? editIcon.setFill(getColorLuminance(flattenColor(bgBaseColor.get(), bgFill)) < LUMINANCE_THRESHOLD ?
Color.WHITE : Color.BLACK Color.WHITE : Color.BLACK
); );
}); });
colorRectangle.setOnMouseExited(e -> toggleHover(false)); colorRectangle.setOnMouseExited(e -> toggleHover(false));
@ -89,10 +90,10 @@ class ColorPaletteBlock extends VBox {
}); });
getChildren().addAll( getChildren().addAll(
colorRectangle, colorRectangle,
colorNameText(fgColorName), colorNameText(fgColorName),
colorNameText(bgColorName), colorNameText(bgColorName),
colorNameText(borderColorName) colorNameText(borderColorName)
); );
getStyleClass().add("block"); getStyleClass().add("block");
} }
@ -116,7 +117,9 @@ class ColorPaletteBlock extends VBox {
colorRectangle.pseudoClassStateChanged(PASSED, ContrastLevel.AA_NORMAL.satisfies(contrastRatio)); colorRectangle.pseudoClassStateChanged(PASSED, ContrastLevel.AA_NORMAL.satisfies(contrastRatio));
contrastRatioText.setText(String.format("%.2f", contrastRatio)); contrastRatioText.setText(String.format("%.2f", contrastRatio));
contrastLevelIcon.setIconCode(ContrastLevel.AA_NORMAL.satisfies(contrastRatio) ? Material2AL.CHECK : Material2AL.CLOSE); contrastLevelIcon.setIconCode(
ContrastLevel.AA_NORMAL.satisfies(contrastRatio) ? Material2AL.CHECK : Material2AL.CLOSE
);
contrastLevelLabel.setVisible(true); contrastLevelLabel.setVisible(true);
contrastLevelLabel.setText(ContrastLevel.AAA_NORMAL.satisfies(contrastRatio) ? "AAA" : "AA"); contrastLevelLabel.setText(ContrastLevel.AAA_NORMAL.satisfies(contrastRatio) ? "AAA" : "AA");
} }
@ -127,7 +130,7 @@ class ColorPaletteBlock extends VBox {
public Color getBgColor() { public Color getBgColor() {
return colorRectangle.getBackground() != null && !colorRectangle.getBackground().isEmpty() ? return colorRectangle.getBackground() != null && !colorRectangle.getBackground().isEmpty() ?
(Color) colorRectangle.getBackground().getFills().get(0).getFill() : null; (Color) colorRectangle.getBackground().getFills().get(0).getFill() : null;
} }
public String getFgColorName() { public String getFgColorName() {

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page.general; package atlantafx.sampler.page.general;
import atlantafx.base.theme.Styles; import atlantafx.base.theme.Styles;
@ -21,12 +22,12 @@ class ColorScale extends VBox {
private final ReadOnlyObjectWrapper<Color> bgBaseColor = new ReadOnlyObjectWrapper<>(Color.WHITE); private final ReadOnlyObjectWrapper<Color> bgBaseColor = new ReadOnlyObjectWrapper<>(Color.WHITE);
private final List<ColorScaleBlock> blocks = Arrays.asList( private final List<ColorScaleBlock> blocks = Arrays.asList(
ColorScaleBlock.forColorPrefix(bgBaseColor, "-color-base-", 10), ColorScaleBlock.forColorPrefix(bgBaseColor, "-color-base-", 10),
ColorScaleBlock.forColorPrefix(bgBaseColor, "-color-accent-", 10), ColorScaleBlock.forColorPrefix(bgBaseColor, "-color-accent-", 10),
ColorScaleBlock.forColorPrefix(bgBaseColor, "-color-success-", 10), ColorScaleBlock.forColorPrefix(bgBaseColor, "-color-success-", 10),
ColorScaleBlock.forColorPrefix(bgBaseColor, "-color-warning-", 10), ColorScaleBlock.forColorPrefix(bgBaseColor, "-color-warning-", 10),
ColorScaleBlock.forColorPrefix(bgBaseColor, "-color-danger-", 10), ColorScaleBlock.forColorPrefix(bgBaseColor, "-color-danger-", 10),
ColorScaleBlock.forColorName(bgBaseColor, "-color-dark", "-color-light") ColorScaleBlock.forColorName(bgBaseColor, "-color-dark", "-color-light")
); );
public ColorScale() { public ColorScale() {
@ -44,18 +45,20 @@ class ColorScale extends VBox {
headerBox.getStyleClass().add("header"); headerBox.getStyleClass().add("header");
var noteText = new TextFlow( var noteText = new TextFlow(
new Text("Avoid referencing scale variables directly when building UI that needs to adapt to different color themes. Instead, use the functional variables listed above.") new Text(
"Avoid referencing scale variables directly when building UI that needs to adapt to different color themes. Instead, use the functional variables listed above."
)
); );
backgroundProperty().addListener((obs, old, val) -> bgBaseColor.set( backgroundProperty().addListener((obs, old, val) -> bgBaseColor.set(
val != null && !val.getFills().isEmpty() ? (Color) val.getFills().get(0).getFill() : Color.WHITE val != null && !val.getFills().isEmpty() ? (Color) val.getFills().get(0).getFill() : Color.WHITE
)); ));
setId("color-scale"); setId("color-scale");
getChildren().setAll( getChildren().setAll(
headerBox, headerBox,
noteText, noteText,
colorTable() colorTable()
); );
} }

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page.general; package atlantafx.sampler.page.general;
import static atlantafx.sampler.util.ContrastLevel.getColorLuminance; import static atlantafx.sampler.util.ContrastLevel.getColorLuminance;
@ -34,8 +35,8 @@ class ColorScaleBlock extends VBox {
if (c instanceof Label label) { if (c instanceof Label label) {
String colorName = (String) label.getUserData(); String colorName = (String) label.getUserData();
label.setStyle(String.format("-fx-background-color:%s;-fx-text-fill:%s;", label.setStyle(String.format("-fx-background-color:%s;-fx-text-fill:%s;",
colorName, colorName,
JColorUtils.toHexWithAlpha(getSafeFgColor(label)) JColorUtils.toHexWithAlpha(getSafeFgColor(label))
)); ));
} }
}); });
@ -67,7 +68,7 @@ class ColorScaleBlock extends VBox {
private Color getBgColor(Label label) { private Color getBgColor(Label label) {
return label.getBackground() != null && !label.getBackground().isEmpty() ? return label.getBackground() != null && !label.getBackground().isEmpty() ?
(Color) label.getBackground().getFills().get(0).getFill() : Color.WHITE; (Color) label.getBackground().getFills().get(0).getFill() : Color.WHITE;
} }
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page.general; package atlantafx.sampler.page.general;
import static atlantafx.sampler.page.general.ColorPaletteBlock.validateColorName; import static atlantafx.sampler.page.general.ColorPaletteBlock.validateColorName;
@ -76,10 +77,10 @@ class ContrastChecker extends GridPane {
this.bgBaseColor = bgBaseColor; this.bgBaseColor = bgBaseColor;
this.contrastRatio = Bindings.createDoubleBinding( this.contrastRatio = Bindings.createDoubleBinding(
() -> getContrastRatioOpacityAware(bgColor.getColor(), fgColor.getColor(), bgBaseColor.get()), () -> getContrastRatioOpacityAware(bgColor.getColor(), fgColor.getColor(), bgBaseColor.get()),
bgColor.colorProperty(), bgColor.colorProperty(),
fgColor.colorProperty(), fgColor.colorProperty(),
bgBaseColor bgBaseColor
); );
createView(); createView();
@ -96,22 +97,35 @@ class ContrastChecker extends GridPane {
setForeground(fgColor); setForeground(fgColor);
} }
public String getBgColorName() { return bgColorName; } public String getBgColorName() {
return bgColorName;
}
public String getFgColorName() { return fgColorName; } public String getFgColorName() {
return fgColorName;
}
public Color getBgColor() { return bgColor.colorProperty().get(); } public Color getBgColor() {
return bgColor.colorProperty().get();
}
public Color getFgColor() { return fgColor.colorProperty().get(); } public Color getFgColor() {
return fgColor.colorProperty().get();
}
public ReadOnlyObjectProperty<Color> bgColorProperty() { return bgColor.colorProperty(); } public ReadOnlyObjectProperty<Color> bgColorProperty() {
return bgColor.colorProperty();
}
public ReadOnlyObjectProperty<Color> fgColorProperty() { return fgColor.colorProperty(); } public ReadOnlyObjectProperty<Color> fgColorProperty() {
return fgColor.colorProperty();
}
// Returns fg color that guaranteed to be visible on the current bg. // Returns fg color that guaranteed to be visible on the current bg.
public Color getSafeFgColor() { public Color getSafeFgColor() {
if (contrastRatio.get() <= CONTRAST_RATIO_THRESHOLD) { if (contrastRatio.get() <= CONTRAST_RATIO_THRESHOLD) {
return getColorLuminance(flattenColor(bgBaseColor.get(), bgColor.getColor())) < LUMINANCE_THRESHOLD ? Color.WHITE : Color.BLACK; return getColorLuminance(flattenColor(bgBaseColor.get(), bgColor.getColor())) < LUMINANCE_THRESHOLD ?
Color.WHITE : Color.BLACK;
} else { } else {
return fgColor.getColor(); return fgColor.getColor();
} }
@ -124,7 +138,7 @@ class ContrastChecker extends GridPane {
var contrastRatioLabel = new Label("0.0"); var contrastRatioLabel = new Label("0.0");
contrastRatioLabel.getStyleClass().add("ratio"); contrastRatioLabel.getStyleClass().add("ratio");
contrastRatioLabel.textProperty().bind(Bindings.createStringBinding( contrastRatioLabel.textProperty().bind(Bindings.createStringBinding(
() -> String.format("%.2f", contrastRatio.get()), contrastRatio () -> String.format("%.2f", contrastRatio.get()), contrastRatio
)); ));
var contrastRatioBox = new HBox(20, largeFontLabel, contrastRatioLabel); var contrastRatioBox = new HBox(20, largeFontLabel, contrastRatioLabel);
@ -148,7 +162,9 @@ class ContrastChecker extends GridPane {
var contrastLevels = new HBox(20, aaNormalBox, aaLargeBox, aaaNormalBox, aaaLargeBox); var contrastLevels = new HBox(20, aaNormalBox, aaLargeBox, aaaNormalBox, aaaLargeBox);
contrastRatio.addListener((obs, old, val) -> { contrastRatio.addListener((obs, old, val) -> {
if (val == null) { return; } if (val == null) {
return;
}
float ratio = val.floatValue(); float ratio = val.floatValue();
updateContrastLevelLabel(aaNormalLabel, ContrastLevel.AA_NORMAL.satisfies(ratio)); updateContrastLevelLabel(aaNormalLabel, ContrastLevel.AA_NORMAL.satisfies(ratio));
updateContrastLevelLabel(aaLargeLabel, ContrastLevel.AA_LARGE.satisfies(ratio)); updateContrastLevelLabel(aaLargeLabel, ContrastLevel.AA_LARGE.satisfies(ratio));
@ -166,7 +182,7 @@ class ContrastChecker extends GridPane {
bgTextField.setEditable(false); bgTextField.setEditable(false);
bgTextField.setLeft(new FontIcon(Feather.HASH)); bgTextField.setLeft(new FontIcon(Feather.HASH));
bgTextField.textProperty().bind(Bindings.createStringBinding( bgTextField.textProperty().bind(Bindings.createStringBinding(
() -> bgColor.getColorHexWithAlpha().substring(1), bgColor.colorProperty() () -> bgColor.getColorHexWithAlpha().substring(1), bgColor.colorProperty()
)); ));
bgTextField.setContextMenu(new RightClickMenu(bgColor)); bgTextField.setContextMenu(new RightClickMenu(bgColor));
@ -178,82 +194,98 @@ class ContrastChecker extends GridPane {
fgTextField.setEditable(false); fgTextField.setEditable(false);
fgTextField.setLeft(new FontIcon(Feather.HASH)); fgTextField.setLeft(new FontIcon(Feather.HASH));
fgTextField.textProperty().bind(Bindings.createStringBinding( fgTextField.textProperty().bind(Bindings.createStringBinding(
() -> fgColor.getColorHexWithAlpha().substring(1), fgColor.colorProperty() () -> fgColor.getColorHexWithAlpha().substring(1), fgColor.colorProperty()
)); ));
fgTextField.setContextMenu(new RightClickMenu(fgColor)); fgTextField.setContextMenu(new RightClickMenu(fgColor));
bgHueSlider = slider(1, 360, 1, 1); bgHueSlider = slider(1, 360, 1, 1);
bgHueSlider.valueProperty().addListener((obs, old, val) -> { bgHueSlider.valueProperty().addListener((obs, old, val) -> {
if (val != null) { bgColor.setHue(val.floatValue()); } if (val != null) {
bgColor.setHue(val.floatValue());
}
}); });
var bgHueLabel = new Label("Hue °"); var bgHueLabel = new Label("Hue °");
bgHueLabel.textProperty().bind(Bindings.createStringBinding( bgHueLabel.textProperty().bind(Bindings.createStringBinding(
() -> String.format("Hue %.0f °", bgHueSlider.getValue()), bgHueSlider.valueProperty()) () -> String.format("Hue %.0f °", bgHueSlider.getValue()), bgHueSlider.valueProperty())
); );
bgSaturationSlider = slider(0, 1, 0, 0.01); bgSaturationSlider = slider(0, 1, 0, 0.01);
bgSaturationSlider.valueProperty().addListener((obs, old, val) -> { bgSaturationSlider.valueProperty().addListener((obs, old, val) -> {
if (val != null) { bgColor.setSaturation(val.floatValue()); } if (val != null) {
bgColor.setSaturation(val.floatValue());
}
}); });
var bgSaturationLabel = new Label("Saturation"); var bgSaturationLabel = new Label("Saturation");
bgSaturationLabel.textProperty().bind(Bindings.createStringBinding( bgSaturationLabel.textProperty().bind(Bindings.createStringBinding(
() -> String.format("Saturation %.2f", bgSaturationSlider.getValue()), bgSaturationSlider.valueProperty()) () -> String.format("Saturation %.2f", bgSaturationSlider.getValue()), bgSaturationSlider.valueProperty())
); );
bgLightnessSlider = slider(0, 1, 0, 0.01); bgLightnessSlider = slider(0, 1, 0, 0.01);
bgLightnessSlider.valueProperty().addListener((obs, old, val) -> { bgLightnessSlider.valueProperty().addListener((obs, old, val) -> {
if (val != null) { bgColor.setLightness(val.floatValue()); } if (val != null) {
bgColor.setLightness(val.floatValue());
}
}); });
var bgLightnessLabel = new Label("Lightness"); var bgLightnessLabel = new Label("Lightness");
bgLightnessLabel.textProperty().bind(Bindings.createStringBinding( bgLightnessLabel.textProperty().bind(Bindings.createStringBinding(
() -> String.format("Lightness %.2f", bgLightnessSlider.getValue()), bgLightnessSlider.valueProperty()) () -> String.format("Lightness %.2f", bgLightnessSlider.getValue()), bgLightnessSlider.valueProperty())
); );
bgAlphaSlider = slider(0, 1, 0, 0.01); bgAlphaSlider = slider(0, 1, 0, 0.01);
bgAlphaSlider.valueProperty().addListener((obs, old, val) -> { bgAlphaSlider.valueProperty().addListener((obs, old, val) -> {
if (val != null) { bgColor.setAlpha(val.floatValue()); } if (val != null) {
bgColor.setAlpha(val.floatValue());
}
}); });
var bgAlphaLabel = new Label("Alpha"); var bgAlphaLabel = new Label("Alpha");
bgAlphaLabel.textProperty().bind(Bindings.createStringBinding( bgAlphaLabel.textProperty().bind(Bindings.createStringBinding(
() -> String.format("Alpha %.2f", bgAlphaSlider.getValue()), bgAlphaSlider.valueProperty()) () -> String.format("Alpha %.2f", bgAlphaSlider.getValue()), bgAlphaSlider.valueProperty())
); );
// ~ // ~
fgHueSlider = slider(1, 360, 1, 1); fgHueSlider = slider(1, 360, 1, 1);
fgHueSlider.valueProperty().addListener((obs, old, val) -> { fgHueSlider.valueProperty().addListener((obs, old, val) -> {
if (val != null) { fgColor.setHue(val.floatValue()); } if (val != null) {
fgColor.setHue(val.floatValue());
}
}); });
var fgHueLabel = new Label("Hue °"); var fgHueLabel = new Label("Hue °");
fgHueLabel.textProperty().bind(Bindings.createStringBinding( fgHueLabel.textProperty().bind(Bindings.createStringBinding(
() -> String.format("Hue %.0f °", fgHueSlider.getValue()), fgHueSlider.valueProperty()) () -> String.format("Hue %.0f °", fgHueSlider.getValue()), fgHueSlider.valueProperty())
); );
fgSaturationSlider = slider(0, 1, 0, 0.01); fgSaturationSlider = slider(0, 1, 0, 0.01);
fgSaturationSlider.valueProperty().addListener((obs, old, val) -> { fgSaturationSlider.valueProperty().addListener((obs, old, val) -> {
if (val != null) { fgColor.setSaturation(val.floatValue()); } if (val != null) {
fgColor.setSaturation(val.floatValue());
}
}); });
var fgSaturationLabel = new Label("Saturation"); var fgSaturationLabel = new Label("Saturation");
fgSaturationLabel.textProperty().bind(Bindings.createStringBinding( fgSaturationLabel.textProperty().bind(Bindings.createStringBinding(
() -> String.format("Saturation %.2f", fgSaturationSlider.getValue()), fgSaturationSlider.valueProperty()) () -> String.format("Saturation %.2f", fgSaturationSlider.getValue()), fgSaturationSlider.valueProperty())
); );
fgLightnessSlider = slider(0, 1, 0, 0.01); fgLightnessSlider = slider(0, 1, 0, 0.01);
fgLightnessSlider.valueProperty().addListener((obs, old, val) -> { fgLightnessSlider.valueProperty().addListener((obs, old, val) -> {
if (val != null) { fgColor.setLightness(val.floatValue()); } if (val != null) {
fgColor.setLightness(val.floatValue());
}
}); });
var fgLightnessLabel = new Label("Lightness"); var fgLightnessLabel = new Label("Lightness");
fgLightnessLabel.textProperty().bind(Bindings.createStringBinding( fgLightnessLabel.textProperty().bind(Bindings.createStringBinding(
() -> String.format("Lightness %.2f", fgLightnessSlider.getValue()), fgLightnessSlider.valueProperty()) () -> String.format("Lightness %.2f", fgLightnessSlider.getValue()), fgLightnessSlider.valueProperty())
); );
fgAlphaSlider = slider(0, 1, 0, 0.01); fgAlphaSlider = slider(0, 1, 0, 0.01);
fgAlphaSlider.valueProperty().addListener((obs, old, val) -> { fgAlphaSlider.valueProperty().addListener((obs, old, val) -> {
if (val != null) { fgColor.setAlpha(val.floatValue()); } if (val != null) {
fgColor.setAlpha(val.floatValue());
}
}); });
var fgAlphaLabel = new Label("Alpha"); var fgAlphaLabel = new Label("Alpha");
fgAlphaLabel.textProperty().bind(Bindings.createStringBinding( fgAlphaLabel.textProperty().bind(Bindings.createStringBinding(
() -> String.format("Alpha %.2f", fgAlphaSlider.getValue()), fgAlphaSlider.valueProperty()) () -> String.format("Alpha %.2f", fgAlphaSlider.getValue()), fgAlphaSlider.valueProperty())
); );
// ~ // ~
@ -269,8 +301,8 @@ class ContrastChecker extends GridPane {
var applyBtn = new Button("Apply"); var applyBtn = new Button("Apply");
applyBtn.setOnAction(e -> ThemeManager.getInstance().setNamedColors(Map.of( applyBtn.setOnAction(e -> ThemeManager.getInstance().setNamedColors(Map.of(
getBgColorName(), bgColor.getColor(), getBgColorName(), bgColor.getColor(),
getFgColorName(), fgColor.getColor() getFgColorName(), fgColor.getColor()
))); )));
var actionsBox = new HBox(20, new Spacer(), flattenBtn, applyBtn); var actionsBox = new HBox(20, new Spacer(), flattenBtn, applyBtn);
@ -312,18 +344,22 @@ class ContrastChecker extends GridPane {
add(fgAlphaSlider, 1, 11); add(fgAlphaSlider, 1, 11);
bgColor.colorProperty().addListener((obs, old, val) -> { bgColor.colorProperty().addListener((obs, old, val) -> {
if (val != null) { updateStyle(); } if (val != null) {
updateStyle();
}
}); });
fgColor.colorProperty().addListener((obs, old, val) -> { fgColor.colorProperty().addListener((obs, old, val) -> {
if (val != null) { updateStyle(); } if (val != null) {
updateStyle();
}
}); });
} }
private void updateStyle() { private void updateStyle() {
setStyle(String.format("-color-contrast-checker-bg:%s;-color-contrast-checker-fg:%s;", setStyle(String.format("-color-contrast-checker-bg:%s;-color-contrast-checker-fg:%s;",
toHexWithAlpha(bgColor.getColor()), toHexWithAlpha(bgColor.getColor()),
toHexWithAlpha(getSafeFgColor()) toHexWithAlpha(getSafeFgColor())
)); ));
} }
@ -385,7 +421,8 @@ class ContrastChecker extends GridPane {
private static class ObservableHSLAColor { private static class ObservableHSLAColor {
private final ObservableList<Float> values = FXCollections.observableArrayList(0f, 0f, 0f, 0f); private final ObservableList<Float> values = FXCollections.observableArrayList(0f, 0f, 0f, 0f);
private final ReadOnlyObjectWrapper<Color> color = new ReadOnlyObjectWrapper<>() { }; private final ReadOnlyObjectWrapper<Color> color = new ReadOnlyObjectWrapper<>() {
};
public ObservableHSLAColor(Color initialColor) { public ObservableHSLAColor(Color initialColor) {
values.addListener((ListChangeListener<Float>) c -> { values.addListener((ListChangeListener<Float>) c -> {
@ -441,18 +478,18 @@ class ContrastChecker extends GridPane {
} }
public float[] getRGBAArithmeticColor() { public float[] getRGBAArithmeticColor() {
float[] hsl = new float[] { getHue(), getSaturation(), getLightness() }; float[] hsl = new float[] {getHue(), getSaturation(), getLightness()};
var color = JColor.color(hsl, getAlpha()); var color = JColor.color(hsl, getAlpha());
return new float[] { return new float[] {
color.getRedArithmetic(), color.getRedArithmetic(),
color.getGreenArithmetic(), color.getGreenArithmetic(),
color.getBlueArithmetic(), color.getBlueArithmetic(),
getAlpha() getAlpha()
}; };
} }
public String getColorHexWithAlpha() { public String getColorHexWithAlpha() {
float[] hsl = new float[] { getHue(), getSaturation(), getLightness() }; float[] hsl = new float[] {getHue(), getSaturation(), getLightness()};
return JColor.color(hsl, getAlpha()).getColorHexWithAlpha(); return JColor.color(hsl, getAlpha()).getColorHexWithAlpha();
} }
} }
@ -472,28 +509,33 @@ class ContrastChecker extends GridPane {
private void createMenu() { private void createMenu() {
var hexItem = new MenuItem("Copy as HEX"); var hexItem = new MenuItem("Copy as HEX");
hexItem.setOnAction(e -> { hexItem.setOnAction(e -> {
var c = JColor.color(new float[] {color.getHue(), color.getSaturation(), color.getLightness(), color.getAlpha()}); var c = JColor.color(
new float[] {color.getHue(), color.getSaturation(), color.getLightness(), color.getAlpha()});
PlatformUtils.copyToClipboard(color.getAlpha() < 1 ? PlatformUtils.copyToClipboard(color.getAlpha() < 1 ?
toHexWithAlpha(color.getColor()) : toHexWithAlpha(color.getColor()) :
c.getColorHex() c.getColorHex()
); );
}); });
var rgbItem = new MenuItem("Copy as RGB"); var rgbItem = new MenuItem("Copy as RGB");
rgbItem.setOnAction(e -> { rgbItem.setOnAction(e -> {
var c = JColor.color(new float[] {color.getHue(), color.getSaturation(), color.getLightness(), color.getAlpha()}); var c = JColor.color(
new float[] {color.getHue(), color.getSaturation(), color.getLightness(), color.getAlpha()});
PlatformUtils.copyToClipboard(color.getAlpha() < 1 ? PlatformUtils.copyToClipboard(color.getAlpha() < 1 ?
String.format("rgba(%d,%d,%d, %.1f)", c.getGreen(), c.getGreen(), c.getBlue(), c.getAlphaArithmetic()) : String.format("rgba(%d,%d,%d, %.1f)", c.getGreen(), c.getGreen(), c.getBlue(),
String.format("rgb(%d,%d,%d)", c.getGreen(), c.getGreen(), c.getBlue()) c.getAlphaArithmetic()) :
String.format("rgb(%d,%d,%d)", c.getGreen(), c.getGreen(), c.getBlue())
); );
}); });
var hslItem = new MenuItem("Copy as HSL"); var hslItem = new MenuItem("Copy as HSL");
hslItem.setOnAction(e -> { hslItem.setOnAction(e -> {
var c = JColor.color(new float[] {color.getHue(), color.getSaturation(), color.getLightness(), color.getAlpha()}); var c = JColor.color(
new float[] {color.getHue(), color.getSaturation(), color.getLightness(), color.getAlpha()});
PlatformUtils.copyToClipboard(color.getAlpha() < 1 ? PlatformUtils.copyToClipboard(color.getAlpha() < 1 ?
String.format("hsla(%.0f,%.2f,%.2f, %.1f)", c.getHue(), c.getSaturation(), c.getLightness(), c.getAlphaArithmetic()) : String.format("hsla(%.0f,%.2f,%.2f, %.1f)", c.getHue(), c.getSaturation(), c.getLightness(),
String.format("hsl(%.0f,%.2f,%.2f)", c.getHue(), c.getSaturation(), c.getLightness()) c.getAlphaArithmetic()) :
String.format("hsl(%.0f,%.2f,%.2f)", c.getHue(), c.getSaturation(), c.getLightness())
); );
}); });

@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
package atlantafx.sampler.page.general; package atlantafx.sampler.page.general;
import atlantafx.sampler.page.OverlayDialog; import atlantafx.sampler.page.OverlayDialog;
@ -25,8 +26,8 @@ class ContrastCheckerDialog extends OverlayDialog<ContrastChecker> {
private void updateStyle() { private void updateStyle() {
setStyle(String.format("-color-dialog-bg:%s;-color-dialog-fg:%s;", setStyle(String.format("-color-dialog-bg:%s;-color-dialog-fg:%s;",
JColorUtils.toHexWithAlpha(contrastChecker.getBgColor()), JColorUtils.toHexWithAlpha(contrastChecker.getBgColor()),
JColorUtils.toHexWithAlpha(contrastChecker.getSafeFgColor()) JColorUtils.toHexWithAlpha(contrastChecker.getSafeFgColor())
)); ));
} }

@ -70,8 +70,8 @@ public class IconBrowser extends TableView<List<Ikon>> {
private void updateData(String filterString) { private void updateData(String filterString) {
var displayedIcons = filterString == null || filterString.isBlank() || filterString.length() < FILTER_LEN var displayedIcons = filterString == null || filterString.isBlank() || filterString.length() < FILTER_LEN
? icons ? icons
: icons.stream().filter(icon -> containsString(icon.getDescription(), filterString)).toList(); : icons.stream().filter(icon -> containsString(icon.getDescription(), filterString)).toList();
var data = partitionList(displayedIcons, colNum); var data = partitionList(displayedIcons, colNum);
getItems().setAll(data); getItems().setAll(data);

Some files were not shown because too many files have changed in this diff Show More