On Tue, 28 Nov 2023 23:34:30 GMT, Andy Goryachev <ango...@openjdk.org> wrote:

>> Provide a public utility method for use by custom and core Nodes to simplify 
>> boilerplate around styleable properties as well as to save some memory.
>> 
>> 
>>     /**
>>      * Utility method which combines {@code CssMetaData} items in one 
>> immutable list.
>>      * <p>
>>      * The intended usage is to combine the parent and the child CSS meta 
>> data for
>>      * the purposes of {@code getClassCssMetaData()} method, see for example 
>> {@link Node#getClassCssMetaData()}.
>>      * <p>
>>      * Example:
>>      * <pre>
>>      * private static final List&lt;CssMetaData&lt;? extends Styleable, ?>> 
>> STYLEABLES = CssMetaData.combine(
>>      *      &lt;Parent>.getClassCssMetaData(),
>>      *      STYLEABLE1,
>>      *      STYLEABLE2
>>      *  );
>>      * </pre>
>>      * This method returns an instance of {@link java.util.RandomAccess} 
>> interface.
>>      *
>>      * @param list the css metadata items, usually from the parent, must not 
>> be null
>>      * @param items the additional items
>>      * @return the immutable list containing all of the items
>>      *
>>      * @since 22
>>      */
>>     public static List<CssMetaData<? extends Styleable, ?>> combine(
>>         List<CssMetaData<? extends Styleable, ?>> list,
>>         CssMetaData<? extends Styleable, ?>... items)
>> 
>> 
>> Problem(s):
>> 
>> - the same less-than-optimal implementation is duplicated throughout the 
>> javafx code base which combines the parent and child styleable properties, 
>> using ArrayList wrapped in a  Collections.unmodifiableList()
>> - the capacity of underlying ArrayList might exceed the number of items, 
>> wasting memory
>> - a potential exists for the custom component developer to inadvertently 
>> create a sub-standard implementation (i.e. return a List which does not 
>> implement RandomAccess interface), or forget to include parent's styleables.
>> 
>> Non-Goals:
>> 
>> - not redesigning the lazy initialization of STYLEABLES list
>> - not changing the way styleables are enumerated in Nodes and Controls
>> - not adding any new methods to JDK (collections)
>> 
>> To Be Discussed:
>> 
>> - it is not clear whether the order of styleables returned by <N extends 
>> Node>.getClassCssMetaData() is of any importance
>> - the current spec for Node.getCssMetaData() specifies the return value as 
>> "The CssMetaData associated with this node, which may include the 
>> CssMetaData of its superclasses.", implying that it may or may not include.  
>> It is unclear whether it must include the parent's styleables (well, except 
>> the Node whose superclass is Obje...
>
> Andy Goryachev has updated the pull request incrementally with one additional 
> commit since the last revision:
> 
>   review comments

The downside of John's proposal is that the metadata list would now be 
duplicated in every node, while currently these lists are only duplicated in 
`Control` nodes. The size of these lists is typically around 20-40 elements.

In any case, expanding on what I wrote earlier, here is how the performance 
requirements could be specified for `getClassCssMetaData`, if we go for "option 
1":

/**
 * Gets an unmodifiable {@code CssMetaData} list for the styleable properties 
of this class.
 * <p>
 * If a derived class declares new styleable properties, it must redeclare this 
method to hide the
 * base method. From the redeclared method, it must return the concatenation of 
the base metadata
 * and the metadata of the newly-added styleable properties.
 * <p>
 * Implementations of this method must satisfy the following performance 
requirements to prevent
 * severe performance degradation in the CSS system:
 * <ol>
 *     <li>The returned list must support random access.
 *     <li>The method must not allocate a new list on each invocation.
 * </ol>
 * It is strongly advised to use {@link CssMetaData#combine} to create the 
concatenated list and
 * store it in a static field:
 * <pre>{@code
 *     private static final List<CssMetaData<? extends Styleable, ?>> 
CSS_METADATA =
 *         CssMetaData.combine(
 *             <Parent>.getClassCssMetaData(),
 *             CUSTOM_CSS_METADATA_1,
 *             CUSTOM_CSS_METADATA_2,
 *             CUSTOM_CSS_METADATA_3
 *         );
 *
 *     public static List<CssMetaData<? extends Styleable, ?>> 
getClassCssMetaData() {
 *         return CSS_METADATA;
 *     }
 * }</pre>
 * Note that in this example, {@code <Parent>} should be substituted with the 
name of the direct base
 * class, even if the direct base class does not have its own {@code 
getClassCssMetaData()} method.
 * This ensures that the code remains correct when such a method is added to 
the direct base class.
 *
 * @return the {@code CssMetaData} list for the styleable properties of this 
class
 * @see CssMetaData#combine
 * @since JavaFX 8.0
 */
public static List<CssMetaData<? extends Styleable, ?>> getClassCssMetaData()

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

PR Comment: https://git.openjdk.org/jfx/pull/1296#issuecomment-1832775656

Reply via email to