Yes, I had similar considerations. I was thinking about providing exactly such 
extended Property classes in JFXtras to remove as much of the boilerplate.

Tom


On 2014-1-8 3:34, John Hendrikx wrote:
Hi List,

I'm in the process of adding CSS metadata to a new control, and I noticed there 
is a lot of boilerplate.

In order to reduce this, I've created some custom classes StyleableProperty 
classes (SimpleStyleableXXXProperty), which reduces the boilerplate 
significantly without sacrificing much (if any) performance.  The only thing 
that I cannot easily provide in this fashion is the static getClassCssMetaData 
method.  From the documentation I understand it is there just for convience for 
subclass creators and is not used by the CSS engine at all -- atleast, 
everything seems to work.

The shortened version for CSS aware properties basically looks like:

  private final SimpleStyleableDoubleProperty cellAlignment = new 
SimpleStyleableDoubleProperty(this, "cellAlignment", "-fx-cell-alignment", 0.8);
  private final SimpleStyleableDoubleProperty density= new SimpleStyleableDoubleProperty(this, 
"density", "-fx-density", 0.02);
  private final SimpleStyleableBooleanProperty reflectionEnabled= new 
SimpleStyleableBooleanProperty(this, "reflectionEnabled", 
"-fx-reflection-enabled", true);
  private final SimpleStyleableBooleanProperty clipReflections= new 
SimpleStyleableBooleanProperty(this, "clipReflections", "-fx-clip-reflections", 
true);

With one small bit of supporting code in the relevant class (Skin or Control), 
which is basically a non-static implementation of the standard CSS List example 
code:

  private static List<CssMetaData<? extends Styleable, ?>> cssMetaData;

  @Override
  public List<CssMetaData<? extends Styleable, ?>> getCssMetaData() {  // 
Unsynchronized. WC: list gets initialized multiple times.
    if(cssMetaData == null) {
      List<CssMetaData<? extends Styleable, ?>> metaData = new 
ArrayList<>(super.getCssMetaData());
      Collections.addAll(metaData,
          cellAlignment.getCssMetaData(),
          density.getCssMetaData(),
          reflectionEnabled.getCssMetaData(),
          clipReflections.getCssMetaData()
      );
      cssMetaData = Collections.unmodifiableList(metaData);
    }

    return cssMetaData;
  }

Note that the List is static and lazy-final.  The same goes for the 
getCssMetaData method in the SimpleStyleableXXXProperty classes.  There is a 
slight performance decrease in those classes as getCssMetaData is looked up 
from a static Map (indexed by Class + css property name) and lazily created as 
needed -- a Map lookup however should be quite fast enough.

I'm sure the design had good reason to do things as they are, and I'm wondering 
if reducing the boilerplate has left me missing something important.

I welcome any insights!

--John


Reply via email to