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