On Thu, 22 Jan 2026 16:53:09 GMT, Michael Strauß <[email protected]> wrote:

>> Implementation of [enhanced property 
>> metadata](https://gist.github.com/mstr2/2fec0303fc440b8eaeb126befc76eb5c).
>> 
>> ### New API
>> This PR includes the following API additions:
>> 
>> 1. `ReadOnlyProperty.getDeclaringClass()` and its default implementation.
>> 2. The `javafx.beans.property.AttachedProperty` interface.
>> 3. New constructors for all `Simple<*>Property` and `ReadOnly<*>Wrapper` 
>> classes, accepting the declaring class of the property.
>> 
>> The declaring class is stored in a new field in the `Simple<*>Property` 
>> classes. If a legacy constructor is used that doesn't specify the declaring 
>> class, the `ReadOnlyProperty.getDeclaringClass()` default implementation is 
>> called the first time the `Simple<*>Property.getDeclaringClass()` method is 
>> called, and its result is stored for future retrieval.
>> 
>> ### Testing
>> For testing, this PR also includes the 
>> `test.util.property.PropertyMetadataVerifier` tool. It systematically tests 
>> all public and protected properties of a class, and ensures conformance to 
>> the following rules:
>> * `ReadOnlyProperty.getBean()` returns the object instance of the enclosing 
>> class, or the target object instance if the property is an attached property.
>> *  `ReadOnlyProperty.getName()` returns the name of the property, which must 
>> correspond to the name of the property getter (excluding the word 
>> "Property").
>> * `ReadOnlyProperty.getDeclaringClass()` returns the enclosing class of the 
>> property getter.
>> * The declaring class of a `Simple<*>Property` or `ReadOnly<*>Wrapper` must 
>> be specified in the constructor, not resolved at runtime.
>> * `getBean()`, `getName()`, and `getDeclaringClass()` must not be overridden 
>> in subclasses of `Simple<*>Property` or `ReadOnly<*>Wrapper`.
>> * An instance property does not implement `AttachedProperty`.
>> * An instance property has a parameterless property getter.
>> * An attached property implements `AttachedProperty`.
>> * An attached property has a static single-argument property getter that 
>> accepts the target object.
>> * `AttachedProperty.getTargetClass()` returns the class of the single 
>> parameter of the static property getter.
>> * A property getter does not return an instance of `ReadOnly<*>Wrapper`, it 
>> returns the result of calling `ReadOnly<*>Wrapper.getReadOnlyProperty()`.
>> 
>> Many properties in existing JavaFX classes violate the 
>> `PropertyMetadataVerifier` rules in some way or shape. This PR won't address 
>> these issues, this will be done in a future cleanup PR.
>
> Michael Strauß has updated the pull request with a new target base due to a 
> merge or a rebase. The incremental webrev excludes the unrelated changes 
> brought in by the merge/rebase. The pull request contains five additional 
> commits since the last revision:
> 
>  - Merge branch 'master' into feature/property-metadata
>  - review changes
>  - ReadOnlyProperty.getDeclaringClass() tests
>  - doc
>  - Enhanced property metadata

I've run into another scenario where having first-class styleable attached 
properties would make life _much_ easier. I've placed a `TabPane` such that its 
tabs overlap a `HeaderBar`. In order for the header bar to work correctly, I 
need to set the `HeaderBar.dragType` property on the tab pane and on its tabs 
(which are produced by a skin and not easily accessible from JavaFX code).

Actually getting hold of the tabs of a `TabPane` is complicated by the fact 
that they only exist after the skin has been inflated by CSS; they don't exist 
after I've typed `var tabPane = new TabPane()` in code. So I need to manually 
inflate the skin, or defer configuration to the next pulse. After that, I need 
to use `Node.lookupAll(".tab")` to get the nodes that represent the tabs, or I 
need to traverse the children of the tab pane until I've found the tabs. Only 
then can I set the `HeaderBar.dragType` property on those nodes.

If we had styleable attached properties, I could just provide a stylesheet for 
my tab pane:

.tab-pane {
    -fx-headerbar-dragtype: transparent-subtree;
}

.tab-pane .tab {
    -fx-headerbar-dragtype: none;
}

-------------

PR Comment: https://git.openjdk.org/jfx/pull/2015#issuecomment-3863351123

Reply via email to