On Thu, 15 Jan 2026 20:48:57 GMT, Michael Strauß <[email protected]> wrote:

> > Are you referring to media queries for the window size when you say that 
> > sizing can influence styling? The others can be resolved similar to how 
> > `ScrollPane` does this (see below).
> 
> Yes, but also in a more general sense. Applications might also manually add 
> or remove style classes depending on the size of controls.

True, and that's fine, but I think we need to warn if they do that during 
layout.  That's just not the right time, as layouts are very restricted in what 
you should be doing.  Most users never write a `layoutChildren` method and most 
aren't crazy enough to do these things in `compute` methods.  They just need to 
be aware of things like pre/post layout listeners, and we need to ensure that 
user code is not called during layout (see below for cells...)

> That's true, but it's also less powerful than a dedicated two-pass approach. 
> The main difference is that WPF/Android communicate down constraints to 
> children during this first pass, asking: "given my available size, how large 
> would you like to be?" The compute methods of JavaFX don't communicate any 
> information from parents to their children, which is why children can't 
> change their answer depending on the constraints imposed by their parents.

Yeah, FX has a limited variant of this with Content Bias.  It can ask "If I 
give you 400 pixels of width, how much height do you want?"

> > `ScrollPane` handles that in one pass. Basically it computes the size of 
> > the children, and if it determines there is need of a scroll bar, it does 
> > those calculations again (which can result in the appearance of the 2nd 
> > scrollbar, and the calculations are repeated one more time; this is quite 
> > visible in `ScrollPaneSkin`). In effect, it solves this problem internally 
> > without waiting for another layout pass, as compute methods can be called 
> > as often as desired.
> 
> > I think doing a loop of layout passes up to a limit is fine, although I'm 
> > not sure if CSS needs to take part in that. One should not be changing 
> > styles during layout, that's a pre-layout concern (which is before CSS 
> > runs) and not something to do in the `compute` chain of methods nor the 
> > `layoutChildren` methods.
> 
> Let's assume a control where the number of children depend on its size. Maybe 
> it arranges a set of nodes that it was provided with in some way, and fills 
> the remaining "unused" slots in its layout with placeholder nodes. This 
> implies that the control only knows how many placeholder nodes it needs after 
> it was laid out. Adding those nodes after the layout pass is done means that 
> they now don't have CSS styling. I think a case like this is already 
> accounted for in the existing layout system, but solving this correctly in an 
> iterative system probably means that CSS needs to be part of the loop.

Although I think I see why CSS needs to be added to the loop (and more), I 
still think that you should refrain from adding/removing children during 
layout, especially if they are cells.  This still best handled in a pre-layout 
listener because if there is no follow-up loop, you will see CSS flicker (white 
background).  Even in a looped system this can then occur when loops are 
exhausted.

The View classes are good examples of dynamic controls that need to have more 
or less children depending on their size. They should be initializing these 
children (including calling `Cell#updateItem`) as part of a pre-layout 
listener.  This allows:

- Flicker free adding of children (CSS runs still, no need to rely on a next 
loop)
- User code doing whatever they want in `updateItem` which is not the case if 
that method is called during the layout phase (there are bugs currently where 
sometimes `updateItem` is called during layout.. very bad, as users are unaware 
that this is the case)

If it turns out there weren't enough (invisible) cells to fill the entire view 
port, then the View class can request another layout pass, which can be looped 
immediately (and should include calling the pre-layout listeners again).  So I 
think you are right here  that we should include CSS in the loop so newly added 
children in a 2nd loop also get the correct styles (hopefully it's cheap if not 
much changed).  So I think it perhaps could work like this:

1. Pulse starts
2. Pre-layout listeners called
   - View controls add/remove children, call `updateItem` based on their 
current size
      - `updateItem` can do whatever it wants, including modifying styles, 
adding/removing children, user code need not worry about layout semantics
3. CSS pass

LAYOUT STARTS -- refrain from doing "more" work besides positioning/sizing

4. Sizes get computed (by `resizeRootToPreferredSize`) down to leafs
5. Layout methods are called (according to dirty status) down to leafs

LAYOUT ENDS

6. Either during layout or in a post-layout listener, the View class discovers 
it did not have enough cells, it asks for a new layout
7. After post layout listeners have run, check if another layout is needed 
immediately, go to step 2 (unless limit exceeded)
8. Pulse ends

In this way we can prevent unnecessary layouts, and also prevent doing 
dangerous things during layout.

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

PR Comment: https://git.openjdk.org/jfx/pull/1945#issuecomment-3757227855

Reply via email to