Package javafx.css

Class StyleablePropertyFactory<S extends Styleable>

java.lang.Object
javafx.css.StyleablePropertyFactory<S>
Type Parameters:
S - The type of Styleable

public class StyleablePropertyFactory<S extends Styleable> extends Object
Methods for creating instances of StyleableProperty with corresponding CssMetaData created behind the scenes. These methods greatly reduce the amount of boiler-plate code needed to implement the StyleableProperty and CssMetaData. These methods take a Function<? extends Styleable, StyleableProperty<?>> which returns a reference to the property itself. See the example below. Note that for efficient use of memory and for better CSS performance, creating the StyleablePropertyFactory as a static member, as shown below, is recommended.

 public final class MyButton extends Button {

     private static final StyleablePropertyFactory<MyButton> FACTORY = new StyleablePropertyFactory<>(Button.getClassCssMetaData());

     MyButton(String labelText) {
         super(labelText);
         getStyleClass().add("my-button");
     }

     // Typical JavaFX property implementation
     public ObservableValue<Boolean> selectedProperty() { return (ObservableValue<Boolean>)selected; }
     public final boolean isSelected() { return selected.getValue(); }
     public final void setSelected(boolean isSelected) { selected.setValue(isSelected); }

     // StyleableProperty implementation reduced to one line
     private final StyleableProperty<Boolean> selected =
         FACTORY.createStyleableBooleanProperty(this, "selected", "-my-selected", s -> s.selected);

     @Override
     public List<CssMetaData<? extends Styleable, ?>> getControlCssMetaData() {
         return FACTORY.getCssMetaData();
     }

 }
 

The example above is the simplest use of StyleablePropertyFactory. But, this use does not provide the static CssMetaData that is useful for getClassCssMetaData(), which is described in the javadoc for CssMetaData. Static CssMetaData can, however, be created via StyleablePropertyFactory methods and will be returned by the methods which create StyleableProperty instances, as the example below illustrates. Note that the static method getClassCssMetaData() is a convention used throughout the JavaFX code base but the getClassCssMetaData() method itself is not used at runtime.


 public final class MyButton extends Button {

     private static final StyleablePropertyFactory<MyButton> FACTORY =
         new StyleablePropertyFactory<>(Button.getClassCssMetaData());

     private static final CssMetaData<MyButton, Boolean> SELECTED =
         FACTORY.createBooleanCssMetaData("-my-selected", s -> s.selected, false, false);

     MyButton(String labelText) {
         super(labelText);
         getStyleClass().add("my-button");
     }

     // Typical JavaFX property implementation
     public ObservableValue<Boolean> selectedProperty() { return (ObservableValue<Boolean>)selected; }
     public final boolean isSelected() { return selected.getValue(); }
     public final void setSelected(boolean isSelected) { selected.setValue(isSelected); }

     // StyleableProperty implementation reduced to one line
     private final StyleableProperty<Boolean> selected =
         new SimpleStyleableBooleanProperty(SELECTED, this, "selected");

     public static List<CssMetaData<? extends Styleable, ?>> getClassCssMetaData() {
         return FACTORY.getCssMetaData();
     }

     @Override
     public List<CssMetaData<? extends Styleable, ?>> getControlCssMetaData() {
         return FACTORY.getCssMetaData();
     }
 }
 

The same can be accomplished with an inner-class. The previous example called new SimpleStyleableBooleanProperty to create the selected property. This example uses the factory to access the CssMetaData that was created along with the anonymous inner-class. For all intents and purposes, the two examples are the same.


 public final class MyButton extends Button {

     private static CssMetaData<MyButton, Boolean> SELECTED;

     private static final StyleablePropertyFactory<MyButton> FACTORY =
         new StyleablePropertyFactory<>(Button.getClassCssMetaData()) {
         {
             SELECTED = createBooleanCssMetaData("-my-selected", s -> s.selected, false, false);
         }
     };


     MyButton(String labelText) {
         super(labelText);
         getStyleClass().add("my-button");
     }

     // Typical JavaFX property implementation
     public ObservableValue<Boolean> selectedProperty() { return (ObservableValue<Boolean>)selected; }
     public final boolean isSelected() { return selected.getValue(); }
     public final void setSelected(boolean isSelected) { selected.setValue(isSelected); }

     // StyleableProperty implementation reduced to one line
     private final StyleableProperty<Boolean> selected =
         new SimpleStyleableBooleanProperty(SELECTED, "selected", "my-selected");

     public static List<CssMetaData<? extends Styleable, ?>> getClassCssMetaData() {
         return FACTORY.getCssMetaData();
     }

     @Override
     public List<CssMetaData<? extends Styleable, ?>> getControlCssMetaData() {
         return FACTORY.getCssMetaData();
     }
 }
 

Caveats:

The only option for creating a StyleableProperty with a number value is to create a StyleableProperty<Number>. The return value from the getValue() method of the StyleableProperty is a Number. Therefore, the get method of the JavaFX property needs to call the correct value method for the return type. For example,

     public ObservableValue<Double> offsetProperty() { return (ObservableValue<Double>)offset; }
     public Double getOffset() { return offset.getValue().doubleValue(); }
     public void setOffset(Double value) { offset.setValue(value); }
     private final StyleableProperty<Number> offset = FACTORY.createStyleableNumberProperty(this, "offset", "-my-offset", s -> ((MyButton)s).offset);
 
Since:
JavaFX 8u40