diff --git a/modules/javafx.controls/src/test/java/test/javafx/scene/control/skin/ToolBarSkinTest.java b/modules/javafx.controls/src/test/java/test/javafx/scene/control/skin/ToolBarSkinTest.java index f4da91c99c2..7be09baa0dc 100644 --- a/modules/javafx.controls/src/test/java/test/javafx/scene/control/skin/ToolBarSkinTest.java +++ b/modules/javafx.controls/src/test/java/test/javafx/scene/control/skin/ToolBarSkinTest.java @@ -87,14 +87,14 @@ public void overflowMenuNotShowingWithDifferentRenderScales() { 2.25 }; - Rectangle rect = new Rectangle(100, 100); - ToolBar toolBar = new ToolBar(rect); - toolBar.setSkin(new ToolBarSkin(toolBar)); - for (var orientation : Orientation.values()) { - toolBar.setOrientation(orientation); - for (double scale : renderScales) { + Rectangle rect = new Rectangle(100, 100); + ToolBar toolBar = new ToolBar(rect); + toolBar.setSkin(new ToolBarSkin(toolBar)); + + toolBar.setOrientation(orientation); + Stage stage = new Stage(); stage.renderScaleXProperty().bind(DoubleConstant.valueOf(scale)); stage.renderScaleYProperty().bind(DoubleConstant.valueOf(scale)); diff --git a/modules/javafx.graphics/src/main/java/javafx/scene/Node.java b/modules/javafx.graphics/src/main/java/javafx/scene/Node.java index c9f3ee20387..79fd9e5dc36 100644 --- a/modules/javafx.graphics/src/main/java/javafx/scene/Node.java +++ b/modules/javafx.graphics/src/main/java/javafx/scene/Node.java @@ -2850,7 +2850,7 @@ protected void invalidated() { final Parent p = getParent(); // Propagate layout if this change isn't triggered by its parent - if (p != null && !p.isCurrentLayoutChild(Node.this)) { + if (p != null && !p.inLayoutChildren()) { if (isManaged()) { // Force its parent to fix the layout since it is a managed child. p.requestLayout(true); @@ -2924,7 +2924,7 @@ protected void invalidated() { final Parent p = getParent(); // Propagate layout if this change isn't triggered by its parent - if (p != null && !p.isCurrentLayoutChild(Node.this)) { + if (p != null && !p.inLayoutChildren()) { if (isManaged()) { // Force its parent to fix the layout since it is a managed child. p.requestLayout(true); diff --git a/modules/javafx.graphics/src/main/java/javafx/scene/Parent.java b/modules/javafx.graphics/src/main/java/javafx/scene/Parent.java index 007d161d9dc..7c51e90fed4 100644 --- a/modules/javafx.graphics/src/main/java/javafx/scene/Parent.java +++ b/modules/javafx.graphics/src/main/java/javafx/scene/Parent.java @@ -984,6 +984,19 @@ boolean isPerformingLayout() { return performingLayout; } + private boolean inLayoutChildren; + + /** + * Returns whether this node is currently running its {@link #layoutChildren()} + * method. This is useful to detect if a change to layout properties of a + * direct child should be ignored, or should trigger a layout pass. + * + * @return {@code true} if this node is running {@link #layoutChildren()}, otherwise {@code false} + */ + boolean inLayoutChildren() { + return inLayoutChildren; + } + private boolean sizeCacheClear = true; private double prefWidthCache = -1; private double prefHeightCache = -1; @@ -1243,17 +1256,6 @@ protected double computeMinHeight(double width) { return super.getBaselineOffset(); } - /** - * It stores the reference to the current child being laid out by its parent. - * This reference is important to differentiate whether a layout is triggered - * by its parent or other events. - */ - private Node currentLayoutChild = null; - - boolean isCurrentLayoutChild(Node node) { - return node == currentLayoutChild; - } - /** * Executes a top-down layout pass on the scene graph under this parent. * @@ -1280,19 +1282,27 @@ public final void layout() { break; } performingLayout = true; - layoutChildren(); + inLayoutChildren = true; + + try { + layoutChildren(); + } + finally { + inLayoutChildren = false; + } + // Intended fall-through case DIRTY_BRANCH: for (int i = 0, max = children.size(); i < max; i++) { final Node child = children.get(i); - currentLayoutChild = child; + if (child instanceof Parent) { ((Parent)child).layout(); } else if (child instanceof SubScene) { ((SubScene)child).layoutPass(); } } - currentLayoutChild = null; + performingLayout = false; break; } @@ -1309,12 +1319,11 @@ public final void layout() { protected void layoutChildren() { for (int i=0, max=children.size(); i subtree = Stream.iterate(leaf, Objects::nonNull, Parent::getParent).toList().reversed(); + + for (int i = 0; i < subtree.size(); i++) { + Parent p = subtree.get(i); + assertEquals(flags[i], ParentShim.getLayoutFlag(p), "" + p); + } + } }