On Mon, 3 Aug 2026 16:34:14 GMT, John Hendrikx <[email protected]> wrote:

> This PR shows how virtual layouts could be implemented, as discussed on the 
> mailinglist: 
> https://mail.openjdk.org/archives/list/[email protected]/thread/PLNSQ3ZI63AVKEFKNT5GT6WHAD2GYMPC/
> 
> It would work by making new non-Node containers called Layouts which can 
> contain a mix of either Nodes or other Layouts. Allowing Layouts to nest 
> makes it possible to create a substructure similar to how nesting 
> StackPane/HBox/VBox etc works today. An example is a simple control that has 
> a graphic with a title and subtitle stacked vertically next to it:
> 
> 
> +-------------+-----------------------------------------+
> |             |                                         |
> |             |                 Title                   |
> |             |                                         |
> |   Graphic   +-----------------------------------------+
> |             |                                         |
> |             |                Subtitle                 |
> |             |                                         |
> +-------------+-----------------------------------------+
> 
> For a control to model this, it would need a VBox containing the Title and 
> Subtitle, and an HBox containing the Graphic and the VBox.  The two 
> containers are heavy-weight Nodes and this incurs sufficiently large memory 
> and performance penalties that most standard JavaFX controls will opt to 
> instead roll their own layout code to avoid paying the cost for these.
> 
> With virtual layouts, the control could make use of non-Node containers. The 
> control would add its three children (Graphic, Title and Subtitle) as direct 
> children for display in the scene graph, but would offload their positioning 
> to a virtual layout.  This roughly looks like this:
> 
> 
>   public class TitledGraphic extends Region {
>       private final HBoxLayout root;
> 
>       public TitledGraphic(Node graphic, String titleText, String 
> subtitleText) {
>           // Flat scene graph:
>           getChildren().addAll(graphic, title, subtitle);
> 
>           // Create virtual layout:
>           root = HBoxLayout.of(graphic, VBoxLayout.of(title, subtitle));
>       }
> 
>       @Override
>       protected void layoutChildren() {
>           root.resizeRelocate(0, 0, getWidth(), getHeight());
>       }
> 
>       @Override protected double computeMinWidth(double height)   { return 
> root.minWidth(height); }
>       @Override protected double computeMinHeight(double width)   { return 
> root.minHeight(width); }
>       @Override protected double computePrefWidth(double height)  { return ...

really like the concept.

Some initial high level comments, will review this in more detail later (count 
me in as reveiwer for this one!)

modules/javafx.graphics/src/main/java/com/sun/javafx/scene/layout/Snapper.java 
line 37:

> 35:  * operations used by layout math.
> 36:  */
> 37: public interface Snapper {

Really like the idea of the `Snapper`.

What I would really like to see documented is what values developers should 
snap.
Maybe we could add all the information we gathered over the years here.
So the conclusion of the mailing list entries, 
https://github.com/openjdk/jfx/pull/1948, 
https://github.com/openjdk/jfx/pull/1111 (maybe even revive this one after) and 
there are probably more.

Especially: Snap only final values once (before they are returned or used as 
x/y/w/h (If I understood that right).

modules/javafx.graphics/src/main/java/com/sun/javafx/scene/layout/Snapper.java 
line 172:

> 170:     double snapPositionY(double value);
> 171:     double snapSpaceX(double value);
> 172:     double snapSpaceY(double value);

could we perhaps have just `snapPositionX/Y`? Since `snapSpaceX/Y` is always 
doing the same, I don't see any point to have both (and I already disliked that 
in the current `Region` implementation)

modules/javafx.graphics/src/main/java/javafx/scene/layout/LayoutSupport.java 
line 62:

> 60:             alt = computedBoundedHeight(snapper, child, fillHeight, 
> contentHeight);
> 61:         }
> 62:         return left + snapper.snapSizeX(child.minWidth(alt)) + right;

What I was always wondering here (since this is the same as in `Region`: Why do 
we not snap the final value? We especially would also save some cycles if we do 
not snap intermediate values and snap them again later. Same on the other 
methods - maybe something to improve later?

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

PR Review: https://git.openjdk.org/jfx/pull/2241#pullrequestreview-4889574763
PR Review Comment: https://git.openjdk.org/jfx/pull/2241#discussion_r3741492916
PR Review Comment: https://git.openjdk.org/jfx/pull/2241#discussion_r3741476013
PR Review Comment: https://git.openjdk.org/jfx/pull/2241#discussion_r3741495897

Reply via email to