Circling back to a new layout algorithm
John Hendrikx
hjohn at xs4all.nl
Sat Nov 13 15:23:47 UTC 2021
I haven't taken a close look, but I've done some automated layout work
before. The baseline layout seems to be an interesting kind of problem
where controls can influence each other, where normally they are mostly
independent.
An iterative approach may be the only viable one, but it does leave me
thinking if there isn't a better option. My primary concern is that it
is relatively easy to construct a situation that would not converge quickly.
Given a fixed height control A with some text that is top aligned and
which has a significant amount of padding at the bottom (maybe it has an
image below the text), and another unbounded control B with its text
vertically centered. Every time the algorithm tries to align the
baselines of these two controls, the container grows a little bit
bigger. This enlarges control B, pushing the baseline down (as it is
centered), which in turn means that aligning control A on that new
baseline will mean its bottom padding now extends beyond the containers
size, and the container is enlarged again... Visually:
+-------+ +-------+
| A | | |
| | | B |
| | | |
+-------+ +-------+
After 1 iteration:
+-------+
+-------+ | |
| A | | |
| | | B |
| | | |
+-------+ +-------+
After 2 iterations:
+-------+
| |
+-------+ | |
| A | | B |
| | | |
| | | |
+-------+ +-------+
In ASCII art this converges relatively fast, but it all depends on the
size of control A and how large its bottom padding is.
I was wondering if this can be improved upon somehow.
--John
On 05/11/2021 03:31, Michael Strauß wrote:
> I previously proposed a new iterative layout algorithm [1] that
> supports baseline alignment and introduces new APIs to give developers
> control over the way nodes are aligned. This is a solution to the
> long-standing problem that JavaFX cannot reliably lay out nodes that
> are aligned on their baseline [2]. The new layout algorithm might also
> fix some issues where the scene graph layout only settles after
> interacting with the controls (for example, by clicking).
>
> I've created a small application that shows the new APIs and a
> correctly working baseline-aligned layout [3]. In addition to that, I
> also built SceneBuilder with both the old and new layout system, and
> played around with it to find out whether there were any regressions
> or visual differences. So far, I haven't found any.
>
> In order to move this forward, I think it would be a good idea to test
> the latest version of the new layout system in more real-world JavaFX
> applications. Any help from JavaFX application developers is greatly
> appreciated. It's as easy as checking out the JavaFX sources from the
> PR [1], building a local SDK and linking your application with the
> binaries.
>
>
> Finally, here's a high-level overview of the new algorithm:
>
> When Parent::layout() is called on a layout root (i.e. a scene root or
> an unmanaged node), it will lay out its children in a loop until the
> scene graph under the layout root is fully laid out, which means it is
> clean and doesn't require further layout. The totality of layout
> activity for a single layout root is called "layout cycle". A layout
> cycle will often take a few layout passes to finish (but not more than
> 2 in most cases). There is no limit on how often Parent::layout() will
> iterate to lay out its children, so in principle, this could lead to
> an infinite layout loop.
>
> One source of infinite layout loops are incorrectly implemented controls:
>
> class PathologicalControl extends Region {
> final Text text = new Text("foo");
>
> PathologicalControl() {
> getChildren().add(text);
> }
>
> @Override
> protected void layoutChildren() {
> text.relocate(0, text.getLayoutY() + 10);
> }
> }
>
> In this example, each call to layoutChildren() moves down the text
> node another 10 pixels from where it was, which causes the layout
> algorithm to schedule yet another layout pass. It's an infinite loop.
>
> The layout system detects this by tracking how often a node
> invalidates the scene graph in a single layout cycle. If a node
> exceeds a threshold of 100 invalidations, it will be suspended from
> layout and can no longer invalidate the scene graph in the current
> layout cycle. A warning will be logged to notify developers of that
> fact.
>
>
> [1] https://github.com/openjdk/jfx/pull/433
> [2] https://bugs.openjdk.java.net/browse/JDK-8090261
> [3] https://github.com/mstr2/jfx-layout-sample
>
More information about the openjfx-dev
mailing list