On Tue, 4 Aug 2026 22:07:27 GMT, Andy Goryachev <[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); }...
>
> modules/javafx.graphics/src/main/java/javafx/scene/layout/StackPaneLayout.java
>  line 164:
> 
>> 162:     @Override
>> 163:     public double minWidth(double height) {
>> 164:         // TODO pre-existing bug, insets not snapped anywhere
> 
> probably not a bug: these methods should not return snapped values (as they 
> might come from properties).  the snapping should be done by the caller.

I think it is a bug; other containers (including the "big" ones like HBox/VBox) 
do snap these.

I think it would lead to subtle issue when mixing snapped/unsnapped content as 
well: for an unsnapped container, you can provide unsnapped sizes, but a 
snapped one should include the space it needs to do correct snapping (and not 
rely on the parent container to also be snapped which is why this problem is 
hidden usually now).

So if a `StackPane` has a child of 50 pixels wide, and insets of 0.6 then 
`minWidth(-1)` should return:
- 0.6 + 50 + 0.6 = 51.2 (unsnapped)
- 1 + 50 + 1 = 52.0 (snapped)

When placed inside a snapped container, both will `ceil()` to 52, but if 
`StackPane` is snapped and its container isn't, it would get only 51.2 pixels 
assigned to it, but it will still try to place things at pixel offsets, meaning 
0.8 pixels of space (or border decoration) would get clipped.

Also I think that if you use a `StackPane` as root for a `Scene` (quite common) 
which doesn't do snapping of its own, and give it insets (not  uncommon) you 
may find that the `Window` is one pixel too small (in either or both 
directions). Usually this is unnoticable as it just crops one pixel of empty 
space, but it could show up as a subtle difference between the left/top and 
right/bottom spacing.

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

PR Review Comment: https://git.openjdk.org/jfx/pull/2241#discussion_r3717620343

Reply via email to