Write a Javadoc for all controls, layouts and utils
This commit is contained in:
parent
750ed00e11
commit
357f31da64
@ -1,24 +1,59 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*/
|
||||
|
||||
package atlantafx.base.controls;
|
||||
|
||||
import javafx.scene.control.Control;
|
||||
import javafx.scene.control.SkinBase;
|
||||
|
||||
public abstract class BehaviorBase<C extends Control, S extends SkinBase<C>> {
|
||||
/**
|
||||
* Encapsulates behavior interaction logic for a skin. The main functionality
|
||||
* in BehaviorBase revolves around infrastructure for resolving events into
|
||||
* function calls. A BehaviorBase implementation will usually contain logic for
|
||||
* handling key events based on the host platform, as well as view-specific
|
||||
* functions for handling mouse and key and other input events.
|
||||
*
|
||||
* <p>Although BehaviorBase is typically used as a base class, it is not abstract and
|
||||
* several skins instantiate an instance of BehaviorBase directly.
|
||||
*
|
||||
* <p>Note: This is an excerpt of the private Behavior API from the JavaFX codebase.
|
||||
* It serves as a compatibility layer for implementing certain controls, although it
|
||||
* can also be useful for new controls.
|
||||
*/
|
||||
public class BehaviorBase<C extends Control, S extends SkinBase<C>> {
|
||||
|
||||
private C control;
|
||||
private S skin;
|
||||
|
||||
/**
|
||||
* Constructor for all BehaviorBase instances.
|
||||
*
|
||||
* @param control The control for which this Skin should attach to.
|
||||
* @param skin The skin used by the control.
|
||||
*/
|
||||
protected BehaviorBase(C control, S skin) {
|
||||
this.control = control;
|
||||
this.skin = skin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the control associated with this behavior.
|
||||
*
|
||||
* @return The control for this behavior.
|
||||
*/
|
||||
public C getControl() {
|
||||
return control;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the skin associated with this behavior.
|
||||
*
|
||||
* @return The control for this behavior.
|
||||
*/
|
||||
public S getSkin() {
|
||||
return skin;
|
||||
}
|
||||
|
@ -1,4 +1,9 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*/
|
||||
|
||||
package atlantafx.base.controls;
|
||||
|
||||
@ -7,21 +12,48 @@ import javafx.beans.value.ObservableValue;
|
||||
import javafx.scene.control.Control;
|
||||
import javafx.scene.control.SkinBase;
|
||||
|
||||
/**
|
||||
* Base implementation class for defining the visual representation of user
|
||||
* interface controls that need to handle platform events and therefore can take
|
||||
* advantage of using the Behavior API.
|
||||
*
|
||||
* <p>Note: This is an excerpt of the private Behavior API from the JavaFX codebase.
|
||||
* It serves as a compatibility layer for implementing certain controls, although it
|
||||
* can also be useful for new controls.
|
||||
*/
|
||||
public abstract class BehaviorSkinBase<C extends Control, B extends BehaviorBase<C, ?>> extends SkinBase<C> {
|
||||
|
||||
protected B behavior;
|
||||
|
||||
/**
|
||||
* Constructor for all BehaviorSkinBase instances.
|
||||
*
|
||||
* @param control The control for which this Skin should attach to.
|
||||
*/
|
||||
protected BehaviorSkinBase(C control) {
|
||||
super(control);
|
||||
behavior = createDefaultBehavior();
|
||||
}
|
||||
|
||||
/**
|
||||
* An abstract method for creating the behavior instance to be used by this skin.
|
||||
*/
|
||||
public abstract B createDefaultBehavior();
|
||||
|
||||
/**
|
||||
* Gets the control associated with this skin.
|
||||
*
|
||||
* @return The control for this Skin.
|
||||
*/
|
||||
public C getControl() {
|
||||
return getSkinnable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the behavior associated with this skin.
|
||||
*
|
||||
* @return The behavior for this skin.
|
||||
*/
|
||||
public B getBehavior() {
|
||||
return behavior;
|
||||
}
|
||||
|
@ -47,14 +47,21 @@ import javafx.scene.control.Skin;
|
||||
import javafx.scene.control.TreeItem;
|
||||
import javafx.scene.layout.Region;
|
||||
import javafx.util.Callback;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Represents a bread crumb bar. This control is useful to visualize and navigate
|
||||
* A bread crumb bar. This control is useful to visualize and navigate
|
||||
* a hierarchical path structure, such as file systems.
|
||||
*
|
||||
* <p>A breadcrumbs consist of two types of elements: a button (default is a hyperlink)
|
||||
* and a divider (default is for Label). You can customize both by providing the
|
||||
* corresponding control factory.
|
||||
* <pre>{@code
|
||||
* String[] list = {"Root", "Folder", "file.txt"};
|
||||
* BreadCrumbItem<String> selectedCrumb = Breadcrumbs.buildTreeModel(list);
|
||||
* Breadcrumbs<String> breadcrumbs = new Breadcrumbs<>(selectedCrumb);
|
||||
* }</pre>
|
||||
*
|
||||
* <p>A breadcrumbs consist of two types of elements: a button (default is
|
||||
* {@code Hyperlink}) and a divider (default is for {@code Label}). You can
|
||||
* customize both by providing the corresponding factory.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class Breadcrumbs<T> extends Control {
|
||||
@ -63,6 +70,7 @@ public class Breadcrumbs<T> extends Control {
|
||||
|
||||
protected final Callback<BreadCrumbItem<T>, ButtonBase> defaultCrumbNodeFactory =
|
||||
item -> new Hyperlink(item.getStringValue());
|
||||
|
||||
protected final Callback<BreadCrumbItem<T>, ? extends Node> defaultDividerFactory =
|
||||
item -> item != null && !item.isLast() ? new Label("/") : null;
|
||||
|
||||
@ -74,10 +82,12 @@ public class Breadcrumbs<T> extends Control {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a bread crumb bar with the given BreadCrumbItem as the currently
|
||||
* selected crumb.
|
||||
* Creates a bread crumb bar with the given BreadCrumbItem as the
|
||||
* currently {@link #selectedCrumbProperty()}.
|
||||
*
|
||||
* @param selectedCrumb The currently selected crumb.
|
||||
*/
|
||||
public Breadcrumbs(BreadCrumbItem<T> selectedCrumb) {
|
||||
public Breadcrumbs(@Nullable BreadCrumbItem<T> selectedCrumb) {
|
||||
getStyleClass().add(DEFAULT_STYLE_CLASS);
|
||||
|
||||
// breadcrumbs should be the size of its content
|
||||
@ -100,8 +110,10 @@ public class Breadcrumbs<T> extends Control {
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a tree model from the flat list which then can be set
|
||||
* as selectedCrumb node to be shown.
|
||||
* Constructs a tree model from the flat list which then can be set
|
||||
* as the {@code selectedCrumb} node to be shown.
|
||||
*
|
||||
* @param crumbs The flat list of values used to build the tree model
|
||||
*/
|
||||
@SafeVarargs
|
||||
public static <T> BreadCrumbItem<T> buildTreeModel(T... crumbs) {
|
||||
@ -128,7 +140,8 @@ public class Breadcrumbs<T> extends Control {
|
||||
* <p>Consider the following hierarchy:
|
||||
* [Root] > [Folder] > [SubFolder] > [file.txt]
|
||||
*
|
||||
* <p>To show the above bread crumb bar, you have to set the [file.txt] tree-node as selected crumb.
|
||||
* <p>To show the above bread crumb bar, you have to set the [file.txt]
|
||||
* tree-node as selected crumb.
|
||||
*/
|
||||
public final ObjectProperty<BreadCrumbItem<T>> selectedCrumbProperty() {
|
||||
return selectedCrumb;
|
||||
@ -147,10 +160,9 @@ public class Breadcrumbs<T> extends Control {
|
||||
|
||||
/**
|
||||
* Enables or disables auto navigation (default is enabled).
|
||||
* If auto navigation is enabled, it will automatically navigate to the crumb which was
|
||||
* clicked by the user.
|
||||
*
|
||||
* @return a {@link BooleanProperty}
|
||||
* If auto navigation is enabled, it will automatically navigate to the
|
||||
* crumb which was clicked by the user, meaning it will set the
|
||||
* {@link #selectedCrumbProperty()} upon click.
|
||||
*/
|
||||
public final BooleanProperty autoNavigationEnabledProperty() {
|
||||
return autoNavigation;
|
||||
@ -168,14 +180,15 @@ public class Breadcrumbs<T> extends Control {
|
||||
}
|
||||
|
||||
/**
|
||||
* Crumb factory is used to create custom bread crumb instances.
|
||||
* <code>null</code> is not allowed and will result in a fallback to the default factory.
|
||||
* The crumb factory is used to create custom bread crumb instances.
|
||||
* A null value is not allowed and will result in a fallback to the default factory.
|
||||
* <ul>
|
||||
* <li><code>BreadCrumbItem<T></code> specifies the tree item for creating bread crumb.</li>
|
||||
* <li><code>ButtonBase</code> stands for resulting bread crumb node.</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p><code>BreadCrumbItem<T></code> specifies the tree item for creating bread crumb. Use
|
||||
* {@link BreadCrumbItem#isFirst()} and {@link BreadCrumbItem#isLast()} to create bread crumb
|
||||
* depending on item position.
|
||||
*
|
||||
* <p><code>ButtonBase</code> stands for resulting bread crumb node. It CAN NOT be <code>null</code>.
|
||||
* <p>Use {@link BreadCrumbItem#isFirst()} and {@link BreadCrumbItem#isLast()} to
|
||||
* create bread crumb depending on item position.
|
||||
*/
|
||||
public final ObjectProperty<Callback<BreadCrumbItem<T>, ButtonBase>> crumbFactoryProperty() {
|
||||
return crumbFactory;
|
||||
@ -196,16 +209,19 @@ public class Breadcrumbs<T> extends Control {
|
||||
}
|
||||
|
||||
/**
|
||||
* Divider factory is used to create custom divider instances.
|
||||
* <code>null</code> is not allowed and will result in a fallback to the default factory.
|
||||
* The divider factory is used to create custom instances of dividers.
|
||||
* A null value is not allowed and will result in a fallback to the default factory.
|
||||
*
|
||||
* <p><code>BreadCrumbItem<T></code> specifies the preceding tree item. It can be null, because this way
|
||||
* you can insert divider before the first bread crumb, which can be used e.g. for creating a Unix path.
|
||||
* Use {@link BreadCrumbItem#isFirst()} and {@link BreadCrumbItem#isLast()} to create divider
|
||||
* depending on item position.
|
||||
* <ul>
|
||||
* <li><code>BreadCrumbItem<T></code> specifies the preceding tree item.
|
||||
* It can be null, which allows for inserting a divider before the first bread crumb,
|
||||
* such as when creating a Unix path.</li>
|
||||
* <li><code>? extends Node</code> stands for resulting divider node. It can also be null,
|
||||
* indicating that there will be no divider inserted after the specified bread crumb.</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p><code>? extends Node</code> stands for resulting divider node. It CAN be <code>null</code>, which
|
||||
* means there will be no divider inserted after the specified bread crumb.
|
||||
* <p>Use {@link BreadCrumbItem#isFirst()} and {@link BreadCrumbItem#isLast()} to
|
||||
* create bread crumb depending on item position.
|
||||
*/
|
||||
public final ObjectProperty<Callback<BreadCrumbItem<T>, ? extends Node>> dividerFactoryProperty() {
|
||||
return dividerFactory;
|
||||
@ -226,26 +242,15 @@ public class Breadcrumbs<T> extends Control {
|
||||
}
|
||||
|
||||
/**
|
||||
* The EventHandler is called when a user selects a bread crumb.
|
||||
* Represents the EventHandler that is called when a user selects a bread crumb.
|
||||
*/
|
||||
public final ObjectProperty<EventHandler<BreadCrumbActionEvent<T>>> onCrumbActionProperty() {
|
||||
return onCrumbAction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a new EventHandler for when a user selects a crumb.
|
||||
*/
|
||||
public final void setOnCrumbAction(EventHandler<BreadCrumbActionEvent<T>> value) {
|
||||
onCrumbActionProperty().set(value);
|
||||
}
|
||||
|
||||
public final EventHandler<BreadCrumbActionEvent<T>> getOnCrumbAction() {
|
||||
return onCrumbActionProperty().get();
|
||||
}
|
||||
|
||||
protected final ObjectProperty<EventHandler<BreadCrumbActionEvent<T>>> onCrumbAction = new ObjectPropertyBase<>() {
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
@Override
|
||||
protected void invalidated() {
|
||||
setEventHandler(BreadCrumbActionEvent.CRUMB_ACTION, (EventHandler<BreadCrumbActionEvent>) (Object) get());
|
||||
@ -262,48 +267,79 @@ public class Breadcrumbs<T> extends Control {
|
||||
}
|
||||
};
|
||||
|
||||
public final void setOnCrumbAction(EventHandler<BreadCrumbActionEvent<T>> value) {
|
||||
onCrumbActionProperty().set(value);
|
||||
}
|
||||
|
||||
public final EventHandler<BreadCrumbActionEvent<T>> getOnCrumbAction() {
|
||||
return onCrumbActionProperty().get();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* {@code BreadCrumbItem} extends {@link TreeItem}, providing support
|
||||
* for navigating hierarchical structures.
|
||||
*
|
||||
* @param <T> The type of the value property within BreadCrumbItem.
|
||||
*/
|
||||
public static class BreadCrumbItem<T> extends TreeItem<T> {
|
||||
|
||||
// setters must not be exposed to user
|
||||
private boolean first;
|
||||
private boolean last;
|
||||
protected boolean first;
|
||||
protected boolean last;
|
||||
|
||||
public BreadCrumbItem(T value) {
|
||||
/**
|
||||
* Creates a BreadCrumbItem with the value property set to the provided object.
|
||||
*
|
||||
* @param value The object to be stored as the value of this BreadCrumbItem.
|
||||
*/
|
||||
public BreadCrumbItem(@Nullable T value) {
|
||||
super(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this method to determine if this item is at the beginning,
|
||||
* so you can create bread crumbs accordingly.
|
||||
*/
|
||||
public boolean isFirst() {
|
||||
return first;
|
||||
}
|
||||
|
||||
void setFirst(boolean first) {
|
||||
this.first = first;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this method to determine if this item is at the end,
|
||||
* so you can create breadcrumbs accordingly.
|
||||
*/
|
||||
public boolean isLast() {
|
||||
return last;
|
||||
}
|
||||
|
||||
void setLast(boolean last) {
|
||||
///////////////////////////////////////////////////
|
||||
// package private //
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
protected void setFirst(boolean first) {
|
||||
this.first = first;
|
||||
}
|
||||
|
||||
protected void setLast(boolean last) {
|
||||
this.last = last;
|
||||
}
|
||||
|
||||
String getStringValue() {
|
||||
protected String getStringValue() {
|
||||
return getValue() != null ? getValue().toString() : "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an Event which is fired when a bread crumb was activated.
|
||||
* An {@code Event} which is fired when a bread crumb was activated.
|
||||
*/
|
||||
public static class BreadCrumbActionEvent<T> extends Event {
|
||||
|
||||
/**
|
||||
* The event type that should be listened to by people interested in
|
||||
* knowing when the {@link Breadcrumbs#selectedCrumbProperty() selected crumb}
|
||||
* has changed.
|
||||
* Represents the event type that should be listened to by people who are
|
||||
* interested in knowing when the selected crumb has changed. This is accomplished
|
||||
* through listening to the {@link Breadcrumbs#selectedCrumbProperty() selected crumb
|
||||
* property}.
|
||||
*/
|
||||
public static final EventType<BreadCrumbActionEvent<?>> CRUMB_ACTION
|
||||
= new EventType<>("CRUMB_ACTION" + UUID.randomUUID());
|
||||
@ -312,6 +348,8 @@ public class Breadcrumbs<T> extends Control {
|
||||
|
||||
/**
|
||||
* Creates a new event that can subsequently be fired.
|
||||
*
|
||||
* @param selectedCrumb The currently selected crumb.
|
||||
*/
|
||||
public BreadCrumbActionEvent(BreadCrumbItem<T> selectedCrumb) {
|
||||
super(CRUMB_ACTION);
|
||||
|
@ -41,17 +41,23 @@ import javafx.scene.control.ButtonBase;
|
||||
import javafx.scene.control.SkinBase;
|
||||
import javafx.scene.control.TreeItem.TreeModificationEvent;
|
||||
|
||||
/**
|
||||
* The default skin for the {@link Breadcrumbs} control.
|
||||
*/
|
||||
public class BreadcrumbsSkin<T> extends SkinBase<Breadcrumbs<T>> {
|
||||
|
||||
protected static final PseudoClass FIRST = PseudoClass.getPseudoClass("first");
|
||||
protected static final PseudoClass LAST = PseudoClass.getPseudoClass("last");
|
||||
|
||||
protected final EventHandler<TreeModificationEvent<Object>> treeChildrenModifiedHandler = e -> updateBreadCrumbs();
|
||||
protected final EventHandler<TreeModificationEvent<Object>> treeChildrenModifiedHandler =
|
||||
e -> updateBreadCrumbs();
|
||||
|
||||
public BreadcrumbsSkin(final Breadcrumbs<T> control) {
|
||||
super(control);
|
||||
|
||||
control.selectedCrumbProperty().addListener((obs, old, val) -> updateSelectedPath(old, val));
|
||||
control.selectedCrumbProperty().addListener(
|
||||
(obs, old, val) -> updateSelectedPath(old, val)
|
||||
);
|
||||
updateSelectedPath(getSkinnable().selectedCrumbProperty().get(), null);
|
||||
}
|
||||
|
||||
|
@ -51,22 +51,23 @@ import javafx.scene.control.Control;
|
||||
import javafx.scene.control.DateCell;
|
||||
import javafx.scene.control.Skin;
|
||||
import javafx.util.Callback;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* The DatePicker control allows the user to select a date. The calendar is based on either
|
||||
* The Calendar control allows the user to select a date. The calendar is based on either
|
||||
* the standard ISO-8601 chronology or any of the other chronology classes defined in the
|
||||
* java.time.chrono package.
|
||||
* <code>java.time.chrono</code> package.
|
||||
*
|
||||
* <p>The {@link #valueProperty() value} property represents the currently selected
|
||||
* {@link LocalDate}. The default value is null.
|
||||
*
|
||||
* <p>The {@link #chronologyProperty() chronology} property specifies a calendar system to be used
|
||||
* for parsing, displaying, and choosing dates.
|
||||
*
|
||||
* <p>The {@link #valueProperty() value} property is always defined in the ISO calendar system,
|
||||
* <ul>
|
||||
* <li>The {@link #valueProperty() value} property represents the currently selected
|
||||
* {@link LocalDate}. The default value is null.</li>
|
||||
* <li>The {@link #chronologyProperty() chronology} property specifies a calendar system to be used
|
||||
* for parsing, displaying, and choosing dates.</li>
|
||||
* <li>The {@link #valueProperty() value} property is always defined in the ISO calendar system,
|
||||
* however, so applications based on a different chronology may use the conversion methods
|
||||
* provided in the {@link java.time.chrono.Chronology} API to get or set the corresponding
|
||||
* {@link java.time.chrono.ChronoLocalDate} value.
|
||||
* {@link java.time.chrono.ChronoLocalDate} value.</li>
|
||||
* </ul>
|
||||
*/
|
||||
public class Calendar extends Control {
|
||||
|
||||
@ -74,7 +75,8 @@ public class Calendar extends Control {
|
||||
protected Chronology lastValidChronology = IsoChronology.INSTANCE;
|
||||
|
||||
/**
|
||||
* Creates a default DatePicker instance with a <code>null</code> date value set.
|
||||
* Creates a default Calendar instance with a <code>null</code>
|
||||
* date value set.
|
||||
*/
|
||||
public Calendar() {
|
||||
this(null);
|
||||
@ -105,11 +107,12 @@ public class Calendar extends Control {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a DatePicker instance and sets the {@link #valueProperty() value} to the given date.
|
||||
* Creates a Calendar instance and sets the {@link #valueProperty() value}
|
||||
* to the specified date.
|
||||
*
|
||||
* @param localDate to be set as the currently selected date in the DatePicker. Can be null.
|
||||
* @param localDate The date to be set as the currently selected date in the Calendar.
|
||||
*/
|
||||
public Calendar(LocalDate localDate) {
|
||||
public Calendar(@Nullable LocalDate localDate) {
|
||||
setValue(localDate);
|
||||
getStyleClass().add(DEFAULT_STYLE_CLASS);
|
||||
}
|
||||
@ -126,6 +129,13 @@ public class Calendar extends Control {
|
||||
// Properties //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Represents the currently selected {@link LocalDate}. The default value is null.
|
||||
*/
|
||||
public ObjectProperty<LocalDate> valueProperty() {
|
||||
return value;
|
||||
}
|
||||
|
||||
private final ObjectProperty<LocalDate> value = new SimpleObjectProperty<>(this, "value");
|
||||
|
||||
public final LocalDate getValue() {
|
||||
@ -136,10 +146,6 @@ public class Calendar extends Control {
|
||||
valueProperty().set(value);
|
||||
}
|
||||
|
||||
public ObjectProperty<LocalDate> valueProperty() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* A custom cell factory can be provided to customize individual day cells
|
||||
* Refer to {@link DateCell} and {@link Cell} for more information on cell factories.
|
||||
@ -162,8 +168,8 @@ public class Calendar extends Control {
|
||||
}
|
||||
|
||||
/**
|
||||
* The calendar system used for parsing, displaying, and choosing dates in the DatePicker
|
||||
* control.
|
||||
* The calendar system used for parsing, displaying, and choosing dates in the
|
||||
* Calendar control.
|
||||
*
|
||||
* <p>The default is usually {@link IsoChronology} unless provided explicitly
|
||||
* in the {@link Locale} by use of a Locale calendar extension.
|
||||
@ -176,7 +182,8 @@ public class Calendar extends Control {
|
||||
return chronology;
|
||||
}
|
||||
|
||||
private final ObjectProperty<Chronology> chronology = new SimpleObjectProperty<>(this, "chronology", null);
|
||||
private final ObjectProperty<Chronology> chronology
|
||||
= new SimpleObjectProperty<>(this, "chronology", null);
|
||||
|
||||
@SuppressWarnings("CatchAndPrintStackTrace")
|
||||
public final Chronology getChronology() {
|
||||
@ -199,7 +206,7 @@ public class Calendar extends Control {
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the DatePicker popup should display a column showing week numbers.
|
||||
* Whether the Calendar should display a column showing week numbers.
|
||||
*
|
||||
* <p>The default value is specified in a resource bundle, and depends on the country of the
|
||||
* current locale.
|
||||
@ -238,7 +245,15 @@ public class Calendar extends Control {
|
||||
return showWeekNumbersProperty().getValue();
|
||||
}
|
||||
|
||||
private final ObjectProperty<Node> topNode = new SimpleObjectProperty<>(this, "topNode", null);
|
||||
/**
|
||||
* Represents the custom node to be placed at the top of the Calendar above the month-year area.
|
||||
*/
|
||||
public ObjectProperty<Node> topNodeProperty() {
|
||||
return topNode;
|
||||
}
|
||||
|
||||
private final ObjectProperty<Node> topNode
|
||||
= new SimpleObjectProperty<>(this, "topNode", null);
|
||||
|
||||
public final void setTopNode(Node value) {
|
||||
topNode.setValue(value);
|
||||
@ -248,11 +263,15 @@ public class Calendar extends Control {
|
||||
return topNode.getValue();
|
||||
}
|
||||
|
||||
public ObjectProperty<Node> topNodeProperty() {
|
||||
return topNode;
|
||||
/**
|
||||
* Represents the custom node to be placed at the bottom of the Calendar below the day-cell grid.
|
||||
*/
|
||||
public ObjectProperty<Node> bottomNodeProperty() {
|
||||
return bottomNode;
|
||||
}
|
||||
|
||||
private final ObjectProperty<Node> bottomNode = new SimpleObjectProperty<>(this, "bottomNode", null);
|
||||
private final ObjectProperty<Node> bottomNode
|
||||
= new SimpleObjectProperty<>(this, "bottomNode", null);
|
||||
|
||||
public final void setBottomNode(Node value) {
|
||||
bottomNode.setValue(value);
|
||||
@ -262,10 +281,6 @@ public class Calendar extends Control {
|
||||
return bottomNode.getValue();
|
||||
}
|
||||
|
||||
public ObjectProperty<Node> bottomNodeProperty() {
|
||||
return bottomNode;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Stylesheet Handling //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
@ -12,6 +12,9 @@ import java.time.ZoneId;
|
||||
import javafx.scene.input.KeyEvent;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
|
||||
/**
|
||||
* The default behavior for the {@link Calendar} control.
|
||||
*/
|
||||
public class CalendarBehavior extends BehaviorBase<Calendar, CalendarSkin> {
|
||||
|
||||
public CalendarBehavior(Calendar control, CalendarSkin skin) {
|
||||
|
@ -73,6 +73,9 @@ import javafx.scene.layout.StackPane;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.util.Callback;
|
||||
|
||||
/**
|
||||
* The default skin for the {@link Calendar} control.
|
||||
*/
|
||||
public class CalendarSkin extends BehaviorSkinBase<Calendar, CalendarBehavior> {
|
||||
|
||||
// formatters
|
||||
@ -100,7 +103,8 @@ public class CalendarSkin extends BehaviorSkinBase<Calendar, CalendarBehavior> {
|
||||
protected DateCell lastFocusedDayCell = null;
|
||||
protected final int daysPerWeek = getDaysPerWeek();
|
||||
|
||||
private final ObjectProperty<YearMonth> displayedYearMonth = new SimpleObjectProperty<>(this, "displayedYearMonth");
|
||||
private final ObjectProperty<YearMonth> displayedYearMonth
|
||||
= new SimpleObjectProperty<>(this, "displayedYearMonth");
|
||||
|
||||
public ObjectProperty<YearMonth> displayedYearMonthProperty() {
|
||||
return displayedYearMonth;
|
||||
@ -113,27 +117,27 @@ public class CalendarSkin extends BehaviorSkinBase<Calendar, CalendarBehavior> {
|
||||
return firstDayOfMonth.get();
|
||||
}
|
||||
|
||||
public CalendarSkin(Calendar datePicker) {
|
||||
super(datePicker);
|
||||
public CalendarSkin(Calendar control) {
|
||||
super(control);
|
||||
|
||||
createUI();
|
||||
|
||||
registerChangeListener(datePicker.valueProperty(), e -> {
|
||||
LocalDate date = datePicker.getValue();
|
||||
registerChangeListener(control.valueProperty(), e -> {
|
||||
LocalDate date = control.getValue();
|
||||
displayedYearMonthProperty().set(
|
||||
date != null ? YearMonth.from(date) : YearMonth.now(ZoneId.systemDefault())
|
||||
);
|
||||
updateValues();
|
||||
datePicker.fireEvent(new ActionEvent());
|
||||
control.fireEvent(new ActionEvent());
|
||||
});
|
||||
|
||||
registerChangeListener(datePicker.showWeekNumbersProperty(), e -> {
|
||||
registerChangeListener(control.showWeekNumbersProperty(), e -> {
|
||||
updateGrid();
|
||||
updateWeekNumberCells();
|
||||
});
|
||||
|
||||
registerChangeListener(datePicker.topNodeProperty(), e -> {
|
||||
Node node = datePicker.getTopNode();
|
||||
registerChangeListener(control.topNodeProperty(), e -> {
|
||||
Node node = control.getTopNode();
|
||||
if (node == null) {
|
||||
rootPane.getChildren().removeIf(c -> c.getStyleClass().contains("top-node"));
|
||||
} else {
|
||||
@ -144,8 +148,8 @@ public class CalendarSkin extends BehaviorSkinBase<Calendar, CalendarBehavior> {
|
||||
}
|
||||
});
|
||||
|
||||
registerChangeListener(datePicker.bottomNodeProperty(), e -> {
|
||||
Node node = datePicker.getBottomNode();
|
||||
registerChangeListener(control.bottomNodeProperty(), e -> {
|
||||
Node node = control.getBottomNode();
|
||||
if (node == null) {
|
||||
rootPane.getChildren().removeIf(c -> c.getStyleClass().contains("bottom-node"));
|
||||
} else {
|
||||
@ -171,9 +175,7 @@ public class CalendarSkin extends BehaviorSkinBase<Calendar, CalendarBehavior> {
|
||||
}
|
||||
|
||||
/**
|
||||
* The primary chronology for display. This may be overridden to be different from the
|
||||
* DatePicker chronology. For example DatePickerHijrahContent uses ISO as primary and Hijrah
|
||||
* as a secondary chronology.
|
||||
* The primary chronology for display.
|
||||
*/
|
||||
public Chronology getPrimaryChronology() {
|
||||
return getControl().getChronology();
|
||||
|
@ -2,20 +2,31 @@
|
||||
|
||||
package atlantafx.base.controls;
|
||||
|
||||
import javafx.beans.NamedArg;
|
||||
import javafx.beans.property.StringProperty;
|
||||
import javafx.scene.control.CustomMenuItem;
|
||||
import javafx.scene.control.Label;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
/**
|
||||
* A MenuItem that is intended to contain a caption for a group of menu items
|
||||
* that share a common purpose.
|
||||
*/
|
||||
public class CaptionMenuItem extends CustomMenuItem {
|
||||
|
||||
protected final Label title = new Label();
|
||||
|
||||
/**
|
||||
* Creates an empty menu item.
|
||||
*/
|
||||
public CaptionMenuItem() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public CaptionMenuItem(String text) {
|
||||
/**
|
||||
* Creates a CaptionMenuItem with the specified text as the title.
|
||||
*/
|
||||
public CaptionMenuItem(@Nullable @NamedArg("text") String text) {
|
||||
super();
|
||||
|
||||
setTitle(text);
|
||||
@ -24,6 +35,13 @@ public class CaptionMenuItem extends CustomMenuItem {
|
||||
getStyleClass().addAll("caption-menu-item");
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains the title of the menu item.
|
||||
*/
|
||||
public StringProperty titleProperty() {
|
||||
return title.textProperty();
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title.getText();
|
||||
}
|
||||
@ -31,8 +49,4 @@ public class CaptionMenuItem extends CustomMenuItem {
|
||||
public void setTitle(String text) {
|
||||
title.setText(text);
|
||||
}
|
||||
|
||||
public StringProperty titleProperty() {
|
||||
return title.textProperty();
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ import javafx.scene.control.Control;
|
||||
import javafx.scene.control.Skin;
|
||||
|
||||
/**
|
||||
* Aa versatile container that can used in various contexts such as headings,
|
||||
* A versatile container that can be used in various contexts, such as headings,
|
||||
* text, dialogs and more. It includes a header to provide a brief overview
|
||||
* or context of the information. The sub-header and body sections provide
|
||||
* more detailed content, while the footer may include additional actions or
|
||||
@ -17,12 +17,17 @@ import javafx.scene.control.Skin;
|
||||
*/
|
||||
public class Card extends Control {
|
||||
|
||||
// Default constructor
|
||||
/**
|
||||
* Creates an empty Card.
|
||||
*/
|
||||
public Card() {
|
||||
super();
|
||||
getStyleClass().add("card");
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected Skin<?> createDefaultSkin() {
|
||||
return new CardSkin(this);
|
||||
@ -33,69 +38,69 @@ public class Card extends Control {
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* The property representing the card’s header node.
|
||||
* Represents the card’s header node.
|
||||
*/
|
||||
public ObjectProperty<Node> headerProperty() {
|
||||
return header;
|
||||
}
|
||||
|
||||
private final ObjectProperty<Node> header = new SimpleObjectProperty<>(this, "header");
|
||||
|
||||
public Node getHeader() {
|
||||
return header.get();
|
||||
}
|
||||
|
||||
public ObjectProperty<Node> headerProperty() {
|
||||
return header;
|
||||
}
|
||||
|
||||
public void setHeader(Node header) {
|
||||
this.header.set(header);
|
||||
}
|
||||
|
||||
/**
|
||||
* The property representing the card’s sub-header node.
|
||||
* Represents the card’s sub-header node.
|
||||
*/
|
||||
public final ObjectProperty<Node> subHeaderProperty() {
|
||||
return subHeader;
|
||||
}
|
||||
|
||||
private final ObjectProperty<Node> subHeader = new SimpleObjectProperty<>(this, "subHeader");
|
||||
|
||||
public Node getSubHeader() {
|
||||
return subHeader.get();
|
||||
}
|
||||
|
||||
public final ObjectProperty<Node> subHeaderProperty() {
|
||||
return subHeader;
|
||||
}
|
||||
|
||||
public void setSubHeader(Node subHeader) {
|
||||
this.subHeader.set(subHeader);
|
||||
}
|
||||
|
||||
/**
|
||||
* The property representing the card’s body node.
|
||||
* Represents the card’s body node.
|
||||
*/
|
||||
public ObjectProperty<Node> bodyProperty() {
|
||||
return body;
|
||||
}
|
||||
|
||||
private final ObjectProperty<Node> body = new SimpleObjectProperty<>(this, "body");
|
||||
|
||||
public Node getBody() {
|
||||
return body.get();
|
||||
}
|
||||
|
||||
public ObjectProperty<Node> bodyProperty() {
|
||||
return body;
|
||||
}
|
||||
|
||||
public void setBody(Node body) {
|
||||
this.body.set(body);
|
||||
}
|
||||
|
||||
/**
|
||||
* The property representing the card’s footer node.
|
||||
* Represents the card’s footer node.
|
||||
*/
|
||||
public ObjectProperty<Node> footerProperty() {
|
||||
return footer;
|
||||
}
|
||||
|
||||
private final ObjectProperty<Node> footer = new SimpleObjectProperty<>(this, "footer");
|
||||
|
||||
public Node getFooter() {
|
||||
return footer.get();
|
||||
}
|
||||
|
||||
public ObjectProperty<Node> footerProperty() {
|
||||
return footer;
|
||||
}
|
||||
|
||||
public void setFooter(Node footer) {
|
||||
this.footer.set(footer);
|
||||
}
|
||||
|
@ -11,6 +11,9 @@ import javafx.scene.layout.Priority;
|
||||
import javafx.scene.layout.StackPane;
|
||||
import javafx.scene.layout.VBox;
|
||||
|
||||
/**
|
||||
* The default skin for the {@link Card} control.
|
||||
*/
|
||||
public class CardSkin implements Skin<Card> {
|
||||
|
||||
protected static final PseudoClass HAS_HEADER = PseudoClass.getPseudoClass("has-header");
|
||||
|
@ -36,79 +36,29 @@ import javafx.scene.control.Skin;
|
||||
import javafx.scene.control.TextField;
|
||||
|
||||
/**
|
||||
* A base class for people wanting to customize a {@link TextField} to contain nodes
|
||||
* inside the text field itself, without being on top of the users typed-in text.
|
||||
* A base class for people wanting to customize a {@link TextField}
|
||||
* to contain nodes inside the text field itself, without being on top
|
||||
* of the users typed-in text.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class CustomTextField extends TextField {
|
||||
|
||||
/**
|
||||
* Instantiates a default CustomTextField.
|
||||
* Creates an empty CustomTextField.
|
||||
*/
|
||||
public CustomTextField() {
|
||||
getStyleClass().add("custom-text-field");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a CustomTextField with initial text content.
|
||||
*
|
||||
* @param text A string for text content.
|
||||
*/
|
||||
public CustomTextField(String text) {
|
||||
this();
|
||||
setText(text);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Properties //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private final ObjectProperty<Node> left = new SimpleObjectProperty<>(this, "left");
|
||||
|
||||
/**
|
||||
* Returns an ObjectProperty wrapping the {@link Node} that is placed
|
||||
* on the left of the text field.
|
||||
*/
|
||||
public final ObjectProperty<Node> leftProperty() {
|
||||
return left;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link Node} that is placed on the left of the text field.
|
||||
*/
|
||||
public final Node getLeft() {
|
||||
return left.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link Node} that is placed on the left of the text field.
|
||||
*/
|
||||
public final void setLeft(Node value) {
|
||||
left.set(value);
|
||||
}
|
||||
|
||||
private final ObjectProperty<Node> right = new SimpleObjectProperty<>(this, "right");
|
||||
|
||||
/**
|
||||
* Property representing the {@link Node} that is placed on the right of the text field.
|
||||
*/
|
||||
public final ObjectProperty<Node> rightProperty() {
|
||||
return right;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link Node} that is placed on the right of the text field.
|
||||
*/
|
||||
public final Node getRight() {
|
||||
return right.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link Node} that is placed on the right of the text field.
|
||||
*/
|
||||
public final void setRight(Node value) {
|
||||
right.set(value);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Methods //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@ -126,4 +76,54 @@ public class CustomTextField extends TextField {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Properties //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Represents the {@link Node} that is placed on the left of the text field.
|
||||
*/
|
||||
public final ObjectProperty<Node> leftProperty() {
|
||||
return left;
|
||||
}
|
||||
|
||||
private final ObjectProperty<Node> left = new SimpleObjectProperty<>(this, "left");
|
||||
|
||||
/**
|
||||
* Returns the {@link Node} that is placed on the left of the text field.
|
||||
*/
|
||||
public final Node getLeft() {
|
||||
return left.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link Node} that is placed on the left of the text field.
|
||||
*/
|
||||
public final void setLeft(Node value) {
|
||||
left.set(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the {@link Node} that is placed on the right of the text field.
|
||||
*/
|
||||
public final ObjectProperty<Node> rightProperty() {
|
||||
return right;
|
||||
}
|
||||
|
||||
private final ObjectProperty<Node> right = new SimpleObjectProperty<>(this, "right");
|
||||
|
||||
/**
|
||||
* Returns the {@link Node} that is placed on the right of the text field.
|
||||
*/
|
||||
public final Node getRight() {
|
||||
return right.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link Node} that is placed on the right of the text field.
|
||||
*/
|
||||
public final void setRight(Node value) {
|
||||
right.set(value);
|
||||
}
|
||||
}
|
||||
|
@ -38,6 +38,9 @@ import javafx.scene.control.skin.TextFieldSkin;
|
||||
import javafx.scene.layout.StackPane;
|
||||
import javafx.scene.text.HitInfo;
|
||||
|
||||
/**
|
||||
* The default skin for the {@link CustomTextField} control.
|
||||
*/
|
||||
public abstract class CustomTextFieldSkin extends TextFieldSkin {
|
||||
|
||||
private static final PseudoClass HAS_NO_SIDE_NODE = PseudoClass.getPseudoClass("no-side-nodes");
|
||||
|
@ -29,6 +29,7 @@ package atlantafx.base.controls;
|
||||
|
||||
import atlantafx.base.util.MaskChar;
|
||||
import atlantafx.base.util.MaskTextFormatter;
|
||||
import atlantafx.base.util.SimpleMaskChar;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import javafx.beans.NamedArg;
|
||||
@ -38,9 +39,9 @@ import javafx.beans.property.StringProperty;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* This is a convenience wrapper for instantiating a {@link CustomTextField} with a
|
||||
* {@code MaskTextFormatter}. For additional info refer to the {@link MaskTextFormatter}
|
||||
* docs.
|
||||
* A convenience wrapper for instantiating a {@link CustomTextField} with a
|
||||
* {@code MaskTextFormatter}. For additional info refer to the
|
||||
* {@link MaskTextFormatter} documentation.
|
||||
*/
|
||||
public class MaskTextField extends CustomTextField {
|
||||
|
||||
@ -56,15 +57,35 @@ public class MaskTextField extends CustomTextField {
|
||||
protected final ReadOnlyObjectWrapper<MaskTextFormatter> formatter =
|
||||
new ReadOnlyObjectWrapper<>(this, "formatter");
|
||||
|
||||
/**
|
||||
* Creates an empty MaskTextField.
|
||||
*/
|
||||
public MaskTextField() {
|
||||
super("");
|
||||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an empty MaskTextField with the specified input mask.
|
||||
*
|
||||
* <p>The input mask is specified as a string that must follow the
|
||||
* rules described in the {@link MaskTextFormatter} documentation.
|
||||
*
|
||||
* @param mask The input mask.
|
||||
*/
|
||||
public MaskTextField(@NamedArg("mask") String mask) {
|
||||
this("", mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a MaskTextField with initial text content and the specified input mask.
|
||||
*
|
||||
* <p>The input mask is specified as a string that must follow the
|
||||
* rules described in the {@link MaskTextFormatter} documentation.
|
||||
*
|
||||
* @param text A string for text content.
|
||||
* @param mask An input mask.
|
||||
*/
|
||||
private MaskTextField(@NamedArg("text") String text,
|
||||
@NamedArg("mask") String mask) {
|
||||
super(Objects.requireNonNullElse(text, ""));
|
||||
@ -74,6 +95,15 @@ public class MaskTextField extends CustomTextField {
|
||||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a MaskTextField with initial text content and the specified input mask.
|
||||
*
|
||||
* <p>The input mask is specified as a list of {@code MaskChar}. You can use
|
||||
* the {@link SimpleMaskChar} as the default implementation.
|
||||
*
|
||||
* @param text A string for text content.
|
||||
* @param mask An input mask.
|
||||
*/
|
||||
public MaskTextField(String text, List<MaskChar> mask) {
|
||||
super(Objects.requireNonNullElse(text, ""));
|
||||
|
||||
@ -90,6 +120,18 @@ public class MaskTextField extends CustomTextField {
|
||||
});
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Properties //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Represents the input mask.
|
||||
*
|
||||
* <p>Note that the MaskTextField allows for specifying the input mask as either a string
|
||||
* or a list of {@code MaskChar}. These formats cannot be converted to one another. Therefore,
|
||||
* if the input mask was specified as a list of {@code MaskChar}, this property will return
|
||||
* null value.
|
||||
*/
|
||||
public StringProperty maskProperty() {
|
||||
return mask;
|
||||
}
|
||||
|
@ -12,21 +12,24 @@ import javafx.scene.control.Skin;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* The Message is a component for displaying notifications or alerts
|
||||
* and is specifically designed to grab the user’s attention.
|
||||
* It is based on the Tile layout and shares its structure.
|
||||
* A control for displaying banners or alerts that is specifically
|
||||
* designed to grab the user’s attention. It is based on the {@link Tile}
|
||||
* layout and shares its structure.
|
||||
*/
|
||||
public class Message extends TileBase {
|
||||
|
||||
/**
|
||||
* See {@link Tile#Tile()}.
|
||||
* Creates an empty Message.
|
||||
*/
|
||||
public Message() {
|
||||
this(null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link Tile#Tile(String, String)}.
|
||||
* Creates a new Message with an initial title and description.
|
||||
*
|
||||
* @param title A string for the title.
|
||||
* @param description A string for the description.
|
||||
*/
|
||||
public Message(@Nullable @NamedArg("title") String title,
|
||||
@Nullable @NamedArg("description") String description) {
|
||||
@ -34,7 +37,11 @@ public class Message extends TileBase {
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link Tile#Tile(String, String, Node)}.
|
||||
* Creates a new Message with an initial title, description and graphic.
|
||||
*
|
||||
* @param title A string for the title.
|
||||
* @param description A string for the description.
|
||||
* @param graphic A graphic or icon.
|
||||
*/
|
||||
public Message(@Nullable String title,
|
||||
@Nullable String description,
|
||||
@ -43,6 +50,9 @@ public class Message extends TileBase {
|
||||
getStyleClass().add("message");
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected Skin<?> createDefaultSkin() {
|
||||
return new MessageSkin(this);
|
||||
@ -53,27 +63,33 @@ public class Message extends TileBase {
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* The property representing the message’s action handler. Setting an action handler
|
||||
* makes the message interactive or clickable. When a user clicks on the interactive
|
||||
* Represents the message’s action handler. Setting an action handler makes the
|
||||
* message interactive (or clickable). When a user clicks on the interactive
|
||||
* message, the specified action handler will be called.
|
||||
*/
|
||||
public ObjectProperty<Runnable> actionHandlerProperty() {
|
||||
return actionHandler;
|
||||
}
|
||||
|
||||
private final ObjectProperty<Runnable> actionHandler = new SimpleObjectProperty<>(this, "actionHandler");
|
||||
|
||||
public Runnable getActionHandler() {
|
||||
return actionHandler.get();
|
||||
}
|
||||
|
||||
public ObjectProperty<Runnable> actionHandlerProperty() {
|
||||
return actionHandler;
|
||||
}
|
||||
|
||||
public void setActionHandler(Runnable actionHandler) {
|
||||
this.actionHandler.set(actionHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* The property representing the user specified close handler.
|
||||
* Represents the user-specified close handler, which is intended to be used to close
|
||||
* or dismiss the message. When a user clicks on the message's close button, the specified
|
||||
* close handler will be called.
|
||||
*/
|
||||
public ObjectProperty<EventHandler<? super Event>> onCloseProperty() {
|
||||
return onClose;
|
||||
}
|
||||
|
||||
protected final ObjectProperty<EventHandler<? super Event>> onClose =
|
||||
new SimpleObjectProperty<>(this, "onClose");
|
||||
|
||||
@ -81,10 +97,6 @@ public class Message extends TileBase {
|
||||
return onClose.get();
|
||||
}
|
||||
|
||||
public ObjectProperty<EventHandler<? super Event>> onCloseProperty() {
|
||||
return onClose;
|
||||
}
|
||||
|
||||
public void setOnClose(EventHandler<? super Event> onClose) {
|
||||
this.onClose.set(onClose);
|
||||
}
|
||||
|
@ -9,6 +9,9 @@ import javafx.geometry.HPos;
|
||||
import javafx.geometry.VPos;
|
||||
import javafx.scene.layout.StackPane;
|
||||
|
||||
/**
|
||||
* The default skin for the {@link Message} control.
|
||||
*/
|
||||
public class MessageSkin extends TileSkinBase<Message> {
|
||||
|
||||
protected static final PseudoClass CLOSEABLE = PseudoClass.getPseudoClass("closeable");
|
||||
|
@ -16,53 +16,93 @@ import javafx.geometry.Side;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.Control;
|
||||
import javafx.scene.control.Skin;
|
||||
import javafx.stage.Stage;
|
||||
import javafx.util.Duration;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* A container for displaying application dialogs ot top of the current scene
|
||||
* without opening a modal {@link javafx.stage.Stage}. It's a translucent (glass) pane
|
||||
* that can hold arbitrary content as well as animate its appearance.<br/><br/>
|
||||
* without opening a modal {@link Stage}. It's a translucent (glass) pane
|
||||
* that can hold arbitrary content as well as animate its appearance.
|
||||
*
|
||||
* <p>When {@link #displayProperty()} value is changed the modal pane modifies own
|
||||
* {@link #viewOrderProperty()} value accordingly, thus moving itself on top of the
|
||||
* parent container or vise versa. You can change the target view order value via the
|
||||
* constructor param. This also means that one must not change modal pane {@link #viewOrderProperty()}
|
||||
* property manually.
|
||||
* constructor param. This also means that one <b>must not</b> change the modal pane
|
||||
* {@link #viewOrderProperty()} property manually.
|
||||
*
|
||||
* <p>Example:
|
||||
*
|
||||
* <pre>{@code
|
||||
* ModalPane modalPane = new ModalPane();
|
||||
*
|
||||
* Label content = new Label("Content");
|
||||
* content.setSize(450, 450);
|
||||
*
|
||||
* Button openBtn = new Button("Open");
|
||||
* openBtn.setOnAction(evt -> modalPane.show(content));
|
||||
* }</pre>
|
||||
*/
|
||||
public class ModalPane extends Control {
|
||||
|
||||
protected static final int Z_FRONT = -10;
|
||||
protected static final int Z_BACK = 10;
|
||||
/**
|
||||
* The default value that is set to the modal pane
|
||||
* when it must be on top of other nodes.
|
||||
*/
|
||||
public static final int Z_FRONT = -10;
|
||||
|
||||
/**
|
||||
* The default value that is set to the modal pane
|
||||
* when it must be below of other nodes.
|
||||
*/
|
||||
public static final int Z_BACK = 10;
|
||||
|
||||
/**
|
||||
* The default animation duration that is applied to the modal content
|
||||
* when it enters the user view.
|
||||
*/
|
||||
public static final Duration DEFAULT_DURATION_IN = Duration.millis(200);
|
||||
|
||||
/**
|
||||
* The default animation duration that is applied to the modal content
|
||||
* when it leaves the user view.
|
||||
*/
|
||||
public static final Duration DEFAULT_DURATION_OUT = Duration.millis(100);
|
||||
|
||||
private final int topViewOrder;
|
||||
|
||||
/**
|
||||
* See {@link #ModalPane(int)}.
|
||||
* Creates a new modal pane with the default {@code topViewOrder}
|
||||
* property value.
|
||||
*/
|
||||
public ModalPane() {
|
||||
this(Z_FRONT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new modal pane.
|
||||
* Creates a new modal pane with the specified {@code topViewOrder} property.
|
||||
*
|
||||
* @param topViewOrder the {@link #viewOrderProperty()} value to be set
|
||||
* to display the modal pane on top of the parent container.
|
||||
* @param topViewOrder The {@link #viewOrderProperty()} value to be set in order
|
||||
* to display the ModalPane on top of the parent container.
|
||||
*/
|
||||
public ModalPane(@NamedArg("topViewOrder") int topViewOrder) {
|
||||
super();
|
||||
this.topViewOrder = topViewOrder;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected Skin<?> createDefaultSkin() {
|
||||
return new ModalPaneSkin(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of {@link #viewOrderProperty()} to be set in order to display
|
||||
* the ModalPane on top of its parent container. This is a constructor parameter
|
||||
* that cannot be changed after the ModalPane has been instantiated.
|
||||
*/
|
||||
public int getTopViewOrder() {
|
||||
return topViewOrder;
|
||||
}
|
||||
@ -71,6 +111,13 @@ public class ModalPane extends Control {
|
||||
// Properties //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Specifies the content node to display inside the modal pane.
|
||||
*/
|
||||
public ObjectProperty<Node> contentProperty() {
|
||||
return content;
|
||||
}
|
||||
|
||||
protected final ObjectProperty<Node> content = new SimpleObjectProperty<>(this, "content", null);
|
||||
|
||||
public Node getContent() {
|
||||
@ -82,14 +129,14 @@ public class ModalPane extends Control {
|
||||
}
|
||||
|
||||
/**
|
||||
* The content node to display inside the modal pane.
|
||||
* Indicates whether the modal pane is set to be on top or not.
|
||||
* When changed, the {@link #viewOrderProperty()} value will be modified accordingly.
|
||||
* See the {@link #getTopViewOrder()}.
|
||||
*/
|
||||
public ObjectProperty<Node> contentProperty() {
|
||||
return content;
|
||||
public BooleanProperty displayProperty() {
|
||||
return display;
|
||||
}
|
||||
|
||||
// ~
|
||||
|
||||
protected final BooleanProperty display = new SimpleBooleanProperty(this, "display", false);
|
||||
|
||||
public boolean isDisplay() {
|
||||
@ -101,15 +148,12 @@ public class ModalPane extends Control {
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the modal pane is set to top or not.
|
||||
* When changed the pane {@link #viewOrderProperty()} value will be modified accordingly.
|
||||
* Specifies the alignment of the content node.
|
||||
*/
|
||||
public BooleanProperty displayProperty() {
|
||||
return display;
|
||||
public ObjectProperty<Pos> alignmentProperty() {
|
||||
return alignment;
|
||||
}
|
||||
|
||||
// ~
|
||||
|
||||
protected final ObjectProperty<Pos> alignment = new SimpleObjectProperty<>(this, "alignment", Pos.CENTER);
|
||||
|
||||
public Pos getAlignment() {
|
||||
@ -121,14 +165,13 @@ public class ModalPane extends Control {
|
||||
}
|
||||
|
||||
/**
|
||||
* Content alignment.
|
||||
* The factory that provides a transition to be played on content appearance,
|
||||
* i.e. when {@link #displayProperty()} is set to 'true'.
|
||||
*/
|
||||
public ObjectProperty<Pos> alignmentProperty() {
|
||||
return alignment;
|
||||
public ObjectProperty<Function<Node, Animation>> inTransitionFactoryProperty() {
|
||||
return inTransitionFactory;
|
||||
}
|
||||
|
||||
// ~
|
||||
|
||||
protected final ObjectProperty<Function<Node, Animation>> inTransitionFactory = new SimpleObjectProperty<>(
|
||||
this, "inTransitionFactory", node -> Animations.zoomIn(node, DEFAULT_DURATION_IN)
|
||||
);
|
||||
@ -142,15 +185,13 @@ public class ModalPane extends Control {
|
||||
}
|
||||
|
||||
/**
|
||||
* The factory that provides a transition to be played on content appearance,
|
||||
* i.e. when {@link #displayProperty()} is set to 'true'.
|
||||
* The factory that provides a transition to be played on content disappearance,
|
||||
* i.e. when {@link #displayProperty()} is set to 'false'.
|
||||
*/
|
||||
public ObjectProperty<Function<Node, Animation>> inTransitionFactoryProperty() {
|
||||
return inTransitionFactory;
|
||||
public ObjectProperty<Function<Node, Animation>> outTransitionFactoryProperty() {
|
||||
return outTransitionFactory;
|
||||
}
|
||||
|
||||
// ~
|
||||
|
||||
protected final ObjectProperty<Function<Node, Animation>> outTransitionFactory = new SimpleObjectProperty<>(
|
||||
this, "outTransitionFactory", node -> Animations.zoomOut(node, DEFAULT_DURATION_OUT)
|
||||
);
|
||||
@ -164,15 +205,16 @@ public class ModalPane extends Control {
|
||||
}
|
||||
|
||||
/**
|
||||
* The factory that provides a transition to be played on content disappearance,
|
||||
* i.e. when {@link #displayProperty()} is set to 'false'.
|
||||
* Specifies whether the content should be treated as persistent or not.
|
||||
*
|
||||
* <p>By default, the modal pane exits when the ESC button is pressed or when
|
||||
* the mouse is clicked outside the content area. This property prevents
|
||||
* this behavior and plays a bouncing animation instead.
|
||||
*/
|
||||
public ObjectProperty<Function<Node, Animation>> outTransitionFactoryProperty() {
|
||||
return outTransitionFactory;
|
||||
public BooleanProperty persistentProperty() {
|
||||
return persistent;
|
||||
}
|
||||
|
||||
// ~
|
||||
|
||||
protected final BooleanProperty persistent = new SimpleBooleanProperty(this, "persistent", false);
|
||||
|
||||
public boolean getPersistent() {
|
||||
@ -183,23 +225,13 @@ public class ModalPane extends Control {
|
||||
this.persistent.set(persistent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies whether content should be treated as persistent or not.
|
||||
* By default, the modal pane exits when the ESC button is pressed or when
|
||||
* the mouse is clicked outside the content area. This property prevents
|
||||
* this behavior and plays bouncing animation instead.
|
||||
*/
|
||||
public BooleanProperty persistentProperty() {
|
||||
return persistent;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Public API //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* A convenience method for setting the content of the modal pane content
|
||||
* and triggering display state at the same time.
|
||||
* and triggering its display state at the same time.
|
||||
*/
|
||||
public void show(Node node) {
|
||||
// calling show method with no content specified doesn't make any sense
|
||||
@ -208,6 +240,17 @@ public class ModalPane extends Control {
|
||||
setDisplay(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* A convenience method for clearing the content of the modal pane content
|
||||
* and triggering its display state at the same time.
|
||||
*/
|
||||
public void hide(boolean clear) {
|
||||
setDisplay(false);
|
||||
if (clear) {
|
||||
setContent(null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link #hide(boolean)}.
|
||||
*/
|
||||
@ -216,24 +259,16 @@ public class ModalPane extends Control {
|
||||
}
|
||||
|
||||
/**
|
||||
* A convenience method for clearing the content of the modal pane content
|
||||
* and triggering display state at the same time.
|
||||
* See {@link #usePredefinedTransitionFactories(Side, Duration, Duration)}.
|
||||
*/
|
||||
public void hide(boolean clear) {
|
||||
setDisplay(false);
|
||||
if (clear) {
|
||||
setContent(null);
|
||||
}
|
||||
public void usePredefinedTransitionFactories(@Nullable Side side) {
|
||||
usePredefinedTransitionFactories(side, DEFAULT_DURATION_IN, DEFAULT_DURATION_OUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the predefined factory for both {@link #inTransitionFactoryProperty()} and
|
||||
* {@link #outTransitionFactoryProperty()} based on content position.
|
||||
*/
|
||||
public void usePredefinedTransitionFactories(@Nullable Side side) {
|
||||
usePredefinedTransitionFactories(side, DEFAULT_DURATION_IN, DEFAULT_DURATION_OUT);
|
||||
}
|
||||
|
||||
public void usePredefinedTransitionFactories(@Nullable Side side,
|
||||
@Nullable Duration inDuration,
|
||||
@Nullable Duration outDuration) {
|
||||
|
@ -22,6 +22,9 @@ import javafx.scene.layout.StackPane;
|
||||
import javafx.util.Duration;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* The default skin for the {@link ModalPane} control.
|
||||
*/
|
||||
public class ModalPaneSkin extends SkinBase<ModalPane> {
|
||||
|
||||
protected ModalPane control;
|
||||
|
@ -15,6 +15,7 @@ import javafx.event.Event;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.ButtonBar;
|
||||
import javafx.scene.control.Control;
|
||||
import javafx.scene.control.MenuItem;
|
||||
import javafx.scene.control.Skin;
|
||||
@ -22,23 +23,34 @@ import javafx.scene.layout.Region;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* The Notification control is intended for displaying alerts and messages
|
||||
* to users as pop-ups. It's customizable with different colors and icons,
|
||||
* can contain a graphic or image, along with the message and additional actions
|
||||
* for users to take. The purpose of this control is to immediately notify users
|
||||
* of significant events and provide them with quick access to related actions without
|
||||
* interrupting their workflow.
|
||||
* A control that is intended for displaying notifications to users as pop-ups.
|
||||
* It is customizable with different colors and icons, can contain a graphic or image,
|
||||
* along with the message and additional actions for users to take.
|
||||
*/
|
||||
public class Notification extends Control {
|
||||
|
||||
/**
|
||||
* Creates an empty Notification.
|
||||
*/
|
||||
public Notification() {
|
||||
this(null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Notification with initial message text.
|
||||
*
|
||||
* @param message A string for the notification message.
|
||||
*/
|
||||
public Notification(@Nullable @NamedArg("message") String message) {
|
||||
this(message, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Notification with initial message text and graphic.
|
||||
*
|
||||
* @param message A string for the notification message.
|
||||
* @param graphic A graphic or icon.
|
||||
*/
|
||||
public Notification(@Nullable @NamedArg("message") String message,
|
||||
@Nullable @NamedArg("graphic") Node graphic) {
|
||||
super();
|
||||
@ -66,16 +78,16 @@ public class Notification extends Control {
|
||||
* Represents an optional graphical component that can be displayed alongside
|
||||
* the notification message.
|
||||
*/
|
||||
public ObjectProperty<Node> graphicProperty() {
|
||||
return graphic;
|
||||
}
|
||||
|
||||
private final ObjectProperty<Node> graphic = new SimpleObjectProperty<>(this, "graphic");
|
||||
|
||||
public Node getGraphic() {
|
||||
return graphic.get();
|
||||
}
|
||||
|
||||
public ObjectProperty<Node> graphicProperty() {
|
||||
return graphic;
|
||||
}
|
||||
|
||||
public void setGraphic(Node graphic) {
|
||||
this.graphic.set(graphic);
|
||||
}
|
||||
@ -84,16 +96,16 @@ public class Notification extends Control {
|
||||
* Stores a short text message that will be displayed to users when the
|
||||
* notification appears. This property doesn't support the formatted text.
|
||||
*/
|
||||
public StringProperty messageProperty() {
|
||||
return message;
|
||||
}
|
||||
|
||||
private final StringProperty message = new SimpleStringProperty(this, "message");
|
||||
|
||||
public String getMessage() {
|
||||
return message.get();
|
||||
}
|
||||
|
||||
public StringProperty messageProperty() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message.set(message);
|
||||
}
|
||||
@ -102,8 +114,14 @@ public class Notification extends Control {
|
||||
* Specifies the primary actions associated with this notification.
|
||||
*
|
||||
* <p>This property is used to store one or more action buttons that will
|
||||
* be displayed at the bottom of the notification when it appears.
|
||||
* be displayed at the bottom of the notification when it appears. These
|
||||
* buttons will be placed inside the {@link ButtonBar} and use the alignment
|
||||
* that is described in the ButtonBar documentation.
|
||||
*/
|
||||
public ReadOnlyObjectProperty<ObservableList<Button>> primaryActionsProperty() {
|
||||
return primaryActions.getReadOnlyProperty();
|
||||
}
|
||||
|
||||
private final ReadOnlyObjectWrapper<ObservableList<Button>> primaryActions =
|
||||
new ReadOnlyObjectWrapper<>(this, "primaryActions", FXCollections.observableArrayList());
|
||||
|
||||
@ -111,10 +129,6 @@ public class Notification extends Control {
|
||||
return primaryActions.get();
|
||||
}
|
||||
|
||||
public ReadOnlyObjectProperty<ObservableList<Button>> primaryActionsProperty() {
|
||||
return primaryActions.getReadOnlyProperty();
|
||||
}
|
||||
|
||||
public void setPrimaryActions(ObservableList<Button> buttons) {
|
||||
this.primaryActions.set(buttons);
|
||||
}
|
||||
@ -128,7 +142,13 @@ public class Notification extends Control {
|
||||
*
|
||||
* <p>This property is used to store one or more menu items that will be displayed
|
||||
* as a dropdown menu at the top corner of the notification when it appears.
|
||||
*
|
||||
* <p>The dropdown menu button will not appear if the list is empty.
|
||||
*/
|
||||
public ReadOnlyObjectProperty<ObservableList<MenuItem>> secondaryActionsProperty() {
|
||||
return secondaryActions.getReadOnlyProperty();
|
||||
}
|
||||
|
||||
private final ReadOnlyObjectWrapper<ObservableList<MenuItem>> secondaryActions =
|
||||
new ReadOnlyObjectWrapper<>(this, "secondaryActions", FXCollections.observableArrayList());
|
||||
|
||||
@ -136,10 +156,6 @@ public class Notification extends Control {
|
||||
return secondaryActions.get();
|
||||
}
|
||||
|
||||
public ReadOnlyObjectProperty<ObservableList<MenuItem>> secondaryActionsProperty() {
|
||||
return secondaryActions.getReadOnlyProperty();
|
||||
}
|
||||
|
||||
public void setSecondaryActions(ObservableList<MenuItem> items) {
|
||||
this.secondaryActions.set(items);
|
||||
}
|
||||
@ -150,7 +166,13 @@ public class Notification extends Control {
|
||||
|
||||
/**
|
||||
* Specifies the close handler used to dismiss this notification.
|
||||
*
|
||||
* <p>The close button will not appear if the handler is not set for it.
|
||||
*/
|
||||
public ObjectProperty<EventHandler<? super Event>> onCloseProperty() {
|
||||
return onClose;
|
||||
}
|
||||
|
||||
protected final ObjectProperty<EventHandler<? super Event>> onClose =
|
||||
new SimpleObjectProperty<>(this, "onClose");
|
||||
|
||||
@ -158,10 +180,6 @@ public class Notification extends Control {
|
||||
return onClose.get();
|
||||
}
|
||||
|
||||
public ObjectProperty<EventHandler<? super Event>> onCloseProperty() {
|
||||
return onClose;
|
||||
}
|
||||
|
||||
public void setOnClose(EventHandler<? super Event> onClose) {
|
||||
this.onClose.set(onClose);
|
||||
}
|
||||
|
@ -19,6 +19,9 @@ import javafx.scene.layout.VBox;
|
||||
import javafx.scene.text.Text;
|
||||
import javafx.scene.text.TextFlow;
|
||||
|
||||
/**
|
||||
* The default skin for the {@link Notification} control.
|
||||
*/
|
||||
public class NotificationSkin extends SkinBase<Notification> {
|
||||
|
||||
protected final VBox container = new VBox();
|
||||
|
@ -34,29 +34,47 @@ import javafx.beans.property.ReadOnlyObjectWrapper;
|
||||
import javafx.beans.property.ReadOnlyStringProperty;
|
||||
|
||||
/**
|
||||
* This is a convenience wrapper for instantiating a {@link CustomTextField}
|
||||
* with {@code PasswordTextFormatter}. For additional info refer to the
|
||||
* {@link PasswordTextFormatter} docs.
|
||||
* A convenience wrapper for instantiating a {@link CustomTextField}
|
||||
* with a {@code PasswordTextFormatter}. For additional info refer to the
|
||||
* {@link PasswordTextFormatter} documentation.
|
||||
*/
|
||||
public class PasswordTextField extends CustomTextField {
|
||||
|
||||
protected final ReadOnlyObjectWrapper<PasswordTextFormatter> formatter
|
||||
= new ReadOnlyObjectWrapper<>(this, "formatter");
|
||||
|
||||
/**
|
||||
* Creates an empty PasswordTextField.
|
||||
*/
|
||||
public PasswordTextField() {
|
||||
this("", PasswordTextFormatter.BULLET);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a PasswordTextField with initial text content.
|
||||
*
|
||||
* @param text A string for text content.
|
||||
*/
|
||||
public PasswordTextField(@NamedArg("text") String text) {
|
||||
this(text, PasswordTextFormatter.BULLET);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a PasswordTextField with initial text content and bullet character.
|
||||
*
|
||||
* @param text A string for text content.
|
||||
* @param bullet A bullet character to mask the password string.
|
||||
*/
|
||||
protected PasswordTextField(@NamedArg("text") String text,
|
||||
@NamedArg("bullet") char bullet) {
|
||||
super(text);
|
||||
formatter.set(PasswordTextFormatter.create(this, bullet));
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Properties //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* See {@link PasswordTextFormatter#passwordProperty()}.
|
||||
*/
|
||||
|
@ -62,29 +62,38 @@ import javafx.stage.WindowEvent;
|
||||
import javafx.util.Duration;
|
||||
|
||||
/**
|
||||
* The Popover control provides detailed information about an owning node in a
|
||||
* popup window. The popup window has a very lightweight appearance (no default
|
||||
* window decorations) and an arrow pointing at the owner. Due to the nature of
|
||||
* popup windows the Popover will move around with the parent window when the
|
||||
* user drags it.
|
||||
* A control that is intended to provide detailed information about
|
||||
* an owning node in a popup window. The popup window has a lightweight
|
||||
* appearance (no default window decorations) and an arrow pointing at the owner.
|
||||
* Due to the nature of popup windows the Popover will move around with the parent
|
||||
* window when the user drags it.
|
||||
*
|
||||
* <p>The Popover can be detached from the owning node by dragging it away from the
|
||||
* owner. It stops displaying an arrow and starts displaying a title and a close
|
||||
* icon.
|
||||
*
|
||||
* <p>Example
|
||||
*
|
||||
* <pre>{@code
|
||||
* var textFlow = new TextFlow(new Text("Some content"));
|
||||
* textFlow.setPrefWidth(300);
|
||||
*
|
||||
* var popover = new Popover(textFlow);
|
||||
* popover.setTitle("Title");
|
||||
*
|
||||
* var ownerLink = new Hyperlink("Show popover");
|
||||
* ownerLink.setOnAction(e -> popover.show(ownerLink));
|
||||
* }</pre>
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class Popover extends PopupControl {
|
||||
|
||||
private static final String DEFAULT_STYLE_CLASS = "popover";
|
||||
private static final Duration DEFAULT_FADE_DURATION = Duration.seconds(.2);
|
||||
|
||||
private final StackPane root = new StackPane();
|
||||
private double targetX;
|
||||
private double targetY;
|
||||
|
||||
private final SimpleBooleanProperty animated = new SimpleBooleanProperty(true);
|
||||
private final ObjectProperty<Duration> fadeInDuration = new SimpleObjectProperty<>(DEFAULT_FADE_DURATION);
|
||||
private final ObjectProperty<Duration> fadeOutDuration = new SimpleObjectProperty<>(DEFAULT_FADE_DURATION);
|
||||
|
||||
/**
|
||||
* Creates a popover with a label as the content node.
|
||||
*/
|
||||
@ -96,7 +105,7 @@ public class Popover extends PopupControl {
|
||||
setAnchorLocation(AnchorLocation.WINDOW_TOP_LEFT);
|
||||
setOnHiding(evt -> setDetached(false));
|
||||
|
||||
/* Create some initial content */
|
||||
// create some initial content
|
||||
Label label = new Label("No Content");
|
||||
label.setPrefSize(200, 200);
|
||||
label.setPadding(new Insets(4));
|
||||
@ -124,31 +133,31 @@ public class Popover extends PopupControl {
|
||||
/**
|
||||
* Creates a popover with the given node as the content node.
|
||||
*
|
||||
* @param content The content shown by the popover
|
||||
* @param content The content shown by the popover.
|
||||
*/
|
||||
public Popover(Node content) {
|
||||
this();
|
||||
|
||||
setContentNode(content);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected Skin<?> createDefaultSkin() {
|
||||
return new PopoverSkin(this);
|
||||
}
|
||||
|
||||
private final StackPane root = new StackPane();
|
||||
|
||||
/**
|
||||
* The root pane stores the content node of the popover. It is accessible
|
||||
* via this method in order to support proper styling.
|
||||
*
|
||||
* <p>Example:
|
||||
*
|
||||
* <pre>
|
||||
* <pre>{@code
|
||||
* Popover popOver = new Popover();
|
||||
* popOver.getRoot().getStylesheets().add(...);
|
||||
* </pre>
|
||||
* }</pre>
|
||||
*
|
||||
* @return the root pane
|
||||
*/
|
||||
@ -156,44 +165,9 @@ public class Popover extends PopupControl {
|
||||
return root;
|
||||
}
|
||||
|
||||
private final ObjectProperty<Node> contentNode = new SimpleObjectProperty<>(this, "contentNode") {
|
||||
@Override
|
||||
public void setValue(Node node) {
|
||||
if (node == null) {
|
||||
throw new NullPointerException("Node cannot be null!");
|
||||
}
|
||||
this.set(node);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the content shown by the popover.
|
||||
*
|
||||
* @return the content node property
|
||||
*/
|
||||
public final ObjectProperty<Node> contentNodeProperty() {
|
||||
return contentNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the content property.
|
||||
*
|
||||
* @return the content node
|
||||
* @see #contentNodeProperty()
|
||||
*/
|
||||
public final Node getContentNode() {
|
||||
return contentNodeProperty().get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the content property.
|
||||
*
|
||||
* @param content the new content node value
|
||||
* @see #contentNodeProperty()
|
||||
*/
|
||||
public final void setContentNode(Node content) {
|
||||
contentNodeProperty().set(content);
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Listeners //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private final InvalidationListener hideListener = observable -> {
|
||||
if (!isDetached()) {
|
||||
@ -220,10 +194,17 @@ public class Popover extends PopupControl {
|
||||
private final WeakChangeListener<Number> weakYListener = new WeakChangeListener<>(yListener);
|
||||
|
||||
private Window ownerWindow;
|
||||
private final EventHandler<WindowEvent> closePopoverOnOwnerWindowCloseLambda = event -> ownerWindowHiding();
|
||||
|
||||
private final EventHandler<WindowEvent> closePopoverOnOwnerWindowCloseLambda
|
||||
= event -> ownerWindowHiding();
|
||||
|
||||
private final WeakEventHandler<WindowEvent> closePopoverOnOwnerWindowClose =
|
||||
new WeakEventHandler<>(closePopoverOnOwnerWindowCloseLambda);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// API //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Shows the popover in a position relative to the edges of the given owner
|
||||
* node. The position is dependent on the arrow location. If the arrow is
|
||||
@ -232,7 +213,7 @@ public class Popover extends PopupControl {
|
||||
* below the given owner node. The arrow will slightly overlap with the
|
||||
* owner node.
|
||||
*
|
||||
* @param owner the owner of the popover
|
||||
* @param owner The owner of the popover.
|
||||
*/
|
||||
public final void show(Node owner) {
|
||||
show(owner, 4);
|
||||
@ -245,10 +226,10 @@ public class Popover extends PopupControl {
|
||||
* given owner. If the arrow points up then the popover will be placed
|
||||
* below the given owner node.
|
||||
*
|
||||
* @param owner the owner of the popover
|
||||
* @param offset if negative specifies the distance to the owner node or when
|
||||
* @param owner The owner of the popover.
|
||||
* @param offset If negative specifies the distance to the owner node or when
|
||||
* 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) {
|
||||
Objects.requireNonNull(owner, "Owner node cannot be null!");
|
||||
@ -311,9 +292,9 @@ public class Popover extends PopupControl {
|
||||
* 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.
|
||||
*
|
||||
* @param owner the owning node
|
||||
* @param x the x coordinate for the popover arrow tip
|
||||
* @param y the y coordinate for the popover arrow tip
|
||||
* @param owner The owning node.
|
||||
* @param x The x coordinate for the popover arrow tip.
|
||||
* @param y The y coordinate for the popover arrow tip.
|
||||
*/
|
||||
@Override
|
||||
public final void show(Node owner, double x, double y) {
|
||||
@ -325,17 +306,16 @@ public class Popover extends PopupControl {
|
||||
* 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.
|
||||
*
|
||||
* @param owner the owning node
|
||||
* @param x the x 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 owner The owning node.
|
||||
* @param x The x 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.
|
||||
* This duration takes precedence over the fade-in property without setting.
|
||||
*/
|
||||
public final void show(Node owner, double x, double y, Duration fadeInDuration) {
|
||||
/*
|
||||
* Calling show() a second time without first closing the popover
|
||||
* causes it to be placed at the wrong location.
|
||||
*/
|
||||
|
||||
// Calling show() a second time without first closing the popover
|
||||
// causes it to be placed at the wrong location.
|
||||
if (ownerWindow != null && isShowing()) {
|
||||
super.hide();
|
||||
}
|
||||
@ -433,8 +413,8 @@ public class Popover extends PopupControl {
|
||||
/**
|
||||
* Hides the popover by quickly changing its opacity to 0.
|
||||
*
|
||||
* @param fadeOutDuration the duration of the fade transition that is being used to
|
||||
* change the opacity of the popover
|
||||
* @param fadeOutDuration The duration of the fade transition that is being used to
|
||||
* change the opacity of the popover.
|
||||
*/
|
||||
public final void hide(Duration fadeOutDuration) {
|
||||
if (fadeOutDuration == null) {
|
||||
@ -521,7 +501,46 @@ public class Popover extends PopupControl {
|
||||
}
|
||||
}
|
||||
|
||||
private final BooleanProperty headerAlwaysVisible = new SimpleBooleanProperty(this, "headerAlwaysVisible");
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Properties //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Specifies the content shown by the popover.
|
||||
*/
|
||||
public final ObjectProperty<Node> contentNodeProperty() {
|
||||
return contentNode;
|
||||
}
|
||||
|
||||
private final ObjectProperty<Node> contentNode = new SimpleObjectProperty<>(this, "contentNode") {
|
||||
@Override
|
||||
public void setValue(Node node) {
|
||||
if (node == null) {
|
||||
throw new NullPointerException("Node cannot be null!");
|
||||
}
|
||||
this.set(node);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the value of the content property.
|
||||
*
|
||||
* @return the content node.
|
||||
* @see #contentNodeProperty()
|
||||
*/
|
||||
public final Node getContentNode() {
|
||||
return contentNodeProperty().get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the content property.
|
||||
*
|
||||
* @param content The new content node value.
|
||||
* @see #contentNodeProperty()
|
||||
*/
|
||||
public final void setContentNode(Node content) {
|
||||
contentNodeProperty().set(content);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the {@link Popover} header should remain visible or not,
|
||||
@ -531,10 +550,12 @@ public class Popover extends PopupControl {
|
||||
return headerAlwaysVisible;
|
||||
}
|
||||
|
||||
private final BooleanProperty headerAlwaysVisible = new SimpleBooleanProperty(this, "headerAlwaysVisible");
|
||||
|
||||
/**
|
||||
* 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()
|
||||
*/
|
||||
public final void setHeaderAlwaysVisible(boolean visible) {
|
||||
@ -544,15 +565,13 @@ public class Popover extends PopupControl {
|
||||
/**
|
||||
* 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()
|
||||
*/
|
||||
public final boolean isHeaderAlwaysVisible() {
|
||||
return headerAlwaysVisible.getValue();
|
||||
}
|
||||
|
||||
private final BooleanProperty closeButtonEnabled = new SimpleBooleanProperty(this, "closeButtonEnabled", true);
|
||||
|
||||
/**
|
||||
* Determines whether the header's close button should be available or not.
|
||||
*/
|
||||
@ -560,10 +579,12 @@ public class Popover extends PopupControl {
|
||||
return closeButtonEnabled;
|
||||
}
|
||||
|
||||
private final BooleanProperty closeButtonEnabled = new SimpleBooleanProperty(this, "closeButtonEnabled", true);
|
||||
|
||||
/**
|
||||
* 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()
|
||||
*/
|
||||
public final void setCloseButtonEnabled(boolean enabled) {
|
||||
@ -573,15 +594,13 @@ public class Popover extends PopupControl {
|
||||
/**
|
||||
* 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()
|
||||
*/
|
||||
public final boolean isCloseButtonEnabled() {
|
||||
return closeButtonEnabled.getValue();
|
||||
}
|
||||
|
||||
private final BooleanProperty detachable = new SimpleBooleanProperty(this, "detachable", true);
|
||||
|
||||
/**
|
||||
* Determines if the popover is detachable at all.
|
||||
*/
|
||||
@ -589,10 +608,12 @@ public class Popover extends PopupControl {
|
||||
return detachable;
|
||||
}
|
||||
|
||||
private final BooleanProperty detachable = new SimpleBooleanProperty(this, "detachable", true);
|
||||
|
||||
/**
|
||||
* 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()
|
||||
*/
|
||||
public final void setDetachable(boolean detachable) {
|
||||
@ -602,31 +623,28 @@ public class Popover extends PopupControl {
|
||||
/**
|
||||
* Returns the value of the detachable property.
|
||||
*
|
||||
* @return true if the user is allowed to detach / tear off the popover
|
||||
* @return "true" if the user is allowed to detach / tear off the popover
|
||||
* @see #detachableProperty()
|
||||
*/
|
||||
public final boolean isDetachable() {
|
||||
return detachableProperty().get();
|
||||
}
|
||||
|
||||
private final BooleanProperty detached = new SimpleBooleanProperty(this, "detached", false);
|
||||
|
||||
/**
|
||||
* Determines whether the popover is detached from the owning node or not.
|
||||
* A detached popover no longer shows an arrow pointing at the owner and
|
||||
* features its own title bar.
|
||||
*
|
||||
* @return the detached property
|
||||
*/
|
||||
public final BooleanProperty detachedProperty() {
|
||||
return detached;
|
||||
}
|
||||
|
||||
private final BooleanProperty detached = new SimpleBooleanProperty(this, "detached", false);
|
||||
|
||||
/**
|
||||
* Sets the value of the detached property.
|
||||
*
|
||||
* @param detached if true the popover will change its appearance to "detached"
|
||||
* mode
|
||||
* @param detached If "true" the popover will change its appearance to "detached" mode.
|
||||
* @see #detachedProperty()
|
||||
*/
|
||||
public final void setDetached(boolean detached) {
|
||||
@ -636,24 +654,23 @@ public class Popover extends PopupControl {
|
||||
/**
|
||||
* 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()
|
||||
*/
|
||||
public final boolean isDetached() {
|
||||
return detachedProperty().get();
|
||||
}
|
||||
|
||||
private final DoubleProperty arrowSize = new SimpleDoubleProperty(this, "arrowSize", 12);
|
||||
|
||||
/**
|
||||
* Controls the size of the arrow. Default value is 12.
|
||||
*
|
||||
* @return the arrow size property
|
||||
* Controls the size of the arrow.
|
||||
* Default value is "12".
|
||||
*/
|
||||
public final DoubleProperty arrowSizeProperty() {
|
||||
return arrowSize;
|
||||
}
|
||||
|
||||
private final DoubleProperty arrowSize = new SimpleDoubleProperty(this, "arrowSize", 12);
|
||||
|
||||
/**
|
||||
* Returns the value of the arrow size property.
|
||||
*
|
||||
@ -667,25 +684,23 @@ public class Popover extends PopupControl {
|
||||
/**
|
||||
* 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()
|
||||
*/
|
||||
public final void setArrowSize(double size) {
|
||||
arrowSizeProperty().set(size);
|
||||
}
|
||||
|
||||
private final DoubleProperty arrowIndent = new SimpleDoubleProperty(this, "arrowIndent", 12);
|
||||
|
||||
/**
|
||||
* Controls the distance between the arrow and the corners of the popover.
|
||||
* The default value is 12.
|
||||
*
|
||||
* @return the arrow indent property
|
||||
* Default value is "12".
|
||||
*/
|
||||
public final DoubleProperty arrowIndentProperty() {
|
||||
return arrowIndent;
|
||||
}
|
||||
|
||||
private final DoubleProperty arrowIndent = new SimpleDoubleProperty(this, "arrowIndent", 12);
|
||||
|
||||
/**
|
||||
* Returns the value of the arrow indent property.
|
||||
*
|
||||
@ -699,24 +714,23 @@ public class Popover extends PopupControl {
|
||||
/**
|
||||
* Sets the value of the arrow indent property.
|
||||
*
|
||||
* @param size the arrow indent value
|
||||
* @param size The arrow indent value.
|
||||
* @see #arrowIndentProperty()
|
||||
*/
|
||||
public final void setArrowIndent(double size) {
|
||||
arrowIndentProperty().set(size);
|
||||
}
|
||||
|
||||
private final DoubleProperty cornerRadius = new SimpleDoubleProperty(this, "cornerRadius", 6);
|
||||
|
||||
/**
|
||||
* Returns the corner radius property for the popover.
|
||||
*
|
||||
* @return the corner radius property (default is 6)
|
||||
* Default value is "6".
|
||||
*/
|
||||
public final DoubleProperty cornerRadiusProperty() {
|
||||
return cornerRadius;
|
||||
}
|
||||
|
||||
private final DoubleProperty cornerRadius = new SimpleDoubleProperty(this, "cornerRadius", 6);
|
||||
|
||||
/**
|
||||
* Returns the value of the corner radius property.
|
||||
*
|
||||
@ -730,24 +744,22 @@ public class Popover extends PopupControl {
|
||||
/**
|
||||
* Sets the value of the corner radius property.
|
||||
*
|
||||
* @param radius the corner radius
|
||||
* @param radius The corner radius.
|
||||
* @see #cornerRadiusProperty()
|
||||
*/
|
||||
public final void setCornerRadius(double radius) {
|
||||
cornerRadiusProperty().set(radius);
|
||||
}
|
||||
|
||||
private final StringProperty title = new SimpleStringProperty(this, "title", "Info");
|
||||
|
||||
/**
|
||||
* Stores the title to display in the Popover's header.
|
||||
*
|
||||
* @return the title property
|
||||
*/
|
||||
public final StringProperty titleProperty() {
|
||||
return title;
|
||||
}
|
||||
|
||||
private final StringProperty title = new SimpleStringProperty(this, "title", "Info");
|
||||
|
||||
/**
|
||||
* Returns the value of the title property.
|
||||
*
|
||||
@ -761,7 +773,7 @@ public class Popover extends PopupControl {
|
||||
/**
|
||||
* 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()
|
||||
*/
|
||||
public final void setTitle(String title) {
|
||||
@ -771,24 +783,23 @@ public class Popover extends PopupControl {
|
||||
titleProperty().set(title);
|
||||
}
|
||||
|
||||
private final ObjectProperty<ArrowLocation> arrowLocation =
|
||||
new SimpleObjectProperty<>(this, "arrowLocation", ArrowLocation.LEFT_TOP);
|
||||
|
||||
/**
|
||||
* Stores the preferred arrow location. This might not be the actual
|
||||
* location of the arrow if auto fix is enabled.
|
||||
*
|
||||
* @return the arrow location property
|
||||
* @see #setAutoFix(boolean)
|
||||
*/
|
||||
public final ObjectProperty<ArrowLocation> arrowLocationProperty() {
|
||||
return arrowLocation;
|
||||
}
|
||||
|
||||
private final ObjectProperty<ArrowLocation> arrowLocation =
|
||||
new SimpleObjectProperty<>(this, "arrowLocation", ArrowLocation.LEFT_TOP);
|
||||
|
||||
/**
|
||||
* Sets the value of the arrow location property.
|
||||
*
|
||||
* @param location the requested location
|
||||
* @param location The requested location.
|
||||
* @see #arrowLocationProperty()
|
||||
*/
|
||||
public final void setArrowLocation(ArrowLocation location) {
|
||||
@ -824,22 +835,13 @@ public class Popover extends PopupControl {
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the fade-in duration. This should be set before calling Popover.show(..).
|
||||
*
|
||||
* @return the fade-in duration property
|
||||
* Stores the fade-in duration. This should be set before calling <code>Popover.show(..)</code>.
|
||||
*/
|
||||
public final ObjectProperty<Duration> fadeInDurationProperty() {
|
||||
return fadeInDuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the fade-out duration.
|
||||
*
|
||||
* @return the fade-out duration property
|
||||
*/
|
||||
public final ObjectProperty<Duration> fadeOutDurationProperty() {
|
||||
return fadeOutDuration;
|
||||
}
|
||||
private final ObjectProperty<Duration> fadeInDuration = new SimpleObjectProperty<>(DEFAULT_FADE_DURATION);
|
||||
|
||||
/**
|
||||
* Returns the value of the fade-in duration property.
|
||||
@ -855,13 +857,22 @@ public class Popover extends PopupControl {
|
||||
* Sets the value of the fade-in duration property. This should be set before calling
|
||||
* Popover.show(..).
|
||||
*
|
||||
* @param duration the requested fade-in duration
|
||||
* @param duration The requested fade-in duration.
|
||||
* @see #fadeInDurationProperty()
|
||||
*/
|
||||
public final void setFadeInDuration(Duration duration) {
|
||||
fadeInDurationProperty().setValue(duration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the fade-out duration.
|
||||
*/
|
||||
public final ObjectProperty<Duration> fadeOutDurationProperty() {
|
||||
return fadeOutDuration;
|
||||
}
|
||||
|
||||
private final ObjectProperty<Duration> fadeOutDuration = new SimpleObjectProperty<>(DEFAULT_FADE_DURATION);
|
||||
|
||||
/**
|
||||
* Returns the value of the fade-out duration property.
|
||||
*
|
||||
@ -875,7 +886,7 @@ public class Popover extends PopupControl {
|
||||
/**
|
||||
* 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()
|
||||
*/
|
||||
public final void setFadeOutDuration(Duration duration) {
|
||||
@ -885,17 +896,17 @@ public class Popover extends PopupControl {
|
||||
/**
|
||||
* Stores the "animated" flag. If true then the Popover will be shown / hidden with a short
|
||||
* fade in / out animation.
|
||||
*
|
||||
* @return the "animated" property
|
||||
*/
|
||||
public final BooleanProperty animatedProperty() {
|
||||
return animated;
|
||||
}
|
||||
|
||||
private final SimpleBooleanProperty animated = new SimpleBooleanProperty(true);
|
||||
|
||||
/**
|
||||
* 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()
|
||||
*/
|
||||
public final boolean isAnimated() {
|
||||
@ -905,7 +916,7 @@ public class Popover extends PopupControl {
|
||||
/**
|
||||
* Sets the value of the "animated" property.
|
||||
*
|
||||
* @param animated if true the Popover will be shown and hidden with a short fade animation
|
||||
* @param animated If "true" the Popover will be shown and hidden with a short fade animation.
|
||||
* @see #animatedProperty()
|
||||
*/
|
||||
public final void setAnimated(boolean animated) {
|
||||
|
@ -62,6 +62,9 @@ import javafx.scene.shape.QuadCurveTo;
|
||||
import javafx.scene.shape.VLineTo;
|
||||
import javafx.stage.Window;
|
||||
|
||||
/**
|
||||
* The default skin for the {@link Popover} control.
|
||||
*/
|
||||
public class PopoverSkin implements Skin<Popover> {
|
||||
|
||||
private static final String DETACHED_STYLE_CLASS = "detached";
|
||||
|
@ -8,7 +8,7 @@ import javafx.scene.control.skin.SliderSkin;
|
||||
import javafx.scene.layout.StackPane;
|
||||
|
||||
/**
|
||||
* {@link Slider} skin that supports progress color.
|
||||
* A {@link Slider} skin that supports progress color indication.
|
||||
*/
|
||||
public class ProgressSliderSkin extends SliderSkin {
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
package atlantafx.base.controls;
|
||||
|
||||
import javafx.beans.NamedArg;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.ReadOnlyBooleanProperty;
|
||||
import javafx.beans.property.ReadOnlyBooleanWrapper;
|
||||
@ -11,21 +12,43 @@ import javafx.scene.control.ProgressIndicator;
|
||||
import javafx.scene.control.Skin;
|
||||
import javafx.util.StringConverter;
|
||||
|
||||
/**
|
||||
* A ProgressIndicator that displays progress value as a ring that gradually
|
||||
* empties out as a task is completed.
|
||||
*/
|
||||
public class RingProgressIndicator extends ProgressIndicator {
|
||||
|
||||
/**
|
||||
* Creates a new indeterminate ProgressIndicator.
|
||||
*/
|
||||
public RingProgressIndicator() {
|
||||
super();
|
||||
}
|
||||
|
||||
public RingProgressIndicator(double progress) {
|
||||
/**
|
||||
* Creates a new ProgressIndicator with the given progress value.
|
||||
*
|
||||
* @param progress The progress, represented as a value between 0 and 1.
|
||||
*/
|
||||
public RingProgressIndicator(@NamedArg("progress") double progress) {
|
||||
this(progress, false);
|
||||
}
|
||||
|
||||
public RingProgressIndicator(double progress, boolean reverse) {
|
||||
/**
|
||||
* Creates a new ProgressIndicator with the given progress value and type.
|
||||
*
|
||||
* @param progress The progress, represented as a value between 0 and 1.
|
||||
* @param reverse A flag to indicate whether the indicator is reversed or not.
|
||||
*/
|
||||
public RingProgressIndicator(@NamedArg("progress") double progress,
|
||||
@NamedArg("reverse") boolean reverse) {
|
||||
super(progress);
|
||||
this.reverse.set(reverse);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected Skin<?> createDefaultSkin() {
|
||||
return new RingProgressIndicatorSkin(this);
|
||||
@ -35,6 +58,14 @@ public class RingProgressIndicator extends ProgressIndicator {
|
||||
// Properties //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Represents the node to be displayed within the progress indicator. If null,
|
||||
* it will fall back to the Label with an integer progress value from 1 to 100.
|
||||
*/
|
||||
public ObjectProperty<Node> graphicProperty() {
|
||||
return graphic;
|
||||
}
|
||||
|
||||
protected final ObjectProperty<Node> graphic = new SimpleObjectProperty<>(this, "graphic", null);
|
||||
|
||||
public Node getGraphic() {
|
||||
@ -46,15 +77,15 @@ public class RingProgressIndicator extends ProgressIndicator {
|
||||
}
|
||||
|
||||
/**
|
||||
* Any node to be displayed within the progress indicator. If null,
|
||||
* it will fall back to the Label with integer progress value from 1 to 100.
|
||||
* Represents an optional converter to transform the progress value to a string.
|
||||
* It is only used if a custom graphic node is not set.
|
||||
*
|
||||
* @see #graphicProperty()
|
||||
*/
|
||||
public ObjectProperty<Node> graphicProperty() {
|
||||
return graphic;
|
||||
public ObjectProperty<StringConverter<Double>> stringConverterProperty() {
|
||||
return stringConverter;
|
||||
}
|
||||
|
||||
// ~
|
||||
|
||||
protected final ObjectProperty<StringConverter<Double>> stringConverter =
|
||||
new SimpleObjectProperty<>(this, "converter", null);
|
||||
|
||||
@ -67,25 +98,16 @@ public class RingProgressIndicator extends ProgressIndicator {
|
||||
}
|
||||
|
||||
/**
|
||||
* Optional converter to transform progress value to string.
|
||||
*/
|
||||
public ObjectProperty<StringConverter<Double>> stringConverterProperty() {
|
||||
return stringConverter;
|
||||
}
|
||||
|
||||
// ~
|
||||
|
||||
private final ReadOnlyBooleanWrapper reverse = new ReadOnlyBooleanWrapper(this, "reverse", false);
|
||||
|
||||
public boolean isReverse() {
|
||||
return reverse.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse progress indicator scale. For indeterminate variant
|
||||
* Reverses the progress indicator scale. For the indeterminate variant,
|
||||
* this means it will be rotated counterclockwise.
|
||||
*/
|
||||
public ReadOnlyBooleanProperty reverseProperty() {
|
||||
return reverse.getReadOnlyProperty();
|
||||
}
|
||||
|
||||
protected final ReadOnlyBooleanWrapper reverse = new ReadOnlyBooleanWrapper(this, "reverse", false);
|
||||
|
||||
public boolean isReverse() {
|
||||
return reverse.get();
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,9 @@ import javafx.scene.shape.Arc;
|
||||
import javafx.scene.shape.Circle;
|
||||
import javafx.util.Duration;
|
||||
|
||||
/**
|
||||
* The default skin for the {@link RingProgressIndicator} control.
|
||||
*/
|
||||
public class RingProgressIndicatorSkin extends SkinBase<RingProgressIndicator> {
|
||||
|
||||
protected static final double DEFAULT_ANIMATION_TIME = 3;
|
||||
|
@ -11,6 +11,15 @@ import javafx.scene.Node;
|
||||
import javafx.scene.layout.Pane;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* An internal convenience class for implementing slot-based approach.
|
||||
*
|
||||
* <p>It is intended to be used for controls that allow custom user nodes
|
||||
* to be placed inside their skins. his class automatically adds or removes
|
||||
* an updated <code>ObservableValue<? extends Node></code> value to/from the
|
||||
* given container and also maintains the <code>:filled</code> pseudo-class
|
||||
* state to indicate whether the corresponding slot is empty or not.
|
||||
*/
|
||||
final class SlotListener implements ChangeListener<Node> {
|
||||
|
||||
private static final PseudoClass FILLED = PseudoClass.getPseudoClass("filled");
|
||||
@ -18,10 +27,24 @@ final class SlotListener implements ChangeListener<Node> {
|
||||
private final Pane slot;
|
||||
private final @Nullable BiConsumer<Node, Boolean> onContentUpdate;
|
||||
|
||||
/**
|
||||
* Creates a new listener and binds it to the specified container.
|
||||
*
|
||||
* @param slot The container for user-specified node.
|
||||
*/
|
||||
public SlotListener(Pane slot) {
|
||||
this(slot, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new listener and binds it to the specified container.
|
||||
* Also, it registers the custom callback handler that will be notified
|
||||
* upon the container content changed.
|
||||
*
|
||||
* @param slot The container for user-specified node.
|
||||
* @param onContentUpdate The callback handler to be notified upon
|
||||
* the container content changing.
|
||||
*/
|
||||
public SlotListener(Node slot, @Nullable BiConsumer<Node, Boolean> onContentUpdate) {
|
||||
Objects.requireNonNull(slot, "Slot cannot be null.");
|
||||
|
||||
|
@ -8,12 +8,38 @@ import javafx.scene.layout.Priority;
|
||||
import javafx.scene.layout.Region;
|
||||
import javafx.scene.layout.VBox;
|
||||
|
||||
/**
|
||||
* A spacing component used to distribute remaining width between
|
||||
* a parent's child components.
|
||||
*
|
||||
* <p>When placing a single Spacer before or after the child components,
|
||||
* the components will be pushed to the right and left of its container
|
||||
* for horizontally oriented Spacer, or to the top and bottom for vertically
|
||||
* oriented Spacer.
|
||||
*
|
||||
* <p>You can also specify the `Spacer` size. In this case, it will not be
|
||||
* extended and will work like a gap with the given size between sibling components.
|
||||
*
|
||||
* <p>Note that this control is not intended to be used in FXML unless SceneBuilder
|
||||
* supports constructor arguments, because none of the properties mentioned above are
|
||||
* observable.
|
||||
*/
|
||||
public class Spacer extends Region {
|
||||
|
||||
/**
|
||||
* Creates a new horizontally oriented Spacer that expands
|
||||
* to fill remaining space.
|
||||
*/
|
||||
public Spacer() {
|
||||
this(Orientation.HORIZONTAL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Spacer with the given orientation that expands
|
||||
* to fill remaining space.
|
||||
*
|
||||
* @param orientation The orientation of the spacer.
|
||||
*/
|
||||
public Spacer(Orientation orientation) {
|
||||
super();
|
||||
|
||||
@ -23,10 +49,21 @@ public class Spacer extends Region {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Spacer with the fixed size.
|
||||
*
|
||||
* @param size The size of the spacer.
|
||||
*/
|
||||
public Spacer(double size) {
|
||||
this(size, Orientation.HORIZONTAL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Spacer with the fixed size and orientation.
|
||||
*
|
||||
* @param size The size of the spacer.
|
||||
* @param orientation The orientation of the spacer.
|
||||
*/
|
||||
public Spacer(double size, Orientation orientation) {
|
||||
super();
|
||||
|
||||
|
@ -10,21 +10,37 @@ import javafx.scene.control.Skin;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* A versatile container that can used in various contexts such as dialog headers,
|
||||
* list items, and cards. It can contain a graphic, a title, description, and optional
|
||||
* actions.
|
||||
* A versatile container that can used in various contexts such as dialog
|
||||
* headers, list items, and cards. It can contain a graphic, a title, description,
|
||||
* and optional actions.
|
||||
*/
|
||||
public class Tile extends TileBase {
|
||||
|
||||
/**
|
||||
* Creates a new empty Tile.
|
||||
*/
|
||||
public Tile() {
|
||||
this(null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Tile with an initial title and description.
|
||||
*
|
||||
* @param title A string for the title.
|
||||
* @param description A string for the description.
|
||||
*/
|
||||
public Tile(@Nullable @NamedArg("title") String title,
|
||||
@Nullable @NamedArg("description") String description) {
|
||||
this(title, description, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Tile with an initial title, description and graphic.
|
||||
*
|
||||
* @param title A string for the title.
|
||||
* @param description A string for the description.
|
||||
* @param graphic A graphic or icon.
|
||||
*/
|
||||
public Tile(@Nullable String title,
|
||||
@Nullable String description,
|
||||
@Nullable Node graphic) {
|
||||
@ -32,6 +48,9 @@ public class Tile extends TileBase {
|
||||
getStyleClass().add("tile");
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected Skin<?> createDefaultSkin() {
|
||||
return new TileSkin(this);
|
||||
@ -42,38 +61,40 @@ public class Tile extends TileBase {
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* The property representing the tile’s action node. It is commonly used
|
||||
* to place an action controls that are associated with the tile.
|
||||
* Represents the node to be placed in the tile’s action slot. It is commonly
|
||||
* used to place action controls that are associated with the tile.
|
||||
*/
|
||||
public ObjectProperty<Node> actionProperty() {
|
||||
return action;
|
||||
}
|
||||
|
||||
private final ObjectProperty<Node> action = new SimpleObjectProperty<>(this, "action");
|
||||
|
||||
public Node getAction() {
|
||||
return action.get();
|
||||
}
|
||||
|
||||
public ObjectProperty<Node> actionProperty() {
|
||||
return action;
|
||||
}
|
||||
|
||||
public void setAction(Node action) {
|
||||
this.action.set(action);
|
||||
}
|
||||
|
||||
/**
|
||||
* The property representing the tile’s action handler. Setting an action handler
|
||||
* makes the tile interactive or clickable. When a user clicks on the interactive
|
||||
* tile, the specified action handler will be called.
|
||||
* Represents the tile’s action handler.
|
||||
*
|
||||
* <p>Setting an action handler makes the tile interactive (or clickable).
|
||||
* When a user clicks on the interactive tile, the specified action handler will be called.
|
||||
*/
|
||||
private final ObjectProperty<Runnable> actionHandler = new SimpleObjectProperty<>(this, "actionHandler");
|
||||
public ObjectProperty<Runnable> actionHandlerProperty() {
|
||||
return actionHandler;
|
||||
}
|
||||
|
||||
private final ObjectProperty<Runnable> actionHandler
|
||||
= new SimpleObjectProperty<>(this, "actionHandler");
|
||||
|
||||
public Runnable getActionHandler() {
|
||||
return actionHandler.get();
|
||||
}
|
||||
|
||||
public ObjectProperty<Runnable> actionHandlerProperty() {
|
||||
return actionHandler;
|
||||
}
|
||||
|
||||
public void setActionHandler(Runnable actionHandler) {
|
||||
this.actionHandler.set(actionHandler);
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
package atlantafx.base.controls;
|
||||
|
||||
import javafx.beans.NamedArg;
|
||||
import atlantafx.base.util.BBCodeParser;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
@ -11,14 +11,18 @@ import javafx.scene.Node;
|
||||
import javafx.scene.control.Control;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* A common class for implementing tile-based controls, specifically the
|
||||
* {@link Message} and the {@link Tile}.
|
||||
*/
|
||||
public abstract class TileBase extends Control {
|
||||
|
||||
public TileBase() {
|
||||
this(null, null, null);
|
||||
}
|
||||
|
||||
public TileBase(@Nullable @NamedArg("title") String title,
|
||||
@Nullable @NamedArg("description") String description) {
|
||||
public TileBase(@Nullable String title,
|
||||
@Nullable String description) {
|
||||
this(title, description, null);
|
||||
}
|
||||
|
||||
@ -38,54 +42,56 @@ public abstract class TileBase extends Control {
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* The property representing the tile’s graphic node. It is commonly used
|
||||
* to add images or icons that are associated with the tile.
|
||||
* Represents the tile’s graphic node. It is commonly used to add images or icons
|
||||
* that are associated with the tile.
|
||||
*/
|
||||
public ObjectProperty<Node> graphicProperty() {
|
||||
return graphic;
|
||||
}
|
||||
|
||||
private final ObjectProperty<Node> graphic = new SimpleObjectProperty<>(this, "graphic");
|
||||
|
||||
public Node getGraphic() {
|
||||
return graphic.get();
|
||||
}
|
||||
|
||||
public ObjectProperty<Node> graphicProperty() {
|
||||
return graphic;
|
||||
}
|
||||
|
||||
public void setGraphic(Node graphic) {
|
||||
this.graphic.set(graphic);
|
||||
}
|
||||
|
||||
/**
|
||||
* The property representing the tile’s title. Although it is not mandatory,
|
||||
* you typically would not want to have a tile without a title.
|
||||
* Represents the tile’s title (or header).
|
||||
*/
|
||||
public StringProperty titleProperty() {
|
||||
return title;
|
||||
}
|
||||
|
||||
private final StringProperty title = new SimpleStringProperty(this, "title");
|
||||
|
||||
public String getTitle() {
|
||||
return title.get();
|
||||
}
|
||||
|
||||
public StringProperty titleProperty() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title.set(title);
|
||||
}
|
||||
|
||||
/**
|
||||
* The property representing the tile’s description.
|
||||
* Represents the tile’s description (or optional text).
|
||||
*
|
||||
* <p>This property supports BBCode formatted text. Refer to the {@link BBCodeParser}
|
||||
* for more information.
|
||||
*/
|
||||
public StringProperty descriptionProperty() {
|
||||
return description;
|
||||
}
|
||||
|
||||
private final StringProperty description = new SimpleStringProperty(this, "description");
|
||||
|
||||
public String getDescription() {
|
||||
return description.get();
|
||||
}
|
||||
|
||||
public StringProperty descriptionProperty() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description.set(description);
|
||||
}
|
||||
|
@ -4,6 +4,9 @@ package atlantafx.base.controls;
|
||||
|
||||
import atlantafx.base.theme.Styles;
|
||||
|
||||
/**
|
||||
* The default skin for the {@link Tile} control.
|
||||
*/
|
||||
public class TileSkin extends TileSkinBase<Tile> {
|
||||
|
||||
public TileSkin(Tile control) {
|
||||
|
@ -15,6 +15,10 @@ import javafx.scene.layout.StackPane;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.scene.text.TextFlow;
|
||||
|
||||
/**
|
||||
* A common skin for implementing tile-based controls, specifically the
|
||||
* {@link MessageSkin} and the {@link TileSkin}.
|
||||
*/
|
||||
public abstract class TileSkinBase<T extends TileBase> extends SkinBase<T> {
|
||||
|
||||
protected static final PseudoClass HAS_GRAPHIC = PseudoClass.getPseudoClass("has-graphic");
|
||||
|
@ -51,7 +51,11 @@ import javafx.scene.control.Skin;
|
||||
import javafx.scene.control.Toggle;
|
||||
import javafx.scene.control.ToggleGroup;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
/**
|
||||
* A control that provides users with the ability to choose between two distinct values.
|
||||
* It is functionally similar, though aesthetically different, from the RadioButton
|
||||
* and Checkbox.
|
||||
*/
|
||||
public class ToggleSwitch extends Labeled implements Toggle {
|
||||
|
||||
protected static final String DEFAULT_STYLE_CLASS = "toggle-switch";
|
||||
@ -68,13 +72,21 @@ public class ToggleSwitch extends Labeled implements Toggle {
|
||||
/**
|
||||
* Creates a toggle switch with the specified label.
|
||||
*
|
||||
* @param text The label string of the control
|
||||
* @param text The label string of the control.
|
||||
*/
|
||||
public ToggleSwitch(String text) {
|
||||
super(text);
|
||||
initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected Skin<?> createDefaultSkin() {
|
||||
return new ToggleSwitchSkin(this);
|
||||
}
|
||||
|
||||
private void initialize() {
|
||||
getStyleClass().setAll(DEFAULT_STYLE_CLASS);
|
||||
}
|
||||
@ -83,18 +95,6 @@ public class ToggleSwitch extends Labeled implements Toggle {
|
||||
// Properties //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private BooleanProperty selected;
|
||||
|
||||
@Override
|
||||
public final void setSelected(boolean value) {
|
||||
selectedProperty().set(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isSelected() {
|
||||
return selected != null && selected.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this Toggle Switch is selected.
|
||||
*/
|
||||
@ -151,24 +151,23 @@ public class ToggleSwitch extends Labeled implements Toggle {
|
||||
return selected;
|
||||
}
|
||||
|
||||
private BooleanProperty selected;
|
||||
|
||||
@Override
|
||||
public final void setSelected(boolean value) {
|
||||
selectedProperty().set(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isSelected() {
|
||||
return selected != null && selected.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link ToggleGroup} to which this {@code ToggleSwitch} belongs.
|
||||
* A {@code ToggleSwitch} can only be in one group at any one time. If the
|
||||
* group is changed, then the button is removed from the old group prior to
|
||||
* being added to the new group.
|
||||
* The {@link ToggleGroup} to which this ToggleSwitch belongs. A toggle can only
|
||||
* be in one group at any one time. If the group is changed, then the toggle is
|
||||
* removed from the old group prior to being added to the new group.
|
||||
*/
|
||||
private ObjectProperty<ToggleGroup> toggleGroup;
|
||||
|
||||
@Override
|
||||
public final void setToggleGroup(ToggleGroup value) {
|
||||
toggleGroupProperty().set(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final ToggleGroup getToggleGroup() {
|
||||
return toggleGroup == null ? null : toggleGroup.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final ObjectProperty<ToggleGroup> toggleGroupProperty() {
|
||||
if (toggleGroup == null) {
|
||||
@ -204,23 +203,20 @@ public class ToggleSwitch extends Labeled implements Toggle {
|
||||
return toggleGroup;
|
||||
}
|
||||
|
||||
// ~
|
||||
private ObjectProperty<ToggleGroup> toggleGroup;
|
||||
|
||||
private ObjectProperty<HorizontalDirection> labelPosition;
|
||||
@Override
|
||||
public final void setToggleGroup(ToggleGroup value) {
|
||||
toggleGroupProperty().set(value);
|
||||
}
|
||||
|
||||
public final void setLabelPosition(HorizontalDirection pos) {
|
||||
labelPositionProperty().setValue(pos);
|
||||
@Override
|
||||
public final ToggleGroup getToggleGroup() {
|
||||
return toggleGroup == null ? null : toggleGroup.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this Toggle Switch is selected.
|
||||
*/
|
||||
public final HorizontalDirection getLabelPosition() {
|
||||
return labelPosition == null ? HorizontalDirection.LEFT : labelPosition.getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the side where {@link #textProperty()} values should be placed.
|
||||
* Specifies the side where {@link #textProperty()} value should be placed.
|
||||
* Default is {@link HorizontalDirection#LEFT}.
|
||||
*/
|
||||
public final ObjectProperty<HorizontalDirection> labelPositionProperty() {
|
||||
@ -253,13 +249,22 @@ public class ToggleSwitch extends Labeled implements Toggle {
|
||||
return labelPosition;
|
||||
}
|
||||
|
||||
private ObjectProperty<HorizontalDirection> labelPosition;
|
||||
|
||||
public final void setLabelPosition(HorizontalDirection pos) {
|
||||
labelPositionProperty().setValue(pos);
|
||||
}
|
||||
|
||||
public final HorizontalDirection getLabelPosition() {
|
||||
return labelPosition == null ? HorizontalDirection.LEFT : labelPosition.getValue();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Methods //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Toggles the state of the {@code Switch}. The {@code Switch} will cycle
|
||||
* through the selected and unselected states.
|
||||
* Toggles the state of the switch, cycling through the selected and unselected states.
|
||||
*/
|
||||
public void fire() {
|
||||
if (!isDisabled()) {
|
||||
@ -268,13 +273,9 @@ public class ToggleSwitch extends Labeled implements Toggle {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected Skin<?> createDefaultSkin() {
|
||||
return new ToggleSwitchSkin(this);
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Styleable Properties //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
@ -284,10 +285,6 @@ public class ToggleSwitch extends Labeled implements Toggle {
|
||||
return StyleableProperties.STYLEABLES;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Styleable Properties //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private static class StyleableProperties {
|
||||
|
||||
private static final CssMetaData<ToggleSwitch, HorizontalDirection> LABEL_POSITION = new CssMetaData<>(
|
||||
|
@ -48,6 +48,9 @@ import javafx.scene.control.SkinBase;
|
||||
import javafx.scene.layout.StackPane;
|
||||
import javafx.util.Duration;
|
||||
|
||||
/**
|
||||
* The default skin for the {@link ToggleSwitch} control.
|
||||
*/
|
||||
public class ToggleSwitchSkin extends SkinBase<ToggleSwitch> {
|
||||
|
||||
protected static final Duration DEFAULT_ANIMATION_TIME = Duration.millis(200);
|
||||
|
@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Defines the UI controls and their corresponding skins.
|
||||
*/
|
||||
|
||||
package atlantafx.base.controls;
|
@ -22,15 +22,15 @@ import javafx.util.Duration;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* DeckPane represents a pane that displays all of its child nodes in a deck,
|
||||
* where only one node can be visible at a time. It does not maintain any sequence
|
||||
* (model), but only cares about the top node, which can be changed by various
|
||||
* transition effects.<p/>
|
||||
* Represents a pane that displays all of its child nodes in a deck,
|
||||
* where only one node can be visible at a time. It <b>does not maintain any
|
||||
* sequence</b> (model), but only cares about the top node, which can be changed
|
||||
* by various transition effects.<p/>
|
||||
*
|
||||
* <h3>View Order</h3>
|
||||
*
|
||||
* <p>DeckPane manages {@link Node#viewOrderProperty()} of its children. Topmost
|
||||
* visible node always has a higher view order value, while the rest of the nodes
|
||||
* visible node always has the highest view order value, while the rest of the nodes
|
||||
* have the default value, which is zero. Following that logic, one must not set
|
||||
* child nodes view order manually, because it will break the contract.
|
||||
*
|
||||
@ -53,6 +53,9 @@ public class DeckPane extends AnchorPane {
|
||||
// the rest of the nodes
|
||||
protected static final int Z_DEFAULT = 0;
|
||||
|
||||
/**
|
||||
* Creates a new empty DeckPane.
|
||||
*/
|
||||
public DeckPane() {
|
||||
super();
|
||||
|
||||
@ -66,14 +69,19 @@ public class DeckPane extends AnchorPane {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an DeckPane with the given children.
|
||||
*
|
||||
* @param children The initial set of children for this pane.
|
||||
*/
|
||||
public DeckPane(Node... children) {
|
||||
this();
|
||||
getChildren().addAll(children);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the node with the higher view order value or the last node
|
||||
* if all child nodes have the same view order value.
|
||||
* Returns the node with the highest view order value, or the
|
||||
* last node if all child nodes have the same view order value.
|
||||
*/
|
||||
public @Nullable Node getTopNode() {
|
||||
var size = getChildren().size();
|
||||
@ -93,6 +101,8 @@ public class DeckPane extends AnchorPane {
|
||||
/**
|
||||
* Sets given node on top without playing any transition.
|
||||
* Does nothing if that node isn't added to the pane.
|
||||
*
|
||||
* @param target The node to be set on top.
|
||||
*/
|
||||
public void setTopNode(Node target) {
|
||||
if (!getChildren().contains(target)) {
|
||||
@ -120,16 +130,19 @@ public class DeckPane extends AnchorPane {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds given nodes to the pane and binds them to the pane edges
|
||||
* using the provided offsets. See {@link AnchorPane#setTopAnchor(Node, Double)}
|
||||
* Adds the given nodes to the pane and binds them to the pane edges
|
||||
* using the provided offset. See {@link AnchorPane#setTopAnchor(Node, Double)}
|
||||
* for the reference.
|
||||
*
|
||||
* @param offset The offset values for each othe the specified nodes.
|
||||
* @param nodes The array of the nodes to be added.
|
||||
*/
|
||||
public void addChildren(Insets offsets, Node... nodes) {
|
||||
public void addChildren(Insets offset, Node... nodes) {
|
||||
for (var node : nodes) {
|
||||
AnchorPane.setTopAnchor(node, offsets.getTop());
|
||||
AnchorPane.setRightAnchor(node, offsets.getRight());
|
||||
AnchorPane.setBottomAnchor(node, offsets.getBottom());
|
||||
AnchorPane.setLeftAnchor(node, offsets.getLeft());
|
||||
AnchorPane.setTopAnchor(node, offset.getTop());
|
||||
AnchorPane.setRightAnchor(node, offset.getRight());
|
||||
AnchorPane.setBottomAnchor(node, offset.getBottom());
|
||||
AnchorPane.setLeftAnchor(node, offset.getLeft());
|
||||
}
|
||||
getChildren().addAll(nodes);
|
||||
}
|
||||
@ -138,6 +151,8 @@ public class DeckPane extends AnchorPane {
|
||||
* Places target node on the top of the pane while playing the
|
||||
* swipe transition from bottom to top. If the pane doesn't contain
|
||||
* that node, it will be added to the end before playing transition.
|
||||
*
|
||||
* @param target The node to be set on top.
|
||||
*/
|
||||
public void swipeUp(Node target) {
|
||||
var topNode = getTopNode();
|
||||
@ -164,6 +179,8 @@ public class DeckPane extends AnchorPane {
|
||||
* Places target node on the top of the pane while playing the
|
||||
* swipe transition from top to bottom. If the pane doesn't contain
|
||||
* that node, it will be added to the end before playing transition.
|
||||
*
|
||||
* @param target The node to be set on top.
|
||||
*/
|
||||
public void swipeDown(Node target) {
|
||||
var topNode = getTopNode();
|
||||
@ -190,6 +207,8 @@ public class DeckPane extends AnchorPane {
|
||||
* Places target node on the top of the pane while playing the
|
||||
* swipe transition from right to left. If the pane doesn't contain
|
||||
* that node, it will be added to the end before playing transition.
|
||||
*
|
||||
* @param target The node to be set on top.
|
||||
*/
|
||||
public void swipeLeft(Node target) {
|
||||
var topNode = getTopNode();
|
||||
@ -216,6 +235,8 @@ public class DeckPane extends AnchorPane {
|
||||
* Places target node on the top of the pane while playing the
|
||||
* swipe transition from left to right. If the pane doesn't contain
|
||||
* that node, it will be added to the end before playing transition.
|
||||
*
|
||||
* @param target The node to be set on top.
|
||||
*/
|
||||
public void swipeRight(Node target) {
|
||||
var topNode = getTopNode();
|
||||
@ -242,6 +263,8 @@ public class DeckPane extends AnchorPane {
|
||||
* Places target node on the top of the pane while playing the
|
||||
* slide transition from bottom to top. If the pane doesn't contain
|
||||
* that node, it will be added to the end before playing transition.
|
||||
*
|
||||
* @param target The node to be set on top.
|
||||
*/
|
||||
public void slideUp(Node target) {
|
||||
var topNode = getTopNode();
|
||||
@ -265,6 +288,8 @@ public class DeckPane extends AnchorPane {
|
||||
* Places target node on the top of the pane while playing the
|
||||
* slide transition from top to bottom. If the pane doesn't contain
|
||||
* that node, it will be added to the end before playing transition.
|
||||
*
|
||||
* @param target The node to be set on top.
|
||||
*/
|
||||
public void slideDown(Node target) {
|
||||
var topNode = getTopNode();
|
||||
@ -288,6 +313,8 @@ public class DeckPane extends AnchorPane {
|
||||
* Places target node on the top of the pane while playing the
|
||||
* slide transition from right to left. If the pane doesn't contain
|
||||
* that node, it will be added to the end before playing transition.
|
||||
*
|
||||
* @param target The node to be set on top.
|
||||
*/
|
||||
public void slideLeft(Node target) {
|
||||
var topNode = getTopNode();
|
||||
@ -311,6 +338,8 @@ public class DeckPane extends AnchorPane {
|
||||
* Places target node on the top of the pane while playing the
|
||||
* slide transition from left to right. If the pane doesn't contain
|
||||
* that node, it will be added to the end before playing transition.
|
||||
*
|
||||
* @param target The node to be set on top.
|
||||
*/
|
||||
public void slideRight(Node target) {
|
||||
var topNode = getTopNode();
|
||||
@ -334,6 +363,13 @@ public class DeckPane extends AnchorPane {
|
||||
// Properties //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Represents the duration of the transition effect that is played when changing the top node.
|
||||
*/
|
||||
public ObjectProperty<Duration> animationDurationProperty() {
|
||||
return animationDuration;
|
||||
}
|
||||
|
||||
protected final ObjectProperty<Duration> animationDuration =
|
||||
new SimpleObjectProperty<>(this, "animationDuration", Duration.seconds(1));
|
||||
|
||||
@ -341,18 +377,17 @@ public class DeckPane extends AnchorPane {
|
||||
return animationDuration.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Duration of the transition effect which is played when changing the top node.
|
||||
*/
|
||||
public ObjectProperty<Duration> animationDurationProperty() {
|
||||
return animationDuration;
|
||||
}
|
||||
|
||||
public void setAnimationDuration(@Nullable Duration animationDuration) {
|
||||
this.animationDuration.set(Objects.requireNonNullElse(animationDuration, Duration.ZERO));
|
||||
}
|
||||
|
||||
// ~
|
||||
/**
|
||||
* Indicates whether the transition is in progress. Subscribe to this property
|
||||
* to be notified when the animation starts or finishes.
|
||||
*/
|
||||
public ReadOnlyBooleanProperty animationActiveProperty() {
|
||||
return animationActive.getReadOnlyProperty();
|
||||
}
|
||||
|
||||
protected final ReadOnlyBooleanWrapper animationActive =
|
||||
new ReadOnlyBooleanWrapper(this, "animationActive");
|
||||
@ -361,19 +396,16 @@ public class DeckPane extends AnchorPane {
|
||||
return animationActive.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether transition is in progress. Subscribe to be notified
|
||||
* when animation started or finished.
|
||||
*/
|
||||
public ReadOnlyBooleanProperty animationActiveProperty() {
|
||||
return animationActive.getReadOnlyProperty();
|
||||
}
|
||||
|
||||
protected void setAnimationActive(boolean animationActive) {
|
||||
this.animationActive.set(animationActive);
|
||||
}
|
||||
|
||||
// ~
|
||||
/**
|
||||
* Sets the callback action to be called before setting a node at the top of the DeckPane.
|
||||
*/
|
||||
public ObjectProperty<Consumer<Node>> beforeShowCallbackProperty() {
|
||||
return beforeShowCallback;
|
||||
}
|
||||
|
||||
protected final ObjectProperty<Consumer<Node>> beforeShowCallback =
|
||||
new SimpleObjectProperty<>(this, "beforeShowCallback");
|
||||
@ -382,13 +414,6 @@ public class DeckPane extends AnchorPane {
|
||||
return beforeShowCallback.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback action to be called before setting a node at the top of the deck.
|
||||
*/
|
||||
public ObjectProperty<Consumer<Node>> beforeShowCallbackProperty() {
|
||||
return beforeShowCallback;
|
||||
}
|
||||
|
||||
public void setBeforeShowCallback(@Nullable Consumer<Node> callback) {
|
||||
this.beforeShowCallback.set(callback);
|
||||
}
|
||||
@ -399,7 +424,12 @@ public class DeckPane extends AnchorPane {
|
||||
}
|
||||
}
|
||||
|
||||
// ~
|
||||
/**
|
||||
* Sets the callback action to be called after removing the top node from the top of the DeckPane.
|
||||
*/
|
||||
public ObjectProperty<Consumer<Node>> afterHideCallbackProperty() {
|
||||
return afterHideCallback;
|
||||
}
|
||||
|
||||
protected final ObjectProperty<Consumer<Node>> afterHideCallback =
|
||||
new SimpleObjectProperty<>(this, "afterHideCallback");
|
||||
@ -408,13 +438,6 @@ public class DeckPane extends AnchorPane {
|
||||
return afterHideCallback.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback action to be called after removing the top node from the top of the deck.
|
||||
*/
|
||||
public ObjectProperty<Consumer<Node>> afterHideCallbackProperty() {
|
||||
return afterHideCallback;
|
||||
}
|
||||
|
||||
public void setAfterHideCallback(@Nullable Consumer<Node> callback) {
|
||||
this.afterHideCallback.set(callback);
|
||||
}
|
||||
|
@ -9,16 +9,18 @@ import javafx.scene.Node;
|
||||
import javafx.scene.layout.HBox;
|
||||
|
||||
/**
|
||||
* InputGroup is a layout that helps combine multiple controls into a group
|
||||
* that looks like a single control. Without it, you would have to manually
|
||||
* add the "left-pill", "center-pill," and "right-pill" styles classes to
|
||||
* each control in such combination. The InputGroup removes this ceremony.
|
||||
* Since it inherits from HBox, you can use the same API.
|
||||
* A layout that helps combine multiple controls into a group that looks
|
||||
* like a single control.
|
||||
*
|
||||
* <p>Without it, you would have to manually add the ".left-pill", ".center-pill"
|
||||
* and ".right-pill" styles classes to each control in such combination.
|
||||
* The InputGroup removes this ceremony. Since it inherits from HBox, you can use
|
||||
* the same API.
|
||||
*/
|
||||
public class InputGroup extends HBox {
|
||||
|
||||
/**
|
||||
* See {@link HBox#HBox()}.
|
||||
* Creates a new empty InputGroup.
|
||||
*/
|
||||
public InputGroup() {
|
||||
super();
|
||||
@ -26,7 +28,9 @@ public class InputGroup extends HBox {
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link HBox#HBox(Node...)}.
|
||||
* Creates an InputGroup with the given children.
|
||||
*
|
||||
* @param children The initial set of children for this pane.
|
||||
*/
|
||||
public InputGroup(Node... children) {
|
||||
super(children);
|
||||
|
@ -17,11 +17,12 @@ import javafx.scene.layout.StackPane;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* The ModalBox is a specialized control or layout designed to hold the
|
||||
* {@link ModalPane} dialog content. It includes the close button out-of-the-box
|
||||
* and allows for the addition of arbitrary children. The ModalBox is derived
|
||||
* from the {@link AnchorPane}, so it inherits the same API. Just be sure that
|
||||
* you haven't removed the close button while using it.
|
||||
* A specialized control (or layout) designed to hold the {@link ModalPane}
|
||||
* dialog content. It includes the close button out-of-the-box and allows for the
|
||||
* addition of arbitrary children.
|
||||
*
|
||||
* <p>The ModalBox is derived from the {@link AnchorPane}, so it inherits the same API.
|
||||
* Just be sure that you haven't removed the close button while using it.
|
||||
*/
|
||||
public class ModalBox extends AnchorPane {
|
||||
|
||||
@ -40,7 +41,7 @@ public class ModalBox extends AnchorPane {
|
||||
/**
|
||||
* Creates a ModalBox layout with the given children.
|
||||
*
|
||||
* @param children the initial set of children for this pane
|
||||
* @param children The initial set of children for this pane.
|
||||
*/
|
||||
public ModalBox(Node... children) {
|
||||
this((String) null, children);
|
||||
@ -52,8 +53,8 @@ public class ModalBox extends AnchorPane {
|
||||
* on the close button, it performs a ModalPane lookup via the specified
|
||||
* selector and calls the {@link ModalPane#hide()} method automatically.
|
||||
*
|
||||
* @param selector the ModalPane pane CSS selector
|
||||
* @param children the initial set of children for this pane
|
||||
* @param selector The ModalPane pane CSS selector.
|
||||
* @param children The initial set of children for this pane.
|
||||
*/
|
||||
public ModalBox(@Nullable @NamedArg("selector") String selector, Node... children) {
|
||||
super(children);
|
||||
@ -69,8 +70,8 @@ public class ModalBox extends AnchorPane {
|
||||
* the close handler to a ModalPane. When user clicks on the close button,
|
||||
* it calls the {@link ModalPane#hide()} method automatically.
|
||||
*
|
||||
* @param modalPane the ModalPane pane CSS selector
|
||||
* @param children the initial set of children for this pane
|
||||
* @param modalPane The ModalPane pane CSS selector.
|
||||
* @param children The initial set of children for this pane.
|
||||
*/
|
||||
public ModalBox(@Nullable ModalPane modalPane, Node... children) {
|
||||
super(children);
|
||||
@ -88,7 +89,7 @@ public class ModalBox extends AnchorPane {
|
||||
* and {@link Node#isMouseTransparent()} is false, then the close button
|
||||
* will not receive mouse events and therefore will not be clickable.
|
||||
*
|
||||
* @param node the node to be added
|
||||
* @param node The node to be added.
|
||||
*/
|
||||
public void addContent(Node node) {
|
||||
Objects.requireNonNull(node, "Node cannot be null.");
|
||||
@ -142,11 +143,16 @@ public class ModalBox extends AnchorPane {
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* The property representing the user specified close handler. Note that
|
||||
* if you have also specified the ModalPane instance or CSS selector, this
|
||||
* handler will be executed after the default close handler. Therefore, you
|
||||
* The property representing the user specified close handler.
|
||||
*
|
||||
* <p>Note that if you have also specified the ModalPane instance or CSS selector,
|
||||
* this handler will be executed after the default close handler. Therefore, you
|
||||
* can use it to perform arbitrary actions on dialog close.
|
||||
*/
|
||||
public ObjectProperty<EventHandler<? super Event>> onCloseProperty() {
|
||||
return onClose;
|
||||
}
|
||||
|
||||
protected final ObjectProperty<EventHandler<? super Event>> onClose =
|
||||
new SimpleObjectProperty<>(this, "onClose");
|
||||
|
||||
@ -154,27 +160,25 @@ public class ModalBox extends AnchorPane {
|
||||
return onClose.get();
|
||||
}
|
||||
|
||||
public ObjectProperty<EventHandler<? super Event>> onCloseProperty() {
|
||||
return onClose;
|
||||
}
|
||||
|
||||
public void setOnClose(EventHandler<? super Event> onClose) {
|
||||
this.onClose.set(onClose);
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link ModalPane#hide(boolean)}.
|
||||
* Specifies whether to remove (clear) the ModalPane content after it's closed.
|
||||
*
|
||||
* @see ModalPane#hide(boolean).
|
||||
*/
|
||||
public BooleanProperty clearOnCloseProperty() {
|
||||
return clearOnClose;
|
||||
}
|
||||
|
||||
protected final BooleanProperty clearOnClose = new SimpleBooleanProperty(this, "clearOnClose");
|
||||
|
||||
public boolean isClearOnClose() {
|
||||
return clearOnClose.get();
|
||||
}
|
||||
|
||||
public BooleanProperty clearOnCloseProperty() {
|
||||
return clearOnClose;
|
||||
}
|
||||
|
||||
public void setClearOnClose(boolean clearOnClose) {
|
||||
this.clearOnClose.set(clearOnClose);
|
||||
}
|
||||
|
@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Defines additional layouts and layout helpers.
|
||||
*/
|
||||
|
||||
package atlantafx.base.layout;
|
@ -11,8 +11,8 @@ import javafx.scene.Node;
|
||||
import javafx.scene.control.TabPane;
|
||||
|
||||
/**
|
||||
* A set of constants and utility methods that simplifies adding
|
||||
* CSS classes programmatically.
|
||||
* A set of constants and utility methods that simplifies adding CSS
|
||||
* classes programmatically.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public final class Styles {
|
||||
@ -132,11 +132,11 @@ public final class Styles {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds given style class to the node if it's not present, otherwise
|
||||
* removes it.
|
||||
* Adds the given style class to the node if it's not present,
|
||||
* otherwise removes it.
|
||||
*
|
||||
* @param node the target node
|
||||
* @param styleClass the style class to be toggled
|
||||
* @param node The target node.
|
||||
* @param styleClass The style class to be toggled.
|
||||
* @throws NullPointerException if node or style class is null
|
||||
*/
|
||||
public static void toggleStyleClass(Node node, String styleClass) {
|
||||
@ -156,13 +156,13 @@ public final class Styles {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds given style class to the node and removes the excluded classes.
|
||||
* Adds the given style class to the node and removes the excluded classes.
|
||||
* This method is supposed to be used when only one from a set of classes
|
||||
* have to be present at once.
|
||||
*
|
||||
* @param node the target node
|
||||
* @param styleClass the style class to be toggled
|
||||
* @param excludes the style classes to be excluded
|
||||
* @param node The target node.
|
||||
* @param styleClass The style class to be toggled.
|
||||
* @param excludes The style classes to be excluded.
|
||||
* @throws NullPointerException if node or styleClass is null
|
||||
*/
|
||||
public static void addStyleClass(Node node, String styleClass, String... excludes) {
|
||||
@ -187,9 +187,9 @@ public final class Styles {
|
||||
* This method is supposed to be used when only one from a set of pseudo-classes
|
||||
* have to be present at once.
|
||||
*
|
||||
* @param node the node to activate the pseudo-class on
|
||||
* @param pseudoClass the pseudo-class to be activated
|
||||
* @param excludes the pseudo-classes to be deactivated
|
||||
* @param node The node to activate the pseudo-class on.
|
||||
* @param pseudoClass The pseudo-class to be activated.
|
||||
* @param excludes The pseudo-classes to be deactivated.
|
||||
* @throws NullPointerException if node or pseudo-class is null
|
||||
*/
|
||||
public static void activatePseudoClass(Node node, PseudoClass pseudoClass, PseudoClass... excludes) {
|
||||
@ -213,9 +213,9 @@ public final class Styles {
|
||||
* There's no check for duplicates, so the CSS declarations with the same property
|
||||
* name can be appended multiple times.
|
||||
*
|
||||
* @param node the node to append the new style declaration
|
||||
* @param prop CSS property name
|
||||
* @param value CSS property value
|
||||
* @param node The node to append the new style declaration.
|
||||
* @param prop The CSS property name.
|
||||
* @param value The CSS property value.
|
||||
* @throws NullPointerException if node is null
|
||||
*/
|
||||
public static void appendStyle(Node node, String prop, String value) {
|
||||
@ -239,8 +239,8 @@ public final class Styles {
|
||||
/**
|
||||
* Removes the specified CSS style declaration from the specified node.
|
||||
*
|
||||
* @param node the node to remove the style from
|
||||
* @param prop the name of the style property to remove
|
||||
* @param node The node to remove the style from.
|
||||
* @param prop The name of the style property to remove.
|
||||
* @throws NullPointerException if node is null
|
||||
*/
|
||||
@SuppressWarnings("StringSplitter")
|
||||
@ -284,8 +284,8 @@ public final class Styles {
|
||||
* node.getStylesheets().remove(dataUri);
|
||||
* </pre>
|
||||
*
|
||||
* @param css the CSS string to encode
|
||||
* @return the resulting data URI string
|
||||
* @param css The CSS string to encode.
|
||||
* @return The resulting data URI string.
|
||||
*/
|
||||
public static String toDataURI(String css) {
|
||||
if (css == null) {
|
||||
|
@ -9,7 +9,7 @@ import javafx.application.Application;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Basic theme interface.
|
||||
* The basic theme interface.
|
||||
*/
|
||||
public interface Theme {
|
||||
|
||||
@ -39,7 +39,7 @@ public interface Theme {
|
||||
boolean isDarkMode();
|
||||
|
||||
/**
|
||||
* Simple factory method for instantiating a new theme.
|
||||
* A simple factory method for instantiating a new theme.
|
||||
*/
|
||||
static Theme of(final String name, final String userAgentStylesheet, final boolean darkMode) {
|
||||
if (name == null) {
|
||||
|
@ -11,10 +11,21 @@ import java.util.stream.Stream;
|
||||
import javafx.css.Stylesheet;
|
||||
|
||||
/**
|
||||
* Lazy man CSS to BSS compiler wrapper.
|
||||
* A lazy man CSS to BSS compiler wrapper.
|
||||
*/
|
||||
public class ThemeCompiler {
|
||||
|
||||
/**
|
||||
* The main class that accepts exactly one parameter, which is the path to
|
||||
* the source directory to be scanned for CSS files.
|
||||
*
|
||||
* <p>Usage:
|
||||
* <pre>{@code
|
||||
* java ThemeCompiler <path>
|
||||
* }</pre>
|
||||
*
|
||||
* @see #convertToBinary(Path)
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
if (args.length < 1) {
|
||||
@ -38,7 +49,7 @@ public class ThemeCompiler {
|
||||
/**
|
||||
* Converts all CSS files in the specified directory to BSS.
|
||||
*
|
||||
* @param dir the source directory to scan for CSS files
|
||||
* @param dir The source directory to scan for CSS files.
|
||||
* @throws IOException to punish you for using Java
|
||||
*/
|
||||
public void convertToBinary(Path dir) throws IOException {
|
||||
@ -62,8 +73,8 @@ public class ThemeCompiler {
|
||||
* Converts the specified CSS file to BSS. If no output file is given,
|
||||
* then the input file name is used with an extension of 'bss'.
|
||||
*
|
||||
* @param in input file path
|
||||
* @param out output file path
|
||||
* @param in The input file path.
|
||||
* @param out The output file path.
|
||||
* @throws IOException to punish you for using Java
|
||||
*/
|
||||
public void convertToBinary(Path in, Path out) throws IOException {
|
||||
|
@ -3,9 +3,9 @@
|
||||
package atlantafx.base.theme;
|
||||
|
||||
/**
|
||||
* Contains extra style class names introduced to tweak some controls view if and where it makes sense.
|
||||
* The reason of supporting tweaks is to allow users to write less CSS code. Search for #tweak/classname
|
||||
* to find the controls supporting tweaks or check the control page in the Sampler app.
|
||||
* Contains extra style class names introduced to tweak some controls view
|
||||
* if and where it makes sense. The reason of supporting tweaks is to allow
|
||||
* users to write less CSS code.
|
||||
*/
|
||||
public final class Tweaks {
|
||||
|
||||
|
@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Contains provided themes and style constants.
|
||||
*/
|
||||
|
||||
package atlantafx.base.theme;
|
@ -38,7 +38,7 @@ public final class Animations {
|
||||
* Changes the node opacity to full transparency and then back to its
|
||||
* original opacity in quick succession, creating a flashing effect.
|
||||
*
|
||||
* @param node the node to be animated
|
||||
* @param node The node to be animated.
|
||||
*/
|
||||
public static Timeline flash(Node node) {
|
||||
Objects.requireNonNull(node, "Node cannot be null!");
|
||||
@ -81,8 +81,8 @@ public final class Animations {
|
||||
* Repeatedly increases and decreases the scale of the node,
|
||||
* giving it a pulsating effect that draws attention to it.
|
||||
*
|
||||
* @param node the node to be animated
|
||||
* @param scale the scale factor
|
||||
* @param node The node to be animated.
|
||||
* @param scale The scale factor.
|
||||
*/
|
||||
public static Timeline pulse(Node node, double scale) {
|
||||
Objects.requireNonNull(node, "Node cannot be null!");
|
||||
@ -127,8 +127,8 @@ public final class Animations {
|
||||
* Rapidly moves the node from side-to-side horizontally,
|
||||
* creating a shaking or vibrating effect.
|
||||
*
|
||||
* @param node the node to be animated
|
||||
* @param offset the shake offset
|
||||
* @param node The node to be animated.
|
||||
* @param offset The shake offset.
|
||||
*/
|
||||
public static Timeline shakeX(Node node, double offset) {
|
||||
Objects.requireNonNull(node, "Node cannot be null!");
|
||||
@ -186,8 +186,8 @@ public final class Animations {
|
||||
* Rapidly moves the node up and down vertically, creating
|
||||
* a shaking or bouncing effect.
|
||||
*
|
||||
* @param node the node to be animated
|
||||
* @param offset the shake offset
|
||||
* @param node The node to be animated.
|
||||
* @param offset The shake offset.
|
||||
*/
|
||||
public static Timeline shakeY(Node node, double offset) {
|
||||
Objects.requireNonNull(node, "Node cannot be null!");
|
||||
@ -241,7 +241,7 @@ public final class Animations {
|
||||
* Causes the node to rapidly wobble back and forth,
|
||||
* creating a visually engaging effect.
|
||||
*
|
||||
* @param node the node to be animated
|
||||
* @param node The node to be animated.
|
||||
*/
|
||||
public static Timeline wobble(Node node) {
|
||||
Objects.requireNonNull(node, "Node cannot be null!");
|
||||
@ -295,8 +295,8 @@ public final class Animations {
|
||||
* Gradually increases the opacity of the node from 0 to 1,
|
||||
* making it appear on the scene with a fading-in effect.
|
||||
*
|
||||
* @param node the node to be animated
|
||||
* @param duration the animation duration
|
||||
* @param node The node to be animated.
|
||||
* @param duration The animation duration.
|
||||
*/
|
||||
public static Timeline fadeIn(Node node, Duration duration) {
|
||||
Objects.requireNonNull(node, "Node cannot be null!");
|
||||
@ -324,8 +324,8 @@ public final class Animations {
|
||||
* Gradually decreases the opacity of the node from 1 to 0,
|
||||
* making it disappear from the scene with a fading-out effect.
|
||||
*
|
||||
* @param node the node to be animated
|
||||
* @param duration the animation duration
|
||||
* @param node The node to be animated.
|
||||
* @param duration The animation duration.
|
||||
*/
|
||||
public static Timeline fadeOut(Node node, Duration duration) {
|
||||
Objects.requireNonNull(node, "Node cannot be null!");
|
||||
@ -353,8 +353,8 @@ public final class Animations {
|
||||
* Combines the {@link #fadeIn(Node, Duration)} effect with the node’s downward
|
||||
* movement, creating an animated entrance of the node from the top.
|
||||
*
|
||||
* @param node the node to be animated
|
||||
* @param duration the animation duration
|
||||
* @param node The node to be animated.
|
||||
* @param duration The animation duration.
|
||||
*/
|
||||
public static Timeline fadeInDown(Node node, Duration duration) {
|
||||
Objects.requireNonNull(node, "Node cannot be null!");
|
||||
@ -386,8 +386,8 @@ public final class Animations {
|
||||
* Combines the {@link #fadeOut(Node, Duration)} effect with the node’s downward
|
||||
* movement, creating an animated exit of the node to the bottom.
|
||||
*
|
||||
* @param node the node to be animated
|
||||
* @param duration the animation duration
|
||||
* @param node The node to be animated.
|
||||
* @param duration The animation duration.
|
||||
*/
|
||||
public static Timeline fadeOutDown(Node node, Duration duration) {
|
||||
Objects.requireNonNull(node, "Node cannot be null!");
|
||||
@ -418,8 +418,8 @@ public final class Animations {
|
||||
* Combines the {@link #fadeIn(Node, Duration)} effect with the node’s leftward
|
||||
* movement, creating an animated entrance of the node from the left.
|
||||
*
|
||||
* @param node the node to be animated
|
||||
* @param duration the animation duration
|
||||
* @param node The node to be animated.
|
||||
* @param duration The animation duration.
|
||||
*/
|
||||
public static Timeline fadeInLeft(Node node, Duration duration) {
|
||||
Objects.requireNonNull(node, "Node cannot be null!");
|
||||
@ -450,8 +450,8 @@ public final class Animations {
|
||||
* Combines the {@link #fadeOut(Node, Duration)} effect with the node’s leftward
|
||||
* movement, creating an animated exit of the node to the left.
|
||||
*
|
||||
* @param node the node to be animated
|
||||
* @param duration the animation duration
|
||||
* @param node The node to be animated.
|
||||
* @param duration The animation duration.
|
||||
*/
|
||||
public static Timeline fadeOutLeft(Node node, Duration duration) {
|
||||
Objects.requireNonNull(node, "Node cannot be null!");
|
||||
@ -482,8 +482,8 @@ public final class Animations {
|
||||
* Combines the {@link #fadeIn(Node, Duration)} effect with the node’s rightward
|
||||
* movement, creating an animated entrance of the node from the right.
|
||||
*
|
||||
* @param node the node to be animated
|
||||
* @param duration the animation duration
|
||||
* @param node The node to be animated.
|
||||
* @param duration The animation duration.
|
||||
*/
|
||||
public static Timeline fadeInRight(Node node, Duration duration) {
|
||||
Objects.requireNonNull(node, "Node cannot be null!");
|
||||
@ -514,8 +514,8 @@ public final class Animations {
|
||||
* Combines the {@link #fadeOut(Node, Duration)} effect with the node’s rightward
|
||||
* movement, creating an animated exit of the node to the right.
|
||||
*
|
||||
* @param node the node to be animated
|
||||
* @param duration the animation duration
|
||||
* @param node The node to be animated.
|
||||
* @param duration The animation duration.
|
||||
*/
|
||||
public static Timeline fadeOutRight(Node node, Duration duration) {
|
||||
Objects.requireNonNull(node, "Node cannot be null!");
|
||||
@ -546,8 +546,8 @@ public final class Animations {
|
||||
* Combines the {@link #fadeIn(Node, Duration)} effect with the node’s upward
|
||||
* movement, creating an animated entrance of the node from the bottom.
|
||||
*
|
||||
* @param node the node to be animated
|
||||
* @param duration the animation duration
|
||||
* @param node The node to be animated.
|
||||
* @param duration The animation duration.
|
||||
*/
|
||||
public static Timeline fadeInUp(Node node, Duration duration) {
|
||||
Objects.requireNonNull(node, "Node cannot be null!");
|
||||
@ -578,8 +578,8 @@ public final class Animations {
|
||||
* Combines the {@link #fadeOut(Node, Duration)} effect with the node’s upward
|
||||
* movement, creating an animated exit of the node to the top.
|
||||
*
|
||||
* @param node the node to be animated
|
||||
* @param duration the animation duration
|
||||
* @param node The node to be animated.
|
||||
* @param duration The animation duration.
|
||||
*/
|
||||
public static Timeline fadeOutUp(Node node, Duration duration) {
|
||||
Objects.requireNonNull(node, "Node cannot be null!");
|
||||
@ -614,8 +614,8 @@ public final class Animations {
|
||||
* Applies an animated effect to the node causing it to roll into
|
||||
* the scene from the left side at an angle.
|
||||
*
|
||||
* @param node the node to be animated
|
||||
* @param duration the animation duration
|
||||
* @param node The node to be animated.
|
||||
* @param duration The animation duration.
|
||||
*/
|
||||
public static Timeline rollIn(Node node, Duration duration) {
|
||||
Objects.requireNonNull(node, "Node cannot be null!");
|
||||
@ -649,8 +649,8 @@ public final class Animations {
|
||||
* Applies an animated effect to the node causing it to roll out
|
||||
* from the scene to the right side at an angle.
|
||||
*
|
||||
* @param node the node to be animated
|
||||
* @param duration the animation duration
|
||||
* @param node The node to be animated.
|
||||
* @param duration The animation duration.
|
||||
*/
|
||||
public static Timeline rollOut(Node node, Duration duration) {
|
||||
Objects.requireNonNull(node, "Node cannot be null!");
|
||||
@ -688,8 +688,8 @@ public final class Animations {
|
||||
* Rotates the node and gradually increases its opacity,
|
||||
* giving it an animated entrance effect.
|
||||
*
|
||||
* @param node the node to be animated
|
||||
* @param duration the animation duration
|
||||
* @param node The node to be animated.
|
||||
* @param duration The animation duration.
|
||||
*/
|
||||
public static Timeline rotateIn(Node node, Duration duration) {
|
||||
Objects.requireNonNull(node, "Node cannot be null!");
|
||||
@ -722,8 +722,8 @@ public final class Animations {
|
||||
* Rotates the node and gradually decreases its opacity,
|
||||
* giving it an animated exit effect.
|
||||
*
|
||||
* @param node the node to be animated
|
||||
* @param duration the animation duration
|
||||
* @param node The node to be animated.
|
||||
* @param duration The animation duration.
|
||||
*/
|
||||
public static Timeline rotateOut(Node node, Duration duration) {
|
||||
Objects.requireNonNull(node, "Node cannot be null!");
|
||||
@ -757,8 +757,8 @@ public final class Animations {
|
||||
* movement from the left, creating an animated entrance of the node from the top
|
||||
* left corner.
|
||||
*
|
||||
* @param node the node to be animated
|
||||
* @param duration the animation duration
|
||||
* @param node The node to be animated.
|
||||
* @param duration The animation duration.
|
||||
*/
|
||||
public static Timeline rotateInDownLeft(Node node, Duration duration) {
|
||||
Objects.requireNonNull(node, "Node cannot be null!");
|
||||
@ -794,8 +794,8 @@ public final class Animations {
|
||||
* movement to the left, creating an animated exit of the node towards the bottom
|
||||
* left corner.
|
||||
*
|
||||
* @param node the node to be animated
|
||||
* @param duration the animation duration
|
||||
* @param node The node to be animated.
|
||||
* @param duration The animation duration.
|
||||
*/
|
||||
public static Timeline rotateOutDownLeft(Node node, Duration duration) {
|
||||
Objects.requireNonNull(node, "Node cannot be null!");
|
||||
@ -831,8 +831,8 @@ public final class Animations {
|
||||
* movement from the right, creating an animated entrance of the node from the top
|
||||
* right corner.
|
||||
*
|
||||
* @param node the node to be animated
|
||||
* @param duration the animation duration
|
||||
* @param node The node to be animated.
|
||||
* @param duration The animation duration.
|
||||
*/
|
||||
public static Timeline rotateInDownRight(Node node, Duration duration) {
|
||||
Objects.requireNonNull(node, "Node cannot be null!");
|
||||
@ -871,8 +871,8 @@ public final class Animations {
|
||||
* movement to the right, creating an animated exit of the node towards the bottom
|
||||
* right corner.
|
||||
*
|
||||
* @param node the node to be animated
|
||||
* @param duration the animation duration
|
||||
* @param node The node to be animated.
|
||||
* @param duration The animation duration.
|
||||
*/
|
||||
public static Timeline rotateOutDownRight(Node node, Duration duration) {
|
||||
Objects.requireNonNull(node, "Node cannot be null!");
|
||||
@ -911,8 +911,8 @@ public final class Animations {
|
||||
* movement from the left, creating an animated entrance of the node from the
|
||||
* bottom left corner.
|
||||
*
|
||||
* @param node the node to be animated
|
||||
* @param duration the animation duration
|
||||
* @param node The node to be animated.
|
||||
* @param duration The animation duration.
|
||||
*/
|
||||
public static Timeline rotateInUpLeft(Node node, Duration duration) {
|
||||
Objects.requireNonNull(node, "Node cannot be null!");
|
||||
@ -948,8 +948,8 @@ public final class Animations {
|
||||
* movement to the left, creating an animated exit of the node towards the top
|
||||
* left corner.
|
||||
*
|
||||
* @param node the node to be animated
|
||||
* @param duration the animation duration
|
||||
* @param node The node to be animated.
|
||||
* @param duration The animation duration.
|
||||
*/
|
||||
public static Timeline rotateOutUpLeft(Node node, Duration duration) {
|
||||
Objects.requireNonNull(node, "Node cannot be null!");
|
||||
@ -985,8 +985,8 @@ public final class Animations {
|
||||
* movement from the right, creating an animated entrance of the node from the
|
||||
* bottom right corner.
|
||||
*
|
||||
* @param node the node to be animated
|
||||
* @param duration the animation duration
|
||||
* @param node The node to be animated.
|
||||
* @param duration The animation duration.
|
||||
*/
|
||||
public static Timeline rotateInUpRight(Node node, Duration duration) {
|
||||
Objects.requireNonNull(node, "Node cannot be null!");
|
||||
@ -1025,8 +1025,8 @@ public final class Animations {
|
||||
* movement to the right, creating an animated exit of the node towards the top
|
||||
* right corner.
|
||||
*
|
||||
* @param node the node to be animated
|
||||
* @param duration the animation duration
|
||||
* @param node The node to be animated.
|
||||
* @param duration The animation duration.
|
||||
*/
|
||||
public static Timeline rotateOutUpRight(Node node, Duration duration) {
|
||||
Objects.requireNonNull(node, "Node cannot be null!");
|
||||
@ -1068,8 +1068,8 @@ public final class Animations {
|
||||
* Applies an animated effect to the node, causing it to slide into view
|
||||
* from the top side.
|
||||
*
|
||||
* @param node the node to be animated
|
||||
* @param duration the animation duration
|
||||
* @param node The node to be animated.
|
||||
* @param duration The animation duration.
|
||||
*/
|
||||
public static Timeline slideInDown(Node node, Duration duration) {
|
||||
Objects.requireNonNull(node, "Node cannot be null!");
|
||||
@ -1097,8 +1097,8 @@ public final class Animations {
|
||||
* Applies an animated effect to the node, causing it to slide out of view
|
||||
* through the bottom side.
|
||||
*
|
||||
* @param node the node to be animated
|
||||
* @param duration the animation duration
|
||||
* @param node The node to be animated.
|
||||
* @param duration The animation duration.
|
||||
*/
|
||||
public static Timeline slideOutDown(Node node, Duration duration) {
|
||||
Objects.requireNonNull(node, "Node cannot be null!");
|
||||
@ -1126,8 +1126,8 @@ public final class Animations {
|
||||
* Applies an animated effect to the node, causing it to slide into view
|
||||
* from the left side.
|
||||
*
|
||||
* @param node the node to be animated
|
||||
* @param duration the animation duration
|
||||
* @param node The node to be animated.
|
||||
* @param duration The animation duration.
|
||||
*/
|
||||
public static Timeline slideInLeft(Node node, Duration duration) {
|
||||
Objects.requireNonNull(node, "Node cannot be null!");
|
||||
@ -1155,8 +1155,8 @@ public final class Animations {
|
||||
* Applies an animated effect to the node, causing it to slide out of view
|
||||
* through the left side.
|
||||
*
|
||||
* @param node the node to be animated
|
||||
* @param duration the animation duration
|
||||
* @param node The node to be animated.
|
||||
* @param duration The animation duration.
|
||||
*/
|
||||
public static Timeline slideOutLeft(Node node, Duration duration) {
|
||||
Objects.requireNonNull(node, "Node cannot be null!");
|
||||
@ -1184,8 +1184,8 @@ public final class Animations {
|
||||
* Applies an animated effect to the node, causing it to slide into view
|
||||
* from the right side.
|
||||
*
|
||||
* @param node the node to be animated
|
||||
* @param duration the animation duration
|
||||
* @param node The node to be animated.
|
||||
* @param duration The animation duration.
|
||||
*/
|
||||
public static Timeline slideInRight(Node node, Duration duration) {
|
||||
Objects.requireNonNull(node, "Node cannot be null!");
|
||||
@ -1213,8 +1213,8 @@ public final class Animations {
|
||||
* Applies an animated effect to the node, causing it to slide out of view
|
||||
* through the right side.
|
||||
*
|
||||
* @param node the node to be animated
|
||||
* @param duration the animation duration
|
||||
* @param node The node to be animated.
|
||||
* @param duration The animation duration.
|
||||
*/
|
||||
public static Timeline slideOutRight(Node node, Duration duration) {
|
||||
Objects.requireNonNull(node, "Node cannot be null!");
|
||||
@ -1242,8 +1242,8 @@ public final class Animations {
|
||||
* Applies an animated effect to the node, causing it to slide into view
|
||||
* from the bottom side.
|
||||
*
|
||||
* @param node the node to be animated
|
||||
* @param duration the animation duration
|
||||
* @param node The node to be animated.
|
||||
* @param duration The animation duration.
|
||||
*/
|
||||
public static Timeline slideInUp(Node node, Duration duration) {
|
||||
Objects.requireNonNull(node, "Node cannot be null!");
|
||||
@ -1271,8 +1271,8 @@ public final class Animations {
|
||||
* Applies an animated effect to the node, causing it to slide out of view
|
||||
* through the top side.
|
||||
*
|
||||
* @param node the node to be animated
|
||||
* @param duration the animation duration
|
||||
* @param node The node to be animated.
|
||||
* @param duration The animation duration.
|
||||
*/
|
||||
public static Timeline slideOutUp(Node node, Duration duration) {
|
||||
Objects.requireNonNull(node, "Node cannot be null!");
|
||||
@ -1311,9 +1311,9 @@ public final class Animations {
|
||||
* Increases the scale of the node, starting from a smaller size and gradually
|
||||
* zooming it to the regular size, emphasizing the node’s entrance.
|
||||
*
|
||||
* @param node the node to be animated
|
||||
* @param duration the animation duration
|
||||
* @param startValue the initial zoom value
|
||||
* @param node The node to be animated.
|
||||
* @param duration The animation duration.
|
||||
* @param startValue The initial zoom value.
|
||||
*/
|
||||
public static Timeline zoomIn(Node node, Duration duration, double startValue) {
|
||||
Objects.requireNonNull(node, "Node cannot be null!");
|
||||
@ -1355,9 +1355,9 @@ public final class Animations {
|
||||
* its original size and gradually zooms out to a smaller size, emphasizing
|
||||
* the node’s exit.
|
||||
*
|
||||
* @param node the node to be animated
|
||||
* @param duration the animation duration
|
||||
* @param endValue the target zoom value
|
||||
* @param node The node to be animated.
|
||||
* @param duration The animation duration.
|
||||
* @param endValue The target zoom value.
|
||||
*/
|
||||
public static Timeline zoomOut(Node node, Duration duration, double endValue) {
|
||||
Objects.requireNonNull(node, "Node cannot be null!");
|
||||
|
@ -36,7 +36,7 @@ import javafx.scene.text.TextFlow;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Basic handler interface for the {@link BBCodeParser} that will
|
||||
* The basic handler interface for the {@link BBCodeParser} that will
|
||||
* receive notifications while processing user input text.
|
||||
*/
|
||||
public interface BBCodeHandler {
|
||||
@ -57,10 +57,10 @@ public interface BBCodeHandler {
|
||||
* Notifies about the start of the tag.
|
||||
* In case of self-closing tag this also notifies about the end of the tag.
|
||||
*
|
||||
* @param name tag name
|
||||
* @param params tag params
|
||||
* @param start tag start position, i.e. the position of open square bracket (not the tag name start)
|
||||
* @param length tag length, including closing bracket
|
||||
* @param name The tag name.
|
||||
* @param params The tag params.
|
||||
* @param start The tag start position, i.e. the position of open square bracket (not the tag name start).
|
||||
* @param length The tag length, including closing bracket.
|
||||
*/
|
||||
void startTag(String name, @Nullable Map<String, String> params, int start, int length);
|
||||
|
||||
@ -68,9 +68,9 @@ public interface BBCodeHandler {
|
||||
* Notifies about the end of the tag.
|
||||
* In case of self-closing tag only {@link #startTag(String, Map, int, int)} method is called.
|
||||
*
|
||||
* @param name tag name
|
||||
* @param start tag start position, i.e. the position of open square bracket (not the tag name start)
|
||||
* @param length tag length, including closing bracket
|
||||
* @param name The tag name.
|
||||
* @param start The tag start position, i.e. the position of open square bracket (not the tag name start).
|
||||
* @param length The tag length, including closing bracket.
|
||||
*/
|
||||
void endTag(String name, int start, int length);
|
||||
|
||||
@ -78,8 +78,8 @@ public interface BBCodeHandler {
|
||||
* Notifies about characters data that doesn't belong to any tag, i.e.
|
||||
* leading, intermediate or trailing text.
|
||||
*
|
||||
* @param start text start position
|
||||
* @param length text length
|
||||
* @param start The text start position.
|
||||
* @param length The text length.
|
||||
*/
|
||||
void characters(int start, int length);
|
||||
|
||||
@ -89,9 +89,9 @@ public interface BBCodeHandler {
|
||||
* A basic {@link BBCodeHandler} implementation.<br/><br/>
|
||||
*
|
||||
* <p>While parsing all created nodes will be added to the given root container.
|
||||
* The choice depends on the actual markup. Default constructor accepts any {@link Pane}
|
||||
* or its descendant. Using {@link TextFlow} for text-only markup (no block nodes) and
|
||||
* {@link VBox} otherwise, is recommended.<br/><br/>
|
||||
* The container choice depends on the actual markup. Default constructor accepts any
|
||||
* {@link Pane} or its descendant. Using the{@link TextFlow} for text-only markup
|
||||
* (no block nodes) and {@link VBox} otherwise, is recommended.<br/><br/>
|
||||
*
|
||||
* <h3>Supported tags</h3><br/>
|
||||
* <pre>
|
||||
@ -149,16 +149,17 @@ public interface BBCodeHandler {
|
||||
* </pre>
|
||||
*
|
||||
* <ul>
|
||||
* <li>If tag param contains whitespaces or trailing slash is must be
|
||||
* <li>If a tag param contains whitespaces or trailing slash is must be
|
||||
* enclosed in double or single quotes.
|
||||
* <li>If tag only has a single param, it can be shortened to {@code [name=value]{text}[/name]}.
|
||||
* In that case tag param name considered to be equal to the tag name.
|
||||
* <li>If a tag only has a single param, it can be shortened to the
|
||||
* {@code [name=value]{text}[/name]}. In this case the tag param name
|
||||
* considered to be equal to the tag name.
|
||||
* <li>Unknown tag params will be ignored.
|
||||
* </ul>
|
||||
*
|
||||
* <h3>Action Events</h3><br/>
|
||||
* Some nodes, e.g. {@link Hyperlink} require action handlers. To avoid traversing
|
||||
* the root node graph you can add an event filter.
|
||||
* the root container's node graph you can add an event filter.
|
||||
*
|
||||
* <pre>{@code
|
||||
* var input = "Visit the [url=https://example.com]website[/url].";
|
||||
@ -672,10 +673,10 @@ public interface BBCodeHandler {
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic block record.
|
||||
* A generic block record.
|
||||
*
|
||||
* @param node the node that represents the block
|
||||
* @param text text content
|
||||
* @param node The node that represents the block.
|
||||
* @param text The text content.
|
||||
*/
|
||||
record Block(Pane node, @Nullable TextFlow text) {
|
||||
|
||||
@ -712,10 +713,12 @@ public interface BBCodeHandler {
|
||||
/**
|
||||
* Generic tag record.
|
||||
*
|
||||
* @param name tag name
|
||||
* @param params tag params
|
||||
* @param styleClasses CSS classes, each element is either a single style or space delimited string
|
||||
* @param styles CSS styles, each element is either a single style or semicolon delimited string
|
||||
* @param name The tag name.
|
||||
* @param params The tag params.
|
||||
* @param styleClasses The CSS classes.
|
||||
* Each element is either a single style or space delimited string.
|
||||
* @param styles The CSS styles.
|
||||
* Each element is either a single style or semicolon delimited string.
|
||||
*/
|
||||
record Tag(String name,
|
||||
Type type,
|
||||
|
@ -22,10 +22,11 @@ import org.jetbrains.annotations.Nullable;
|
||||
*
|
||||
* <p>The parser doesn't impose restrictions on tag names or tag params.
|
||||
* It's a handler implementation responsibility to differentiate supported
|
||||
* tags from unsupported and so to for tag params. This allows user to utilize
|
||||
* tags from unsupported and so to for the tag params. This allows user to utilize
|
||||
* arbitrary tags or params without changing the parser behaviour. The parser,
|
||||
* however, verifies that each opening tag has the matching closing tag.
|
||||
* If parsing is failed due to invalid input an {@link IllegalStateException}
|
||||
*
|
||||
* <p>If parsing is failed due to invalid input an {@link IllegalStateException}
|
||||
* will be thrown.
|
||||
*/
|
||||
public class BBCodeParser {
|
||||
@ -53,7 +54,9 @@ public class BBCodeParser {
|
||||
private int lastClosingPos = 0;
|
||||
|
||||
/**
|
||||
* See {@link #BBCodeParser(String, BBCodeHandler, Set)}.
|
||||
* Creates a new parser.
|
||||
*
|
||||
* @see #BBCodeParser(String, BBCodeHandler, Set).
|
||||
*/
|
||||
public BBCodeParser(String input, BBCodeHandler handler) {
|
||||
this(input, handler, RESERVED_TAGS);
|
||||
@ -62,9 +65,9 @@ public class BBCodeParser {
|
||||
/**
|
||||
* Creates a new parser.
|
||||
*
|
||||
* @param input an input non-null string
|
||||
* @param handler a {@link BBCodeHandler} implementation
|
||||
* @param tags the list of processed tags, i.e. the tags that parser won't ignore
|
||||
* @param input An input non-null string.
|
||||
* @param handler A {@link BBCodeHandler} implementation.
|
||||
* @param tags The list of processed tags, i.e. the tags that parser won't ignore.
|
||||
*/
|
||||
public BBCodeParser(String input, BBCodeHandler handler, @Nullable Set<String> tags) {
|
||||
this.input = Objects.requireNonNull(input, "Input can't be null.");
|
||||
@ -73,8 +76,8 @@ public class BBCodeParser {
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts input parsing. There's no way to stop the process until
|
||||
* parsing is finished.
|
||||
* Starts input parsing.
|
||||
* There's no way to stop the process until parsing is finished.
|
||||
*/
|
||||
public void parse() {
|
||||
handler.startDocument(input.toCharArray());
|
||||
@ -175,8 +178,9 @@ public class BBCodeParser {
|
||||
* Parses the given string using BBCode markup and returns corresponding layout.
|
||||
* This is a shorthand method for using the feature.
|
||||
*
|
||||
* @param input BBCode markup string
|
||||
* @param container root container
|
||||
* @param input The BBCode markup string.
|
||||
* @param container The root container.
|
||||
* @see BBCodeHandler
|
||||
*/
|
||||
public static <T extends Pane> T createLayout(String input, T container) {
|
||||
var handler = new BBCodeHandler.Default<>(container);
|
||||
|
@ -13,16 +13,16 @@ import javafx.scene.control.Tooltip;
|
||||
import javafx.util.StringConverter;
|
||||
|
||||
/**
|
||||
* Converts between user-edited strings and {@link Double} values.
|
||||
* Accepts an optional {@link Runnable} that resets the editor on {@link NumberFormatException},
|
||||
* or a {@link TextField} or {@link Spinner} that is preemptively monitored for invalid
|
||||
* input during typing, and restricts valid input to a specified range when committed.
|
||||
* <p>
|
||||
* This implementation shows up to two decimal digits, but only if a fractional part exists.
|
||||
* The default implementation always shows one decimal digit which hinders typing.</p>
|
||||
* Converts between user-edited strings and Double values.
|
||||
*
|
||||
* <p>Accepts an optional Runnable that resets the editor on {@code NumberFormatException},
|
||||
* or a TextField or Spinner that is preemptively monitored for invalid input
|
||||
* during typing, and restricts valid input to a specified range when committed.
|
||||
*
|
||||
* <p>This implementation shows up to two decimal digits, but only if a fractional part
|
||||
* exists. The default implementation always shows one decimal digit which hinders typing.
|
||||
*
|
||||
* @author Christoph Nahr
|
||||
* @version 1.0.2
|
||||
*/
|
||||
public class DoubleStringConverter extends StringConverter<Double> {
|
||||
|
||||
@ -30,8 +30,9 @@ public class DoubleStringConverter extends StringConverter<Double> {
|
||||
private Runnable reset;
|
||||
|
||||
/**
|
||||
* Creates a {@link DoubleStringConverter}.
|
||||
* Swallows {@link NumberFormatException} but does nothing
|
||||
* Creates a DoubleStringConverter.
|
||||
*
|
||||
* <p>Swallows {@code NumberFormatException} but does nothing
|
||||
* in response until {@link #setReset} is defined.
|
||||
*/
|
||||
public DoubleStringConverter() {
|
||||
@ -39,26 +40,27 @@ public class DoubleStringConverter extends StringConverter<Double> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link DoubleStringConverter} with an editor reset callback.
|
||||
* Specifying {@code null} has the same effect as the default constructor.
|
||||
* Creates a DoubleStringConverter with an editor reset callback.
|
||||
* Specifying null has the same effect as the default constructor.
|
||||
*
|
||||
* @param reset the {@link Runnable} to call upon {@link NumberFormatException}
|
||||
* @param reset the Runnable to call upon {@code NumberFormatException}
|
||||
*/
|
||||
public DoubleStringConverter(Runnable reset) {
|
||||
this.reset = reset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link DoubleStringConverter} with the specified input range.
|
||||
* Preemptively monitors {@code input} to reject any invalid characters during
|
||||
* typing, restricts {@code input} to [{@code min}, {@code max}] (inclusive) when
|
||||
* valid text is committed, and resets {@code input} to the closest value to zero
|
||||
* Creates a DoubleStringConverter with the specified input range.
|
||||
*
|
||||
* <p>Preemptively monitors input to reject any invalid characters during
|
||||
* typing. Restricts input to [{@code min}, {@code max}] (inclusive) when
|
||||
* valid text is committed, and resets input to the closest value to zero
|
||||
* within [{@code min}, {@code max}] when invalid text is committed.
|
||||
*
|
||||
* @param input the {@link TextField} providing user-edited strings
|
||||
* @param min the smallest valid {@link Double} value
|
||||
* @param max the greatest valid {@link Double} value
|
||||
* @throws NullPointerException if {@code input} is {@code null}
|
||||
* @param input The TextField providing user-edited strings.
|
||||
* @param min The smallest valid value.
|
||||
* @param max The greatest valid value.
|
||||
* @throws NullPointerException if input is {@code null}.
|
||||
*/
|
||||
public DoubleStringConverter(TextField input, double min, double max) {
|
||||
if (input == null) {
|
||||
@ -68,11 +70,6 @@ public class DoubleStringConverter extends StringConverter<Double> {
|
||||
final double resetValue = Math.min(Math.max(0, min), max);
|
||||
reset = () -> input.setText(decimalFormat.format(resetValue));
|
||||
|
||||
// bound JavaFX properties cannot be explicitly set
|
||||
// if (!input.tooltipProperty().isBound()) {
|
||||
// input.setTooltip(new Tooltip(String.format("Enter a value between %.2f and %.2f", min, max)));
|
||||
// }
|
||||
|
||||
// restrict direct input to valid numerical characters
|
||||
input.textProperty().addListener((ov, oldValue, newValue) -> {
|
||||
if (newValue == null || newValue.isEmpty()) {
|
||||
@ -115,14 +112,15 @@ public class DoubleStringConverter extends StringConverter<Double> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link DoubleStringConverter} for the specified {@link Spinner}.
|
||||
* Uses the {@link TextField} and minimum and maximum values of the specified
|
||||
* {@link Spinner} for construction, and also sets the new {@link DoubleStringConverter}
|
||||
* Creates a DoubleStringConverter for the specified Spinner.
|
||||
*
|
||||
* <p>Uses the TextField and minimum and maximum values of the specified
|
||||
* Spinner for construction, and also sets the new DoubleStringConverter
|
||||
* on its {@link SpinnerValueFactory.DoubleSpinnerValueFactory}.
|
||||
*
|
||||
* @param spinner the {@link Spinner} to create a {@link DoubleStringConverter} for
|
||||
* @return the new {@link DoubleStringConverter}
|
||||
* @throws NullPointerException if {@code spinner} is {@code null}
|
||||
* @param spinner The Spinner to create a DoubleStringConverter for.
|
||||
* @return the new DoubleStringConverter
|
||||
* @throws NullPointerException if the Spinner is {@code null}
|
||||
*/
|
||||
public static DoubleStringConverter createFor(Spinner<Double> spinner) {
|
||||
final SpinnerValueFactory.DoubleSpinnerValueFactory factory =
|
||||
@ -141,13 +139,14 @@ public class DoubleStringConverter extends StringConverter<Double> {
|
||||
|
||||
/**
|
||||
* Sets the editor reset callback.
|
||||
* Specify {@code null} to clear a previously set {@link Runnable}. When creating
|
||||
* a {@link DoubleStringConverter} for a {@link TextField} or {@link Spinner},
|
||||
* this callback is automatically defined to reset committed invalid input to the
|
||||
* closest value to zero within the legal range. Setting a different callback
|
||||
* will overwrite this functionality.
|
||||
*
|
||||
* @param reset the {@link Runnable} to call upon {@link NumberFormatException}
|
||||
* <p>Specify {@code null} to clear a previously set Runnable. When creating
|
||||
* a DoubleStringConverter for a TextField or Spinner, this callback is
|
||||
* automatically defined to reset committed invalid input to the closest value
|
||||
* to zero within the legal range. Setting a different callback will overwrite this
|
||||
* functionality.
|
||||
*
|
||||
* @param reset The Runnable to call upon NumberFormatException.
|
||||
* @see #fromString
|
||||
*/
|
||||
public void setReset(Runnable reset) {
|
||||
@ -155,12 +154,12 @@ public class DoubleStringConverter extends StringConverter<Double> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the specified {@link String} into its {@link Double} value.
|
||||
* Converts the specified string into its double value.
|
||||
* A {@code null}, empty, or otherwise invalid argument returns zero
|
||||
* and also executes the editor reset callback, if any.
|
||||
*
|
||||
* @param s the {@link String} to convert
|
||||
* @return the {@link Double} value of {@code s}
|
||||
* @param s The string to convert.
|
||||
* @return the double value of {@code s}
|
||||
* @see #setReset
|
||||
*/
|
||||
@Override
|
||||
@ -183,11 +182,11 @@ public class DoubleStringConverter extends StringConverter<Double> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the specified {@link Double} into its {@link String} form.
|
||||
* Converts the specified double into its string form.
|
||||
* A {@code null} argument is converted into the literal string "0".
|
||||
*
|
||||
* @param value the {@link Double} to convert
|
||||
* @return the {@link String} form of {@code value}
|
||||
* @param value The Double to convert.
|
||||
* @return the string form of {@code value}
|
||||
*/
|
||||
@Override
|
||||
public String toString(Double value) {
|
||||
|
@ -12,47 +12,48 @@ import javafx.scene.control.Tooltip;
|
||||
import javafx.util.StringConverter;
|
||||
|
||||
/**
|
||||
* Converts between user-edited strings and {@link Integer} values.
|
||||
* Accepts an optional {@link Runnable} that resets the editor on {@link NumberFormatException},
|
||||
* or a {@link TextField} or {@link Spinner} that is preemptively monitored for invalid
|
||||
* Converts between user-edited strings and integer values.
|
||||
*
|
||||
* <p>Accepts an optional Runnable that resets the editor on NumberFormatException,
|
||||
* or a TextField or Spinner that is preemptively monitored for invalid
|
||||
* input during typing, and restricts valid input to a specified range when committed.
|
||||
*
|
||||
* @author Christoph Nahr
|
||||
* @version 1.0.2
|
||||
*/
|
||||
public class IntegerStringConverter extends StringConverter<Integer> {
|
||||
|
||||
private Runnable reset;
|
||||
|
||||
/**
|
||||
* Creates an {@link IntegerStringConverter}.
|
||||
* Swallows {@link NumberFormatException} but does nothing
|
||||
* Creates an IntegerStringConverter.
|
||||
* Swallows NumberFormatException but does nothing
|
||||
* in response until {@link #setReset} is defined.
|
||||
*/
|
||||
public IntegerStringConverter() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an {@link IntegerStringConverter} with an editor reset callback.
|
||||
* Creates an IntegerStringConverter with an editor reset callback.
|
||||
* Specifying {@code null} has the same effect as the default constructor.
|
||||
*
|
||||
* @param reset the {@link Runnable} to call upon {@link NumberFormatException}
|
||||
* @param reset The Runnable to call upon NumberFormatException.
|
||||
*/
|
||||
public IntegerStringConverter(Runnable reset) {
|
||||
this.reset = reset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an {@link IntegerStringConverter} with the specified input range.
|
||||
* Preemptively monitors {@code input} to reject any invalid characters during
|
||||
* typing, restricts {@code input} to [{@code min}, {@code max}] (inclusive) when
|
||||
* valid text is committed, and resets {@code input} to the closest value to zero
|
||||
* Creates an IntegerStringConverter with the specified input range.
|
||||
*
|
||||
* <p>Preemptively monitors input to reject any invalid characters during
|
||||
* typing, restricts input to [{@code min}, {@code max}] (inclusive) when
|
||||
* valid text is committed, and resets input to the closest value to zero
|
||||
* within [{@code min}, {@code max}] when invalid text is committed.
|
||||
*
|
||||
* @param input the {@link TextField} providing user-edited strings
|
||||
* @param min the smallest valid {@link Integer} value
|
||||
* @param max the greatest valid {@link Integer} value
|
||||
* @throws NullPointerException if {@code input} is {@code null}
|
||||
* @param input The TextField providing user-edited strings.
|
||||
* @param min The smallest valid integer value.
|
||||
* @param max The greatest valid integer value.
|
||||
* @throws NullPointerException if input is {@code null}
|
||||
*/
|
||||
public IntegerStringConverter(TextField input, int min, int max) {
|
||||
if (input == null) {
|
||||
@ -62,11 +63,6 @@ public class IntegerStringConverter extends StringConverter<Integer> {
|
||||
final int resetValue = Math.min(Math.max(0, min), max);
|
||||
reset = () -> input.setText(Integer.toString(resetValue));
|
||||
|
||||
// bound JavaFX properties cannot be explicitly set
|
||||
// if (!input.tooltipProperty().isBound()) {
|
||||
// input.setTooltip(new Tooltip(String.format("Enter a value between %d and %d", min, max)));
|
||||
// }
|
||||
|
||||
// restrict direct input to valid numerical characters
|
||||
input.textProperty().addListener((ov, oldValue, newValue) -> {
|
||||
if (newValue == null || newValue.isEmpty()) {
|
||||
@ -109,13 +105,13 @@ public class IntegerStringConverter extends StringConverter<Integer> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an {@link IntegerStringConverter} for the specified {@link Spinner}.
|
||||
* Uses the {@link TextField} and minimum and maximum values of the specified
|
||||
* {@link Spinner} for construction, and also sets the new {@link IntegerStringConverter}
|
||||
* Creates an IntegerStringConverter for the specified Spinner.
|
||||
* Uses the TextField and minimum and maximum values of the specified
|
||||
* Spinner for construction, and also sets the new IntegerStringConverter
|
||||
* on its {@link SpinnerValueFactory.IntegerSpinnerValueFactory}.
|
||||
*
|
||||
* @param spinner the {@link Spinner} to create an {@link IntegerStringConverter} for
|
||||
* @return the new {@link IntegerStringConverter}
|
||||
* @param spinner The Spinner to create an IntegerStringConverter for.
|
||||
* @return the new IntegerStringConverter
|
||||
* @throws NullPointerException if {@code spinner} is {@code null}
|
||||
*/
|
||||
public static IntegerStringConverter createFor(Spinner<Integer> spinner) {
|
||||
@ -135,13 +131,14 @@ public class IntegerStringConverter extends StringConverter<Integer> {
|
||||
|
||||
/**
|
||||
* Sets the editor reset callback.
|
||||
* Specify {@code null} to clear a previously set {@link Runnable}. When creating
|
||||
* an {@link IntegerStringConverter} for a {@link TextField} or {@link Spinner},
|
||||
* this callback is automatically defined to reset committed invalid input to the
|
||||
* closest value to zero within the legal range. Setting a different callback
|
||||
* will overwrite this functionality.
|
||||
*
|
||||
* @param reset the {@link Runnable} to call upon {@link NumberFormatException}
|
||||
* <p>Specify {@code null} to clear a previously set Runnable. When creating
|
||||
* an IntegerStringConverter for a TextField or Spinner, this callback is
|
||||
* automatically defined to reset committed invalid input to the closest value
|
||||
* to zero within the legal range. Setting a different callback will overwrite
|
||||
* this functionality.
|
||||
*
|
||||
* @param reset The Runnable to call upon NumberFormatException.
|
||||
* @see #fromString
|
||||
*/
|
||||
public void setReset(Runnable reset) {
|
||||
@ -149,12 +146,12 @@ public class IntegerStringConverter extends StringConverter<Integer> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the specified {@link String} into its {@link Integer} value.
|
||||
* Converts the specified string into its integer value.
|
||||
* A {@code null}, empty, or otherwise invalid argument returns zero
|
||||
* and also executes the editor reset callback, if any.
|
||||
*
|
||||
* @param s the {@link String} to convert
|
||||
* @return the {@link Integer} value of {@code s}
|
||||
* @param s The {@link String} to convert.
|
||||
* @return the integer value of {@code s}
|
||||
* @see #setReset
|
||||
*/
|
||||
@Override
|
||||
@ -177,10 +174,10 @@ public class IntegerStringConverter extends StringConverter<Integer> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the specified {@link Integer} into its {@link String} form.
|
||||
* Converts the specified integer into its string form.
|
||||
* A {@code null} argument is converted into the literal string "0".
|
||||
*
|
||||
* @param value the {@link Integer} to convert
|
||||
* @param value The integer to convert.
|
||||
* @return the {@link String} form of {@code value}
|
||||
*/
|
||||
@Override
|
||||
|
@ -26,7 +26,7 @@ public interface MaskChar {
|
||||
char INPUT_MASK_DIGIT_ZERO = '0';
|
||||
|
||||
/**
|
||||
* Returns true if the character is allowed, false otherwise.
|
||||
* Returns "true" if the character is allowed, "false" otherwise.
|
||||
*/
|
||||
boolean isAllowed(char ch);
|
||||
|
||||
|
@ -36,14 +36,19 @@ import org.jetbrains.annotations.Nullable;
|
||||
* </ul>
|
||||
*
|
||||
* <p><h3>Behavior</h3>
|
||||
* Any {@code TextField} with {@code MaskTextFormatter} applied shows a placeholder mask by default.
|
||||
* This is basically the input mask with all mask characters replaced with {@link MaskChar#getPlaceholder()}.
|
||||
* The behavior changes if you set {@link TextField#promptTextProperty()}. In that case placeholder
|
||||
* mask is only displayed when {@code TextField} gets focus and will be hidden after focus lost.
|
||||
* So, the placeholder mask is always displayed when focus is set to the {@code TextField}.
|
||||
* You can replace the placeholder mask with any sensible default simply by changing initial
|
||||
* {@code TextField} text to any string that is valid against the input mask.
|
||||
* <br/><br/>The caret will be positioned before the first not fixed character (see {@link MaskChar#isFixed()})
|
||||
* Any {@code TextField} with {@code MaskTextFormatter} applied shows a placeholder
|
||||
* mask by default. This is basically the input mask with all mask characters replaced
|
||||
* with the {@link MaskChar#getPlaceholder()} character.
|
||||
*
|
||||
* <p>The behavior changes if you set the {@link TextField#promptTextProperty()}.
|
||||
* In that case placeholder mask is only displayed when {@code TextField} gets focus and
|
||||
* will be hidden after focus lost. So, the placeholder mask is always displayed when focus
|
||||
* is set to the {@code TextField}.
|
||||
*
|
||||
* <p>You can replace the placeholder mask with any sensible default simply by changing initial
|
||||
* {@code TextField} text to any string that is valid against the input mask.<br/><br/>
|
||||
*
|
||||
* <p>The caret will be positioned before the first not fixed character (see {@link MaskChar#isFixed()})
|
||||
* starting from the beginning of the input mask.<br/><br/>
|
||||
*
|
||||
* <p><h3>Validation</h3>
|
||||
@ -68,8 +73,6 @@ public class MaskTextFormatter extends TextFormatter<String> {
|
||||
|
||||
/**
|
||||
* Creates a new text field with the provided string input mask.
|
||||
* Use this if you create your controls from Java code and don't need to
|
||||
* modify the default {@link MaskChar} implementation.
|
||||
*/
|
||||
public static TextField createTextField(String mask) {
|
||||
return createTextField(fromString(mask));
|
||||
@ -77,8 +80,6 @@ public class MaskTextFormatter extends TextFormatter<String> {
|
||||
|
||||
/**
|
||||
* Creates a new text field with the provided input mask.
|
||||
* Use this if you create your controls from Java code and want to
|
||||
* modify the default {@link MaskChar} implementation.
|
||||
*/
|
||||
public static TextField createTextField(List<MaskChar> mask) {
|
||||
final var field = new TextField();
|
||||
@ -88,9 +89,7 @@ public class MaskTextFormatter extends TextFormatter<String> {
|
||||
|
||||
/**
|
||||
* Creates a new mask text formatter with the provided string input mask and
|
||||
* applies itself to the specified text field. Use this if you create your
|
||||
* controls from FXML and don't need to modify the default {@link MaskChar}
|
||||
* implementation.
|
||||
* applies itself to the specified text field.
|
||||
*/
|
||||
public static MaskTextFormatter create(TextField field, String mask) {
|
||||
return create(field, fromString(mask));
|
||||
@ -98,8 +97,7 @@ public class MaskTextFormatter extends TextFormatter<String> {
|
||||
|
||||
/**
|
||||
* Creates a new mask text formatter with the provided input mask and
|
||||
* applies itself to the specified text field. Use this if you create your
|
||||
* controls from FXML and want to modify the default {@link MaskChar} implementation.
|
||||
* applies itself to the specified text field.
|
||||
*/
|
||||
public static MaskTextFormatter create(TextField field, List<MaskChar> mask) {
|
||||
Objects.requireNonNull(field, "Text field can't be null");
|
||||
|
@ -8,13 +8,14 @@ import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.ReadOnlyStringProperty;
|
||||
import javafx.beans.property.ReadOnlyStringWrapper;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.scene.control.PasswordField;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.control.TextFormatter;
|
||||
import javafx.util.StringConverter;
|
||||
|
||||
/**
|
||||
* An alternative for the {@link javafx.scene.control.PasswordField}.
|
||||
* The formatter (un)masks text field content based on boolean property.
|
||||
* An alternative to the {@link PasswordField} class. This formatter masks
|
||||
* or unmasks text field content based on a boolean property.
|
||||
*/
|
||||
public class PasswordTextFormatter extends TextFormatter<String> {
|
||||
|
||||
|
@ -3,8 +3,8 @@
|
||||
package atlantafx.base.util;
|
||||
|
||||
/**
|
||||
* Utility class that provides just some basic methods that's commonly necessary
|
||||
* for control/skin development.
|
||||
* A utility class that provides just some platform methods that's commonly
|
||||
* necessary for control/skin development.
|
||||
*/
|
||||
public final class PlatformUtils {
|
||||
|
||||
@ -20,18 +20,30 @@ public final class PlatformUtils {
|
||||
private static final boolean OPEN_BSD = OS.startsWith("openbsd");
|
||||
private static final boolean NET_BSD = OS.startsWith("netbsd");
|
||||
|
||||
/**
|
||||
* Returns "true" if this is Windows.
|
||||
*/
|
||||
public static boolean isWindows() {
|
||||
return WINDOWS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns "true" if this is Mac.
|
||||
*/
|
||||
public static boolean isMac() {
|
||||
return MAC;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns "true" if this is Linux.
|
||||
*/
|
||||
public static boolean isLinux() {
|
||||
return LINUX;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns "true" if this is a UNIX like system.
|
||||
*/
|
||||
public static boolean isUnix() {
|
||||
return LINUX || FREE_BSD || OPEN_BSD || NET_BSD;
|
||||
}
|
||||
|
@ -17,21 +17,53 @@ public final class SimpleMaskChar implements MaskChar {
|
||||
private final char placeholder;
|
||||
private final boolean fixed;
|
||||
|
||||
/**
|
||||
* Creates a SimpleMaskChar.
|
||||
*
|
||||
* @param matchExpr The matching predicate that determines which characters are masked.
|
||||
* @see #SimpleMaskChar(Predicate, UnaryOperator, char, boolean)
|
||||
*/
|
||||
public SimpleMaskChar(Predicate<Character> matchExpr) {
|
||||
this(matchExpr, UnaryOperator.identity(), UNDERSCORE, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a SimpleMaskChar.
|
||||
*
|
||||
* @param matchExpr The matching predicate that determines which characters are masked.
|
||||
* @param transform The transformation function that is applied to input characters.
|
||||
* @see #SimpleMaskChar(Predicate, UnaryOperator, char, boolean)
|
||||
*/
|
||||
public SimpleMaskChar(Predicate<Character> matchExpr,
|
||||
UnaryOperator<Character> transform) {
|
||||
this(matchExpr, transform, UNDERSCORE, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a SimpleMaskChar.
|
||||
*
|
||||
* @param matchExpr The matching predicate that determines which characters are masked.
|
||||
* @param transform The transformation function that is applied to input characters.
|
||||
* @param placeholder The placeholder character to use for masking.
|
||||
* @see #SimpleMaskChar(Predicate, UnaryOperator, char, boolean)
|
||||
*/
|
||||
public SimpleMaskChar(Predicate<Character> matchExpr,
|
||||
UnaryOperator<Character> transform,
|
||||
char placeholder) {
|
||||
this(matchExpr, transform, placeholder, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a SimpleMaskChar.
|
||||
*
|
||||
* @param matchExpr The matching predicate that determines which characters are masked.
|
||||
* @param transform The transformation function that is applied to input characters.
|
||||
* No transformation is applied by default.
|
||||
* @param placeholder The placeholder character to use for masking.
|
||||
* The default replacement is underscore character.
|
||||
* @param fixed Boolean value indicating if the character is fixed or not.
|
||||
* Default is false.
|
||||
*/
|
||||
public SimpleMaskChar(Predicate<Character> matchExpr,
|
||||
UnaryOperator<Character> transform,
|
||||
char placeholder,
|
||||
@ -42,26 +74,42 @@ public final class SimpleMaskChar implements MaskChar {
|
||||
this.fixed = fixed;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public boolean isAllowed(final char ch) {
|
||||
return matchExpr.test(ch);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public char transform(final char ch) {
|
||||
return transform.apply(ch);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public char getPlaceholder() {
|
||||
return placeholder;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public boolean isFixed() {
|
||||
return fixed;
|
||||
}
|
||||
|
||||
/**
|
||||
* A utility method for creating a fixed character - that is, the character used to represent
|
||||
* the fixed part (a prefix or a suffix) of the input mask.
|
||||
*/
|
||||
public static SimpleMaskChar fixed(char ch) {
|
||||
return new SimpleMaskChar(c -> c == ch, UnaryOperator.identity(), ch, true);
|
||||
}
|
||||
|
5
base/src/main/java/atlantafx/base/util/package-info.java
Normal file
5
base/src/main/java/atlantafx/base/util/package-info.java
Normal file
@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Provides various utility classes, formatters and converters.
|
||||
*/
|
||||
|
||||
package atlantafx.base.util;
|
@ -1,4 +1,7 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/**
|
||||
* Provides additional controls, layout and Java API for
|
||||
* custom themes support.
|
||||
*/
|
||||
|
||||
module atlantafx.base {
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user