Hi everyone,

I'm interested in hearing your thoughts on the following proposal,
which could increase the expressiveness of the JavaFX Property API:

Problem
-------
The JavaFX CSS system applies the following order of precedence to
determine the value of a styleable property (in ascending
specificity):
1. user-agent stylesheets
2. values set from code
3. Scene stylesheets
4. Parent stylesheets
5. inline styles

While this system works quite well in general, applications sometimes
need to override individual property values from code. However, this
doesn't work reliably in the presence of Scene or Parent stylesheets.
There are two usual workarounds to solve this problem:

A) Use an inline style instead of setting the property value directly.

This is obviously not a good solution, as you'll lose the strong
typing afforded by the Java language. Additionally, the value must be
a true constant, it can't be an expression or the result of a
computation.

B) Create an `ObservableValue` instance that holds the desired value,
and bind the property to it.

This is a much better solution. However, what we really want is just
the binding semantics: the bound property becomes unmodifiable and has
the highest precedence in the CSS cascade. But the API only gives us
binding semantics if we give it an `ObservableValue`.


Solution
--------
I'm proposing to separate the toggles "binding semantics" and
"observability". While observability requires you to provide an
`ObservableValue`, binding semantics should work with both observable
and regular values.

This is a powerful addition to the Property API, since it increases
the expressiveness of the API in a natural way:

    // instead of:
    rect.setStyle("-fx-fill: red; -fx-width: 200");

    // you can use strongly-typed Java code:
    rect.fillProperty().bindConstant(Color.RED);
    rect.widthProperty().bindConstant(200);

Since the `bindConstant` method accepts a value of the property type,
all features of the Java language can be used to fill in the value.


Implementation
--------------
The following method will be added to the `Property` interface:

    default void bindConstant(T value) {
        bind(ObjectConstant.valueOf(value));
    }

Specialized methods will be added to `BooleanProperty`,
`DoubleProperty`, `FloatProperty`, `IntegerProperty`, and
`LongProperty`, each with one of the preexisting constant wrappers
that are already in the framework.
Some wrappers can be deduplicated (we only ever need two wrapper
instances for boolean values).

Reply via email to