diff -r 74e2d2f67cfc javafx-ui-common/src/javafx/scene/Node.java --- a/javafx-ui-common/src/javafx/scene/Node.java Fri Jul 20 12:44:57 2012 -0700 +++ b/javafx-ui-common/src/javafx/scene/Node.java Fri Jul 20 15:42:44 2012 -0700 @@ -2102,6 +2102,7 @@ if (parent != null) { parent.managedChildChanged(); } + notifyManagedChanged(); } @Override @@ -2120,6 +2121,13 @@ } /** + * Called whenever the "managed" flag has changed. This is only + * used by Parent as an optimization to keep track of whether a + * Parent node is a layout root or not. + */ + void notifyManagedChanged() { } + + /** * Defines the x coordinate of the translation that is added to this {@code Node}'s * transform for the purpose of layout. The value should be computed as the * offset required to adjust the position of the node from its current diff -r 74e2d2f67cfc javafx-ui-common/src/javafx/scene/Parent.java --- a/javafx-ui-common/src/javafx/scene/Parent.java Fri Jul 20 12:44:57 2012 -0700 +++ b/javafx-ui-common/src/javafx/scene/Parent.java Fri Jul 20 15:42:44 2012 -0700 @@ -33,8 +33,7 @@ import com.sun.javafx.jmx.MXNodeAlgorithm; import com.sun.javafx.jmx.MXNodeAlgorithmContext; -import javafx.beans.property.ObjectProperty; -import javafx.beans.property.SimpleObjectProperty; +import javafx.beans.property.*; import javafx.collections.FXCollections; import javafx.collections.ListChangeListener.Change; import javafx.collections.ObservableList; @@ -60,8 +59,6 @@ import com.sun.javafx.sg.PGGroup; import com.sun.javafx.sg.PGNode; import com.sun.javafx.tk.Toolkit; -import javafx.beans.property.ReadOnlyBooleanProperty; -import javafx.beans.property.ReadOnlyBooleanWrapper; /** * The base class for all nodes that have children in the scene graph. @@ -651,7 +648,7 @@ // If this node is dirty and the new scene is not null // then add this node to the new scene's dirty list - if (scene != null && awaitingLayout && isLayoutRoot()) { + if (scene != null && awaitingLayout && layoutRoot) { scene.addToDirtyLayoutList(this); } } @@ -700,7 +697,7 @@ } @Override boolean isConnected() { - return super.isConnected() || isSceneRoot(); + return super.isConnected() || sceneRoot; } @Override public Node lookup(String selector) { @@ -824,7 +821,7 @@ } setNeedsLayout(true); - if (isLayoutRoot()) { + if (layoutRoot) { final Scene scene = getScene(); if (scene != null) { if (logger.isLoggable(PlatformLogger.FINER)) { @@ -852,7 +849,7 @@ prefHeightCache = -1; minWidthCache = -1; minHeightCache = -1; - if (!isLayoutRoot()) { + if (!layoutRoot) { final Parent parent = getParent(); if (parent != null) { parent.clearSizeCache(); @@ -1045,13 +1042,25 @@ } } - boolean isSceneRoot() { - final Scene scene = getScene(); - return scene != null ? scene.getRoot() == this : false; + /** + * This field is managed by the Scene, and set on any node which is the + * root of a Scene. + */ + private boolean sceneRoot = false; + final boolean isSceneRoot() { return sceneRoot; } + final void updateSceneRoot(boolean value) { + this.sceneRoot = value; + layoutRoot = !isManaged() || sceneRoot; } - boolean isLayoutRoot() { - return !isManaged() || isSceneRoot(); + /** + * Keeps track of whether this node is a layout root. This is updated + * whenever the sceneRoot field changes, or whenever the managed + * property changes. + */ + private boolean layoutRoot = false; + @Override final void notifyManagedChanged() { + layoutRoot = !isManaged() || sceneRoot; } /*********************************************************************** diff -r 74e2d2f67cfc javafx-ui-common/src/javafx/scene/Scene.java --- a/javafx-ui-common/src/javafx/scene/Scene.java Fri Jul 20 12:44:57 2012 -0700 +++ b/javafx-ui-common/src/javafx/scene/Scene.java Fri Jul 20 15:42:44 2012 -0700 @@ -991,6 +991,7 @@ if (oldRoot != null) { oldRoot.setScene(null); oldRoot.setImpl_traversalEngine(null); + oldRoot.updateSceneRoot(false); } oldRoot = _value; if (_value.getImpl_traversalEngine() == null) { @@ -998,6 +999,7 @@ } _value.getStyleClass().add(0, "root"); _value.setScene(Scene.this); + _value.updateSceneRoot(true); markDirty(DirtyBits.ROOT_DIRTY); _value.resize(getWidth(), getHeight()); // maybe no-op if root is not resizable _value.requestLayout();