<!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>