<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <p>I have a draft PR for this now.</p>
    <p>I'd appreciate some feedback, before I flesh this out completely
      (I'd need to add CSS documentation for example).</p>
    <p><a class="moz-txt-link-freetext" href="https://github.com/openjdk/jfx/pull/1714">https://github.com/openjdk/jfx/pull/1714</a></p>
    <p>--John<br>
    </p>
    <div class="moz-cite-prefix">On 11/02/2025 23:47, John Hendrikx
      wrote:<br>
    </div>
    <blockquote type="cite"
      cite="mid:7a13841d-af52-4ebb-a30f-8d3866f82285@gmail.com">
      <meta http-equiv="content-type" content="text/html; charset=UTF-8">
      <p>Hi list,</p>
      <p>I've done a little proof of concept where I've made some minor
        modifications to CssStyleHelper to allow the CSS engine to offer
        styleable properties on children, but defined by the container
        class.</p>
      <p>What this means is that we can make it appear that direct
        children of a container like GridPane, HBox and VBox have
        properties like: `vgrow`, `hgrow`, `column-index`, `margin`,
        `halignment`, `fill-width` etc.  The exact names can be chosen
        by the container in question.  For example, I could style a
        child of an HBox like this:</p>
      <p style="margin:0;">.text-field {</p>
      <p style="margin:0;">    -fx-background-color: yellow;</p>
      <p style="margin:0;">    -fx-hbox-hgrow: ALWAYS;</p>
      <p style="margin:0;">    -fx-hbox-margin: 5px;<br>
      </p>
      <p style="margin:0;">}</p>
      <p>This will make it possible to do far more visual styling
        directly in CSS.  As usual, unrecognized properties are ignored,
        so if you put this text field in a VBox, nothing will happen.<br>
      </p>
      <p>How does it work?</p>
      <p>- Containers that wish to add additional styleable properties
        to their direct descendants implement this interface:</p>
      <div style="background-color:#ffffff;padding:0px 0px 0px 2px;">
        <div
style="color:#000000;background-color:#ffffff;font-family:"Consolas";font-size:11pt;white-space:pre;"><p
        style="margin:0;"><span style="color:#0000a0;font-weight:bold;">public</span><span
        style="color:#000000;"> </span><span
        style="color:#0000a0;font-weight:bold;">interface</span><span
        style="color:#000000;"> ChildStyleProvider {</span></p><p
        style="margin:0;"><span style="color:#000000;">    List<CssMetaData<Styleable, ?>> getChildCssMetaData(Node child);</span></p><p
        style="margin:0;"><span style="color:#000000;">}</span></p></div>
      </div>
      <p>- The CssMetaData they provide for these properties looks like
        this for example:<br>
        <br>
      </p>
      <div style="background-color:#ffffff;padding:0px 0px 0px 2px;">
        <div
style="color:#000000;background-color:#ffffff;font-family:"Consolas";font-size:11pt;white-space:pre;"><p
        style="margin:0;"><span style="color:#000000;">            </span><span
        style="color:#0000a0;font-weight:bold;">new</span><span
        style="color:#000000;"> CssMetaData<>(</span><span
        style="color:#2a00ff;">"-fx-hbox-hgrow"</span><span
        style="color:#000000;">, StyleConverter.</span><span
        style="color:#000000;font-style:italic;">getEnumConverter</span><span
        style="color:#000000;">(Priority.</span><span
        style="color:#0000a0;font-weight:bold;">class</span><span
        style="color:#000000;">)) {</span></p><p style="margin:0;"><span
        style="color:#000000;">                </span><span
        style="color:#646464;">@Override</span></p><p style="margin:0;"><span
        style="color:#000000;">                </span><span
        style="color:#0000a0;font-weight:bold;">public</span><span
        style="color:#000000;"> </span><span
        style="color:#0000a0;font-weight:bold;">boolean</span><span
        style="color:#000000;"> isSettable(Styleable styleable) {</span></p><p
        style="margin:0;"><span style="color:#000000;">                    </span><span
        style="color:#7f0055;font-weight:bold;">return</span><span
        style="color:#000000;"> </span><span
        style="color:#0000a0;font-weight:bold;">true</span><span
        style="color:#000000;">;</span></p><p style="margin:0;"><span
        style="color:#000000;">                }</span></p><p
        style="margin:0;">
</p><p style="margin:0;"><span style="color:#000000;">                </span><span
        style="color:#646464;">@Override</span></p><p style="margin:0;"><span
        style="color:#000000;">                </span><span
        style="color:#0000a0;font-weight:bold;">public</span><span
        style="color:#000000;"> StyleableProperty<Priority> getStyleableProperty(Styleable styleable) {</span></p><p
        style="margin:0;"><span style="color:#000000;">                    </span><span
        style="color:#7f0055;font-weight:bold;">return</span><span
        style="color:#000000;"> ChildStyleProvider.</span><span
        style="color:#000000;font-style:italic;">createProp</span><span
        style="color:#000000;">(</span><span
        style="color:#0000a0;font-weight:bold;">this</span><span
        style="color:#000000;">, </span><span style="color:#2a00ff;">"hbox-hgrow"</span><span
        style="color:#000000;">, child);</span></p><p style="margin:0;"><span
        style="color:#000000;">                }</span></p><p
        style="margin:0;"><span style="color:#000000;">            }</span></p></div>
      </div>
      <p>- A special <span style="color:#000000;">StyleableProperty </span>is
        created as the "receiver" of CSS styling that will store the
        value in the Node#getProperties map (where normally these values
        are already stored when using the static methods like
        HBox.setHGrow(Node, Priority) type methods).  This property is
        cached as part of the same getProperties map, so it is only
        created once.<br>
        <br>
        - The CssStyleHelper will see if the parent of the Node being
        styled implements <span style="color:#000000;">ChildStyleProvider,
          and if so will also </span>process these additional
        CssMetaData properties when any are present; this seems to be
        fairly safe to do, as changing a Node's parent will reset all
        its styling already. Some more tests are needed here, if moving
        this forward.<br>
      </p>
      <p>That is basically the change in a nutshell.  Not only does
        setting a property like `-fx-hbox-hgrow` on a child now act as
        if you called `HBox.setHGrow`, changing the style of the child
        can also change these settings and HBox will instantly respond
        to the change.  When the style is completely removed, it will
        also null the hgrow value which is translated as removing that
        key from the Node#getProperties map.<br>
      </p>
      <p>If people think this proposal has some merit, I can flesh it
        out further and make it into a PR.</p>
      <p>--John<br>
      </p>
      <p><br>
      </p>
      <br>
      <p><br>
      </p>
    </blockquote>
  </body>
</html>