<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
I haven't looked at this proposal yet, but there are some
interesting ideas here worth further discussion.<br>
<br>
I just wanted to weigh in on the cssref piece. As Andy indicated,
cssref.html is the normative specification for JavaFX CSS
properties. And no, it can't be (fully) auto-generated.<br>
<br>
The only way I could imagine tooling being involved is to
auto-generate the individual property tables for including in the
html somehow (which would need some sort of javadoc-inspired
facility to add comments in the table, etc). And while an
interesting concept, it would likely be a rather large effort for
relatively little gain.<br>
<br>
-- Kevin<br>
<br>
<br>
<div class="moz-cite-prefix">On 12/7/2023 7:48 AM, Andy Goryachev
wrote:<br>
</div>
<blockquote type="cite" cite="mid:DM5PR1001MB21720D19000CFE7B144E1E09E58BA@DM5PR1001MB2172.namprd10.prod.outlook.com">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<style>@font-face
{font-family:"Cambria Math";
panose-1:2 4 5 3 5 4 6 3 2 4;}@font-face
{font-family:"Yu Gothic";
panose-1:2 11 4 0 0 0 0 0 0 0;}@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;}@font-face
{font-family:"\@Yu Gothic";
panose-1:2 11 4 0 0 0 0 0 0 0;}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.EmailStyle18
{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;}div.WordSection1
{page:WordSection1;}</style>
<div class="WordSection1">
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">>
</span><span style="font-size:11.0pt">I think that the CSS
reference should be generated from the source code, which is
something the annotation processor can do.<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"">Surely,
you don't suggest we should change the CSS ref?<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""><a href="https://openjfx.io/javadoc/21/javafx.graphics/javafx/scene/doc-files/cssref.html" moz-do-not-send="true" class="moz-txt-link-freetext">https://openjfx.io/javadoc/21/javafx.graphics/javafx/scene/doc-files/cssref.html</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"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">I
subscribe to a school of thought that requires
specifications written by humans for humans. The CSS
reference is, in my opinion, an authoritative source, so I
would be against developing any tooling that generates it
from the source code.<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">Nir
Lisker <a class="moz-txt-link-rfc2396E" href="mailto:nlisker@gmail.com"><nlisker@gmail.com></a><br>
<b>Date: </b>Thursday, December 7, 2023 at 01:54<br>
<b>To: </b>Andy Goryachev
<a class="moz-txt-link-rfc2396E" href="mailto:andy.goryachev@oracle.com"><andy.goryachev@oracle.com></a><br>
<b>Cc: </b>Michael Strauß
<a class="moz-txt-link-rfc2396E" href="mailto:michaelstrau2@gmail.com"><michaelstrau2@gmail.com></a>, openjfx-dev
<a class="moz-txt-link-rfc2396E" href="mailto:openjfx-dev@openjdk.org"><openjfx-dev@openjdk.org></a><br>
<b>Subject: </b>Re: [External] : Re: Reflective
discovery of styleable properties<o:p></o:p></span></p>
</div>
<div>
<blockquote style="border:none;border-left:solid #CCCCCC 1.0pt;padding:0in 0in 0in 6.0pt;margin-left:4.8pt;margin-right:0in">
<p class="MsoNormal"><span style="font-size:11.0pt"> - I
would recommend against the scanner figuring out the
property name: the property > names are codified
by the CSS reference which serves as a normative
document in this case <o:p></o:p></span></p>
</blockquote>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"> <o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">I
think that the CSS reference should be generated
from the source code, which is something the
annotation processor can do.<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<blockquote style="border:none;border-left:solid #CCCCCC 1.0pt;padding:0in 0in 0in 6.0pt;margin-left:4.8pt;margin-right:0in">
<p class="MsoNormal"><span style="font-size:11.0pt">-
isSettable() logic might be more complex than (prop
== null && !(prop.isBound)), see Node.tra</span><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">nslateXProperty.
How would that work with annotations?</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</blockquote>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">From
what John said, you can fall back to the CSSMetaData
way if the defaults are not good for you. <o:p></o:p></span></p>
</div>
</div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
<div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">On
Wed, Dec 6, 2023 at 6:21 PM Andy Goryachev <<a href="mailto:andy.goryachev@oracle.com" moz-do-not-send="true" class="moz-txt-link-freetext">andy.goryachev@oracle.com</a>>
wrote:<o:p></o:p></span></p>
</div>
<blockquote style="border:none;border-left:solid #CCCCCC 1.0pt;padding:0in 0in 0in 6.0pt;margin-left:4.8pt;margin-right:0in">
<div>
<div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">I
also like this idea very much. Still needs a
reflective scanner, but it's far more easier
to understand and use.</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><span style="font-size:11.0pt"><o:p></o:p></span></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">A
couple of comments/questions:</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><span style="font-size:11.0pt"><o:p></o:p></span></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">- I
would recommend against the scanner figuring
out the property name: the property names are
codified by the CSS reference which serves as
a normative document in this case</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><span style="font-size:11.0pt"><o:p></o:p></span></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">-
isSettable() logic might be more complex than
(prop == null && !(prop.isBound)), see
Node.translateXProperty. How would that work
with annotations?</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><span style="font-size:11.0pt"><o:p></o:p></span></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">What
do you think?</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><span style="font-size:11.0pt"><o:p></o:p></span></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">-andy</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><span style="font-size:11.0pt"><o:p></o:p></span></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><span style="font-size:11.0pt"><o:p></o:p></span></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><span style="font-size:11.0pt"><o:p></o:p></span></p>
<div id="m_-3923328145871554435mail-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="mso-margin-top-alt:auto;margin-bottom:12.0pt"><b><span style="font-size:12.0pt;color:black">From:
</span></b><span style="font-size:12.0pt;color:black">Nir
Lisker <<a href="mailto:nlisker@gmail.com" target="_blank" moz-do-not-send="true" class="moz-txt-link-freetext">nlisker@gmail.com</a>><br>
<b>Date: </b>Wednesday, December 6,
2023 at 02:37<br>
<b>To: </b>Andy Goryachev <<a href="mailto:andy.goryachev@oracle.com" target="_blank" moz-do-not-send="true" class="moz-txt-link-freetext">andy.goryachev@oracle.com</a>><br>
<b>Cc: </b>Michael Strauß <<a href="mailto:michaelstrau2@gmail.com" target="_blank" moz-do-not-send="true" class="moz-txt-link-freetext">michaelstrau2@gmail.com</a>>,
openjfx-dev <<a href="mailto:openjfx-dev@openjdk.org" target="_blank" moz-do-not-send="true" class="moz-txt-link-freetext">openjfx-dev@openjdk.org</a>><br>
<b>Subject: </b>[External] : Re:
Reflective discovery of styleable
properties</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt">I thought about
the option of reflection, but I opted to
propose annotations instead. The
following is my reasoning.<o:p></o:p></span></p>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt"> <o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt">Firstly,
reflection is very magic-y. The author
of the class has no indication of what
side effects happen due to the code
they write, the output (css handling
in this case) comes out of nowhere
from their perspective. As with other
reflection cases, it is a "pull"
rather than "push" approach - you
don't write what should happen, you
let someone else decide that. For
writers of skin/control classes, this
means that they need to know exactly
what constitutes a hook for the
reflection mechanism, or face
surprises. There is no compile time
check that tells you whether you have
declared your styleable property
properly or not (without an external
ad-hoc checker).<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt">We do this
somewhat with properties - any method
of the form "...property()" gets
special treatment, but this is for the
docs. I don't think we have code that
depends on this other than in tests.<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt"> <o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt">Secondly, the
proposed mechanism depends on the
runtime type, not the declared type.
As a user, I see no indication in the
API whether a property is styleable or
not. This is also (what I would
consider) a problem with the current
state. When I thought about using
reflection to solve this, I at least
thought to specify the declared type
of the property as styleable, like
StyleableBooleanProperty instead of
BooleanProperty (restricting the
returned type is backwards
compatible). A downside of this is
that it gives access to the methods of
StyleableProperty, which are not
useful for the user, I think, but
maybe someone has a use for them.<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt"> <o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt">Thirdly,
maybe I want to declare a styleable
property not to be used automatically.
I can't think off the top of my head
when I would want to do that, but I'm
also not a heavy css user. Are we sure
that just initializing a property with
a styleable runtime type should
*always* be caught by this process?<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt"> <o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt">To compare,
annotations have the following
benefits:<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt"> <o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt">Firstly, they
are declarative, which means no
surprises for the class author
(WYSIWYG). This also allows more
flexibility/control over which
properties get special treatment via
an opt-in mechanism.<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt"> <o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt">Secondly,
They can also be displayed in the
JavaDocs (via @Documented) with their
assigned values. For example, the
padding property of Region can be
annotated
with @Styleable(property="-fx-padding"),
informing the user both that this
value can be set by css, and how to do
it. Interestingly, the annotation
doesn't need to be public API to be
displayed, so we are not bound by
contracts.<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt"> <o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt">In terms of
similarities:<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt"> <o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt">In both the
reflection and the annotation
proposals, the steps are:<o:p></o:p></span></p>
</div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt">1. Create
styleable properties.<br>
2. That's it.<o:p></o:p></span></p>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt">It's just
that step 1 also adds an annotation to
the creation of the property (which
was/is a 2-step process anyway,
declaring the property and its css
metadata).<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt"> <o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt">Annotations
also require a processor to read the
data from their values and target (the
field/method). This is a bit of work,
but Michael's CssMetaDataCache class
is basically that - read the data from
the class (via reflection or
annotations) and store it in a map.
The logic should be the same, just the
method to obtain the data is
different. Both, as a result, have the
benefits of handling control/skin
combinations (what I mentioned in the
point "<span style="color:#E8E6E3">Usable
both in controls and in skins (or
other classes)")</span>.<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt"> <o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt">The benefit
of co-locating the property and its
css metadata in the class itself also
remains.<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt"> <o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt"> <o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt">To summarize,
both approaches eliminate all the
clutter of writing styleable
properties (John, will you like to
create styleable properties now? [1]
:) ), both apply the flexibility of
caching per class, both allow better
structuring of the class, but they
read the properties differently and
have a different level of
declarativness.<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt"> <o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt">[1] <a href="https://mail.openjdk.org/pipermail/openjfx-dev/2023-December/044010.html" target="_blank" moz-do-not-send="true" class="moz-txt-link-freetext">https://mail.openjdk.org/pipermail/openjfx-dev/2023-December/044010.html</a><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt"> <o:p></o:p></span></p>
</div>
</div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt"> <o:p></o:p></span></p>
<div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt">On Tue, Dec
5, 2023 at 11:21 PM Andy Goryachev
<<a href="mailto:andy.goryachev@oracle.com" target="_blank" moz-do-not-send="true" class="moz-txt-link-freetext">andy.goryachev@oracle.com</a>>
wrote:<o:p></o:p></span></p>
</div>
<blockquote style="border:none;border-left:solid #CCCCCC 1.0pt;padding:0in 0in 0in 6.0pt;margin-left:4.8pt;margin-top:5.0pt;margin-right:0in;margin-bottom:5.0pt">
<div>
<div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">I
like the idea.</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><span style="font-size:11.0pt"><o:p></o:p></span></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><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</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><span style="font-size:11.0pt"><o:p></o:p></span></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;text-indent:.5in">
<span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">setGetter(Function<S,
StyleableProperty<V>>
getter)</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><span style="font-size:11.0pt"><o:p></o:p></span></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><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).</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><span style="font-size:11.0pt"><o:p></o:p></span></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">Example:</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><span style="font-size:11.0pt"><o:p></o:p></span></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;background:#E8F2FE">
<span style="font-size:12.0pt;font-family:"Iosevka Fixed SS16";color:black" lang="FR">CssMetaData.<ControlExample,Font>of(</span><span style="font-size:12.0pt;font-family:"Iosevka Fixed SS16";color:#2A00FF" lang="FR">"-fx-font"</span><span style="font-size:12.0pt;font-family:"Iosevka Fixed SS16";color:black" lang="FR">, Font.getDefault(),
(n) -> n.font)</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"" lang="FR"> </span><span style="font-size:11.0pt"><o:p></o:p></span></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">Just
a thought. What do you think?</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><span style="font-size:11.0pt"><o:p></o:p></span></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">-andy</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><span style="font-size:11.0pt"><o:p></o:p></span></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><span style="font-size:11.0pt"><o:p></o:p></span></p>
<div id="m_-3923328145871554435m_-7571650920342053996m_640328469919311222m_-4650580218595929338mail-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="mso-margin-top-alt:auto;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 <<a href="mailto:openjfx-dev-retn@openjdk.org" target="_blank" moz-do-not-send="true" class="moz-txt-link-freetext">openjfx-dev-retn@openjdk.org</a>> on
behalf of Michael Strauß
<<a href="mailto:michaelstrau2@gmail.com" target="_blank" moz-do-not-send="true" class="moz-txt-link-freetext">michaelstrau2@gmail.com</a>><br>
<b>Date: </b>Sunday,
December 3, 2023 at 22:02<br>
<b>To: </b>openjfx-dev
<<a href="mailto:openjfx-dev@openjdk.org" target="_blank" moz-do-not-send="true" class="moz-txt-link-freetext">openjfx-dev@openjdk.org</a>><br>
<b>Subject: </b>Reflective
discovery of styleable
properties</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><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" target="_blank" moz-do-not-send="true" class="moz-txt-link-freetext">
https://mail.openjdk.org/pipermail/openjfx-dev/2023-December/044046.html</a><br>
[1] <a href="https://urldefense.com/v3/__https:/github.com/openjdk/jfx/pull/1299__;!!ACWV5N9M2RV99hQ!K7nDyvMP0PzEOLu-h9yGCoHIoSnny6LJ5acSISP81wBjJjP2z4VcDA6CIMU_Wvzxv2QJgPTsB6F9wtnzMK97$" target="_blank" moz-do-not-send="true">
https://github.com/openjdk/jfx/pull/1299</a><o:p></o:p></span></p>
</div>
</div>
</div>
</div>
</div>
</div>
</blockquote>
</div>
</div>
</div>
</div>
</div>
</div>
</blockquote>
</div>
</div>
</div>
</div>
</blockquote>
<br>
</body>
</html>