“ I've changed the default alignment for Label to TOP_LEFT (the default alignment of the base class Labeled is CENTER_LEFT).”
How can you do that without breaking things? Even though it may be uncommon to set minHeight or prefHeight, that isn’t the point. It still breaks existing code. Scott > On Apr 16, 2021, at 12:48 AM, Michael Strauß <michaelstr...@gmail.com> wrote: > > I've learned a few new things while working on the proposed new layout > algorithm, and added a few new APIs: > > > 1. A central concept of the new algorithm was the notion of a > text-baseline node, indicated by Node::isTextBaseline(). I've come to > realize that this property should percolate upwards in the scene > graph: if a node has a text-baseline, the node's parent should also be > considered to have a text-baseline. Adding this new behavior works > surprisingly well and produces very intuitive layout results. > > > 2. The default behavior of all layout containers is to pick the first > text-baseline child to derive their own baseline offset. I've added > Node::prefBaselineProperty(), which makes it possible to override this > default selection: layout containers now pick the first child that > reports Node::isPrefBaseline(), and only if there is no such child, > they fall back to Node::isTextBaseline(). Developers can use this > property to fine-tune their baseline layouts. > > > 3. Optimization: Controls that contain text will often consist of a > container of some sort and a javafx.scene.text.Text node within it. > Computing the baseline offset of such a control is very easy with the > new layout algorithm: > > public double getBaselineOffset() { > return text.getLayoutBounds().getMinY() + text.getLayoutY() + > text.getBaselineOffset(); > } > > This works because changing text.layoutY will automatically schedule > another layout pass for all of its parents. Re-layouting all parents > is necessary because changing layoutY can change the effective > baseline offset, and changing the baseline offset of any node can have > layout implications on any of its parents. > > However, when we consider the Label control (which is probably among > the most commonly used controls), this can be a bit excessive. Label > controls are often used to display pure text, and as such, we can > often "know" the baseline offset without actually needing to schedule > a second layout pass. This assumption is only correct if the text > within the Label is top-aligned (because if it isn't, the Label > baseline offset can not be known in advance of an actual layout pass). > > To leverage this assumption, I've changed the default alignment for > Label to TOP_LEFT (the default alignment of the base class Labeled is > CENTER_LEFT). In most cases, there will be no visual difference > anyway, because I imagine Label controls will seldomly be set to a > minHeight or prefHeight. > > This specific scenario will enable an optimization where the first > layout pass of Label will not schedule a second layout pass. It might > be possible to find more such scenarios that can benefit from > fast-path optimizations. > > > 4. In order to get a better understanding of the layout process, I > added additional logging to track layout passes. Then I compared the > current algorithm with the new algorithm by tracking the initial > layout after starting a sample program (i.e. all layout activity until > the first frame is rendered). In the following log, "cumulative layout > passes" means how often layoutChildren() has been invoked on any of > the scene graph nodes. The actual log output includes a tree > visualization of the entire scene graph that is being layouted, which > I've removed for the sake or brevity. > > Current algorithm log output: > INFO: Layouting VBox (triggered by scene out-of-pulse), cumulative > layout passes: 49 > INFO: Layouting VBox (triggered by scene pulse), cumulative layout passes: 43 > INFO: Layouting VBox (triggered by scene pulse), cumulative layout passes: 0 > > New algorithm log output: > INFO: Layouting VBox (triggered by scene out-of-pulse), cumulative > layout passes: 86 > INFO: Layouting VBox (triggered by scene pulse), cumulative layout passes: 19 > > A major difference is that the current algorithm will often leave the > scene graph in a 'dirty' layout state after running a complete layout > cycle, which necessitates another layout cycle as part of the next > pulse. The new algorithm, however, leaves the scene graph in a clean > layout state after a complete cycle, which takes more work at first, > but saves work that would otherwise be done in the next pulse. > > > 5. Since the new layout algorithm will leave the scene graph in a > clean state, it is not necessary to repeatedly layout the same thing > (like in Node::doLayoutPass()). Cases like these should be identified > and may be changed to single layout invocations. > > > Overall, I think there's good reason to assume that the proposed > algorithm works and that it produces consistent results for > application developers. At this point it would be useful to know > whether or not to continue with the effort.