/*
 * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package javafx.css;

import java.util.Collections;
import java.util.List;
import javafx.scene.Node;

A CssMetaData instance provides information about the CSS style and provides the hooks that allow CSS to set a property value. It encapsulates the CSS property name, the type into which the CSS value is converted, and the default value of the property.

CssMetaData is the bridge between a value that can be represented syntactically in a .css file, and a StyleableProperty. There is a one-to-one correspondence between a CssMetaData and a StyleableProperty. Typically, the CssMetaData of a Node will include the CssMetaData of its ancestors. For example, the CssMetaData of a Rectangle includes the CssMetaData of Shape and also of Node. During CSS processing, the CSS engine iterates over the Node's CssMetaData, looks up the parsed value of each property, converts the parsed value, and sets the value on the StyleableProperty.

The method Node.getCssMetaData() is called to obtain the List<CssMetaData>. This method is called frequently and it is prudent to return a static list rather than creating the list on each call. By convention, node classes that have CssMetaData will implement a static method getClassCssMetaData() and it is customary to have getCssMetaData() simply return getClassCssMetaData(). The purpose of getClassCssMetaData() is to allow sub-classes to easily include the CssMetaData of some ancestor.

The StyleablePropertyFactory greatly simplifies creating a StyleableProperty and its corresponding CssMetaData.

This example is a typical implementation.

 private DoubleProperty gapProperty = new StyleableDoubleProperty(0) { @Override public CssMetaData<MyWidget,Number> getCssMetaData() { return GAP_META_DATA; } @Override public Object getBean() { return MyWidget.this; } @Override public String getName() { return "gap"; } }; private static final CssMetaData GAP_META_DATA = new CssMetaData<MyWidget,Number>("-my-gap", StyleConverter.getSizeConverter(), 0d) { @Override public boolean isSettable(MyWidget node) { return node.gapProperty == null || !node.gapProperty.isBound(); } @Override public StyleableProperty<Number> getStyleableProperty(MyWidget node) { return (StyleableProperty<Number>)node.gapProperty; } }; private static final List<CssMetaData<? extends Node, ?>> cssMetaDataList; static { List<CssMetaData<? extends Node, ?>> temp = new ArrayList<CssMetaData<? extends Node, ?>>(Control.getClassCssMetaData()); temp.add(GAP_META_DATA); cssMetaDataList = Collections.unmodifiableList(temp); } public static List<CssMetaData<? extends Node, ?>> getClassCssMetaData() { return cssMetaDataList; } @Override public List<CssMetaData<? extends Node, ?>> getCssMetaData() { return getClassCssMetaData(); } 
Type parameters:
  • <S> – The type of Styleable
  • <V> – The type into which the parsed value is converted.
See Also:
Since:JavaFX 8.0
/** * A CssMetaData instance provides information about the CSS style and * provides the hooks that allow CSS to set a property value. * It encapsulates the CSS property name, the type into which the CSS value * is converted, and the default value of the property. * <p> * CssMetaData is the bridge between a value that can be represented * syntactically in a .css file, and a {@link StyleableProperty}. There is * a one-to-one correspondence between a CssMetaData and a StyleableProperty. * Typically, the CssMetaData of a Node will include the CssMetaData of its ancestors. * For example, the CssMetaData of a Rectangle includes the CssMetaData of Shape and also of Node. * During CSS processing, the CSS engine iterates over the Node's CssMetaData, * looks up the parsed value of each {@link javafx.css.CssMetaData#getProperty() property}, * converts the parsed value, and sets the value on the StyleableProperty. * <p> * The method {@link Node#getCssMetaData()} is called to obtain the * List&lt;CssMetaData&gt;. This method is called frequently and it is prudent * to return a static list rather than creating the list on each call. By * convention, node classes that have CssMetaData will implement a * static method {@code getClassCssMetaData()} and it is customary to have * {@code getCssMetaData()} simply return {@code getClassCssMetaData()}. The * purpose of {@code getClassCssMetaData()} is to allow sub-classes to easily * include the CssMetaData of some ancestor. * <p>The {@link javafx.css.StyleablePropertyFactory StyleablePropertyFactory} * greatly simplifies creating a StyleableProperty and its corresponding CssMetaData.</p> * <p> * This example is a typical implementation. * <pre><code> * private DoubleProperty gapProperty = new StyleableDoubleProperty(0) { * {@literal @}Override * public CssMetaData{@literal <}MyWidget,Number{@literal >} getCssMetaData() { * return GAP_META_DATA; * } * * {@literal @}Override * public Object getBean() { * return MyWidget.this; * } * * {@literal @}Override * public String getName() { * return "gap"; * } * }; * * private static final CssMetaData GAP_META_DATA = * new CssMetaData{@literal <}MyWidget,Number{@literal >}("-my-gap", StyleConverter.getSizeConverter(), 0d) { * * {@literal @}Override * public boolean isSettable(MyWidget node) { * return node.gapProperty == null || !node.gapProperty.isBound(); * } * * {@literal @}Override * public StyleableProperty{@literal <}Number{@literal >} getStyleableProperty(MyWidget node) { * return (StyleableProperty{@literal <}Number{@literal >})node.gapProperty; * } * }; * * private static final List{@literal <}CssMetaData{@literal <}? extends Node, ?{@literal >}{@literal >} cssMetaDataList; * static { * List{@literal <}CssMetaData{@literal <}? extends Node, ?{@literal >}{@literal >} temp = * new ArrayList{@literal <}CssMetaData{@literal <}? extends Node, ?{@literal >}{@literal >}(Control.getClassCssMetaData()); * temp.add(GAP_META_DATA); * cssMetaDataList = Collections.unmodifiableList(temp); * } * * public static List{@literal <}CssMetaData{@literal <}? extends Node, ?{@literal >}{@literal >} getClassCssMetaData() { * return cssMetaDataList; * } * * {@literal @}Override * public List{@literal <}CssMetaData{@literal <}? extends Node, ?{@literal >}{@literal >} getCssMetaData() { * return getClassCssMetaData(); * } * </code></pre> * @param <S> The type of Styleable * @param <V> The type into which the parsed value is converted. * @since JavaFX 8.0 * @see javafx.css.StyleablePropertyFactory */
public abstract class CssMetaData<S extends Styleable, V> {
Set the value of the corresponding property on the given Node.
Params:
  • styleable – The Styleable on which the property value is being set
  • value – The value to which the property is set
  • origin – the origin
Deprecated:This method is no longer called from CSS code. Use StyleableProperty.applyStyle(StyleOrigin, Object)
/** * Set the value of the corresponding property on the given Node. * @param styleable The Styleable on which the property value is being set * @param value The value to which the property is set * @param origin the origin * @deprecated This method is no longer called from CSS code. * Use {@link StyleableProperty#applyStyle(javafx.css.StyleOrigin, java.lang.Object)} */
@Deprecated(since="8") public void set(S styleable, V value, StyleOrigin origin) { final StyleableProperty<V> styleableProperty = getStyleableProperty(styleable); final StyleOrigin currentOrigin = styleableProperty.getStyleOrigin(); final V currentValue = styleableProperty.getValue(); // RT-21185: Only apply the style if something has changed. if ((currentOrigin != origin) || (currentValue != null ? currentValue.equals(value) == false : value != null)) { styleableProperty.applyStyle(origin, value); } }
Check to see if the corresponding property on the given Node is settable. This method is called before any styles are looked up for the given property. It is abstract so that the code can check if the property is settable without expanding the property. Generally, the property is settable if it is not null or is not bound.
Params:
  • styleable – The Styleable on which the property value is being set
Returns:true if the property can be set.
/** * Check to see if the corresponding property on the given Node is * settable. This method is called before any styles are looked up for the * given property. It is abstract so that the code can check if the property * is settable without expanding the property. Generally, the property is * settable if it is not null or is not bound. * * @param styleable The Styleable on which the property value is being set * @return true if the property can be set. */
public abstract boolean isSettable(S styleable);
Return the corresponding StyleableProperty for the given Node. Note that calling this method will cause the property to be expanded.
Params:
  • styleable – The Styleable for which the property is returned
Returns:The StyleableProperty corresponding to this CssMetaData for the given Styleable
/** * Return the corresponding {@link StyleableProperty} for the given Node. * Note that calling this method will cause the property to be expanded. * @param styleable The Styleable for which the property is returned * @return The StyleableProperty corresponding to this CssMetaData for the * given Styleable */
public abstract StyleableProperty<V> getStyleableProperty(S styleable); private final String property;
Returns:the CSS property name
/** * @return the CSS property name */
public final String getProperty() { return property; } private final StyleConverter<?,V> converter;
Returns:The CSS converter that handles conversion from a CSS value to a Java Object
/** * @return The CSS converter that handles conversion from a CSS value to a Java Object */
public final StyleConverter<?,V> getConverter() { return converter; } private final V initialValue;
The initial value of a CssMetaData corresponds to the default value of the StyleableProperty in code. For example, the default value of Shape.fill is Color.BLACK and the initialValue of Shape.StyleableProperties.FILL is also Color.BLACK.

There may be exceptions to this, however. The initialValue may depend on the state of the Node. A ScrollBar has a default orientation of horizontal. If the ScrollBar is vertical, however, this method should return Orientation.VERTICAL. Otherwise, a vertical ScrollBar would be incorrectly set to a horizontal ScrollBar when the initial value is applied.

Params:
  • styleable – the styleable
Returns:The initial value of the property, possibly null
/** * The initial value of a CssMetaData corresponds to the default * value of the StyleableProperty in code. * For example, the default value of Shape.fill is Color.BLACK and the * initialValue of Shape.StyleableProperties.FILL is also Color.BLACK. * <p> * There may be exceptions to this, however. The initialValue may depend * on the state of the Node. A ScrollBar has a default orientation of * horizontal. If the ScrollBar is vertical, however, this method should * return Orientation.VERTICAL. Otherwise, a vertical ScrollBar would be * incorrectly set to a horizontal ScrollBar when the initial value is * applied. * @param styleable the styleable * @return The initial value of the property, possibly null */
public V getInitialValue(S styleable) { return initialValue; } private final List<CssMetaData<? extends Styleable, ?>> subProperties;
The sub-properties refers to the constituent properties of this property, if any. For example, "-fx-font-weight" is sub-property of "-fx-font".
Returns:the list of sub-properties
/** * The sub-properties refers to the constituent properties of this property, * if any. For example, "-fx-font-weight" is sub-property of "-fx-font". * @return the list of sub-properties */
public final List<CssMetaData<? extends Styleable, ?>> getSubProperties() { return subProperties; } private final boolean inherits;
If true, the value of this property is the same as the parent's computed value of this property.
See Also:
Returns:false by default unless inherits is true
/** * If true, the value of this property is the same as * the parent's computed value of this property. * @return false by default unless inherits is true * @see <a href="http://www.w3.org/TR/css3-cascade/#inheritance">CSS Inheritance</a> */
public final boolean isInherits() { return inherits; }
Construct a CssMetaData with the given parameters and no sub-properties.
Params:
  • property – the CSS property
  • converter – the StyleConverter used to convert the CSS parsed value to a Java object.
  • initialValue – The initial or default value of the corresponding StyleableProperty
  • inherits – true if this property uses CSS inheritance
  • subProperties – the sub-properties of this property. For example, the -fx-font property has the sub-properties -fx-font-family, -fx-font-size, -fx-font-weight, and -fx-font-style.
/** * Construct a CssMetaData with the given parameters and no sub-properties. * @param property the CSS property * @param converter the StyleConverter used to convert the CSS parsed value to a Java object. * @param initialValue The initial or default value of the corresponding StyleableProperty * @param inherits true if this property uses CSS inheritance * @param subProperties the sub-properties of this property. For example, * the -fx-font property has the sub-properties -fx-font-family, * -fx-font-size, -fx-font-weight, and -fx-font-style. */
protected CssMetaData( final String property, final StyleConverter<?,V> converter, final V initialValue, boolean inherits, final List<CssMetaData<? extends Styleable, ?>> subProperties) { this.property = property; this.converter = converter; this.initialValue = initialValue; this.inherits = inherits; this.subProperties = subProperties != null ? Collections.unmodifiableList(subProperties) : null; if (this.property == null || this.converter == null) { throw new IllegalArgumentException("neither property nor converter can be null"); } }
Construct a CssMetaData with the given parameters and no sub-properties.
Params:
  • property – the CSS property
  • converter – the StyleConverter used to convert the CSS parsed value to a Java object.
  • initialValue – The initial or default value of the corresponding StyleableProperty
  • inherits – true if this property uses CSS inheritance
/** * Construct a CssMetaData with the given parameters and no sub-properties. * @param property the CSS property * @param converter the StyleConverter used to convert the CSS parsed value to a Java object. * @param initialValue The initial or default value of the corresponding StyleableProperty * @param inherits true if this property uses CSS inheritance */
protected CssMetaData( final String property, final StyleConverter<?,V> converter, final V initialValue, boolean inherits) { this(property, converter, initialValue, inherits, null); }
Construct a CssMetaData with the given parameters, inherit set to false and no sub-properties.
Params:
  • property – the CSS property
  • converter – the StyleConverter used to convert the CSS parsed value to a Java object.
  • initialValue – The initial or default value of the corresponding StyleableProperty
/** * Construct a CssMetaData with the given parameters, inherit set to * false and no sub-properties. * @param property the CSS property * @param converter the StyleConverter used to convert the CSS parsed value to a Java object. * @param initialValue The initial or default value of the corresponding StyleableProperty */
protected CssMetaData( final String property, final StyleConverter<?,V> converter, final V initialValue) { this(property, converter, initialValue, false, null); }
Construct a CssMetaData with the given parameters, initialValue is null, inherit is set to false, and no sub-properties.
Params:
  • property – the CSS property
  • converter – the StyleConverter used to convert the CSS parsed value to a Java object.
/** * Construct a CssMetaData with the given parameters, initialValue is * null, inherit is set to false, and no sub-properties. * @param property the CSS property * @param converter the StyleConverter used to convert the CSS parsed value to a Java object. */
protected CssMetaData( final String property, final StyleConverter<?,V> converter) { this(property, converter, null, false, null); }
Two CssMetaData objects are considered to be equal if their property values are equal.
Returns:true if the obj is equaled, false otherwise
/** * Two CssMetaData objects are considered to be equal if their {@link #getProperty() property} values are equal. * @return true if the obj is equaled, false otherwise */
@Override public boolean equals(Object obj) { if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final CssMetaData<? extends Styleable, ?> other = (CssMetaData<? extends Styleable, ?>) obj; if ((this.property == null) ? (other.property != null) : !this.property.equals(other.property)) { return false; } return true; } @Override public int hashCode() { int hash = 3; hash = 19 * hash + (this.property != null ? this.property.hashCode() : 0); return hash; } @Override public String toString() { return new StringBuilder("CSSProperty {") .append("property: ").append(property) .append(", converter: ").append(converter.toString()) .append(", initalValue: ").append(String.valueOf(initialValue)) .append(", inherits: ").append(inherits) .append(", subProperties: ").append( (subProperties != null) ? subProperties.toString() : "[]") .append("}").toString(); } }