<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
{font-family:"Cambria Math";
panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
{font-family:"Iosevka Fixed SS16";
panose-1:2 0 5 9 3 0 0 0 0 4;}
@font-face
{font-family:"Times New Roman \(Body CS\)";
panose-1:2 11 6 4 2 2 2 2 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{margin:0in;
font-size:10.0pt;
font-family:"Calibri",sans-serif;}
a:link, span.MsoHyperlink
{mso-style-priority:99;
color:blue;
text-decoration:underline;}
span.EmailStyle19
{mso-style-type:personal-reply;
font-family:"Iosevka Fixed SS16";
color:windowtext;}
.MsoChpDefault
{mso-style-type:export-only;
font-size:10.0pt;
mso-ligatures:none;}
@page WordSection1
{size:8.5in 11.0in;
margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
{page:WordSection1;}
--></style>
</head>
<body lang="EN-US" link="blue" vlink="purple" style="word-wrap:break-word">
<div class="WordSection1">
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">I like the idea.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">I wonder if it is possible to reduce the amount of boilerplate code? For example, a CssMetaData can have a<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""><o:p> </o:p></span></p>
<p class="MsoNormal" style="text-indent:.5in"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">setGetter(Function<S, StyleableProperty<V>> getter)<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">method which supplies the property reference? This way CssMetaData.isSettable(Node) and CssMetaData.getStyleableProperty(Node) can be implemented in the base class (there
are more complicated cases, so perhaps setIsSettable(Predicate<Node>) would also be required).<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">Example:<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""><o:p> </o:p></span></p>
<p class="MsoNormal" style="background:#E8F2FE"><span lang="FR" style="font-size:12.0pt;font-family:"Iosevka Fixed SS16";color:black">CssMetaData.<ControlExample,Font>of(</span><span lang="FR" style="font-size:12.0pt;font-family:"Iosevka Fixed SS16";color:#2A00FF">"-fx-font"</span><span lang="FR" style="font-size:12.0pt;font-family:"Iosevka Fixed SS16";color:black">,
Font.getDefault(), (n) -> n.font)<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="FR" style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">Just a thought. What do you think?<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">-andy<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""><o:p> </o:p></span></p>
<div id="mail-editor-reference-message-container">
<div>
<div style="border:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0in 0in 0in">
<p class="MsoNormal" style="margin-bottom:12.0pt"><b><span style="font-size:12.0pt;color:black">From:
</span></b><span style="font-size:12.0pt;color:black">openjfx-dev <openjfx-dev-retn@openjdk.org> on behalf of Michael Strauß <michaelstrau2@gmail.com><br>
<b>Date: </b>Sunday, December 3, 2023 at 22:02<br>
<b>To: </b>openjfx-dev <openjfx-dev@openjdk.org><br>
<b>Subject: </b>Reflective discovery of styleable properties<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">Following up the discussion around the CssMetaData API, I'd like to<br>
chime in with yet another idea. To recap, here's Nir's summary of the<br>
current API [0]:<br>
<br>
"Let's look at what implementation is required from a user who wants<br>
to write their own styleable control:<br>
1. Create styleable properties.<br>
2. Create a list of these properties to be passed on.<br>
3. Create a public static method that returns the concatenation of<br>
this list with the one of its parent. (This method happens to be<br>
poorly documented, as mstr said.)<br>
4. Create a public non-static method that calls the static method in a<br>
forced-override pattern because otherwise you will be calling the<br>
wrong static method. (This method's docs seem to be just wrong because<br>
you don't always want to delegate to Node's list.)"<br>
<br>
<br>
I think this could reasonably be replaced with the following<br>
implementation requirements:<br>
1. Create styleable properties.<br>
2. That's it.<br>
<br>
Let's look at what we're actually trying to do: create a list of<br>
CSS-styleable property metadata of a class. But we can easily do that<br>
without all of the boilerplate code.<br>
<br>
When ´Node.getCssMetaData()` is invoked, all public methods of the<br>
class are reflectively enumerated, and metadata is retrieved from<br>
`Property` and `StyleableProperty` getters. This is a price that's<br>
only paid once for any particular class (i.e. not for every instance).<br>
The resulting metadata list is cached and reused for all instances of<br>
that particular class.<br>
<br>
As a further optimization, metadata lists are also cached and<br>
deduplicated for Control/Skin combinations (currently every Control<br>
instance has its own copy of the metadata list).<br>
<br>
Another benefit of this approach is that the CssMetaData can now be<br>
co-located with the property implementation, and not be kept around in<br>
other parts of the source code file. Here's how that looks like when a<br>
new "myValue" property is added to MyClass:<br>
<br>
StyleableDoubleProperty myValue =<br>
new SimpleStyleableDoubleProperty(this, "myValue") {<br>
<br>
static final CssMetaData<MyClass, Number> METADATA =<br>
new CssMetaData<MyClass, Number>(<br>
"-fx-my-value",<br>
SizeConverter.getInstance(),<br>
USE_COMPUTED_SIZE) {<br>
@Override<br>
public boolean isSettable(MyClass node) {<br>
return !node.myValue.isBound();<br>
}<br>
<br>
@Override<br>
public StyleableProperty getStyleableProperty(<br>
MyClass node) {<br>
return node.myValue;<br>
}<br>
};<br>
<br>
@Override<br>
public CssMetaData getCssMetaData() {<br>
return METADATA;<br>
}<br>
};<br>
<br>
public final DoubleProperty myValueProperty() {<br>
return myValue;<br>
}<br>
<br>
It is not required to override the `getCssMetaData()` method, nor is<br>
it required to redeclare a new static `getClassCssMetaData()` method.<br>
It is also not required to manually keep the list of styleable<br>
properties in sync with the list of CSS metadata.<br>
<br>
I've prototyped this concept for the `Node`, `Region` and `Control` classes [1].<br>
<br>
[0] <a href="https://mail.openjdk.org/pipermail/openjfx-dev/2023-December/044046.html">
https://mail.openjdk.org/pipermail/openjfx-dev/2023-December/044046.html</a><br>
[1] <a href="https://github.com/openjdk/jfx/pull/1299">https://github.com/openjdk/jfx/pull/1299</a><o:p></o:p></span></p>
</div>
</div>
</div>
</div>
</body>
</html>