diff --git a/core/src/main/java/edu/umd/cs/piccolo/PNode.java b/core/src/main/java/edu/umd/cs/piccolo/PNode.java index cdd26f7..62a041e 100644 --- a/core/src/main/java/edu/umd/cs/piccolo/PNode.java +++ b/core/src/main/java/edu/umd/cs/piccolo/PNode.java @@ -95,3663 +95,3902 @@ * @author Jesse Grosjean */ public class PNode implements Cloneable, Serializable, Printable { - /** - * The minimum difference in transparency required before the transparency - * is allowed to change. Done for efficiency reasons. I doubt very much that - * the human eye could tell the difference between 0.01 and 0.02 - * transparency. - */ - private static final float TRANSPARENCY_RESOLUTION = 0.01f; + /** + * The minimum difference in transparency required before the transparency + * is allowed to change. Done for efficiency reasons. I doubt very much that + * the human eye could tell the difference between 0.01 and 0.02 + * transparency. + */ + private static final float TRANSPARENCY_RESOLUTION = 0.01f; - /** - * Allows for future serialization code to understand versioned binary - * formats. - */ - private static final long serialVersionUID = 1L; + /** + * Allows for future serialization code to understand versioned binary + * formats. + */ + private static final long serialVersionUID = 1L; - /** - * The property name that identifies a change in this node's client - * propertie (see {@link #getClientProperty getClientProperty}). In an - * property change event the new value will be a reference to the map of - * client properties but old value will always be null. - */ - public static final String PROPERTY_CLIENT_PROPERTIES = "clientProperties"; + /** + * The property name that identifies a change in this node's client + * propertie (see {@link #getClientProperty getClientProperty}). In an + * property change event the new value will be a reference to the map of + * client properties but old value will always be null. + */ + public static final String PROPERTY_CLIENT_PROPERTIES = "clientProperties"; - /** - * The property code that identifies a change in this node's client - * propertie (see {@link #getClientProperty getClientProperty}). In an - * property change event the new value will be a reference to the map of - * client properties but old value will always be null. - */ - public static final int PROPERTY_CODE_CLIENT_PROPERTIES = 1 << 0; + /** + * The property code that identifies a change in this node's client + * propertie (see {@link #getClientProperty getClientProperty}). In an + * property change event the new value will be a reference to the map of + * client properties but old value will always be null. + */ + public static final int PROPERTY_CODE_CLIENT_PROPERTIES = 1 << 0; - /** - * The property name that identifies a change of this node's bounds (see - * {@link #getBounds getBounds}, {@link #getBoundsReference - * getBoundsReference}). In any property change event the new value will be - * a reference to this node's bounds, but old value will always be null. - */ - public static final String PROPERTY_BOUNDS = "bounds"; + /** + * The property name that identifies a change of this node's bounds (see + * {@link #getBounds getBounds}, {@link #getBoundsReference + * getBoundsReference}). In any property change event the new value will be + * a reference to this node's bounds, but old value will always be null. + */ + public static final String PROPERTY_BOUNDS = "bounds"; - /** - * The property code that identifies a change of this node's bounds (see - * {@link #getBounds getBounds}, {@link #getBoundsReference - * getBoundsReference}). In any property change event the new value will be - * a reference to this node's bounds, but old value will always be null. - */ - public static final int PROPERTY_CODE_BOUNDS = 1 << 1; + /** + * The property code that identifies a change of this node's bounds (see + * {@link #getBounds getBounds}, {@link #getBoundsReference + * getBoundsReference}). In any property change event the new value will be + * a reference to this node's bounds, but old value will always be null. + */ + public static final int PROPERTY_CODE_BOUNDS = 1 << 1; - /** - * The property name that identifies a change of this node's full bounds - * (see {@link #getFullBounds getFullBounds}, - * {@link #getFullBoundsReference getFullBoundsReference}). In any property - * change event the new value will be a reference to this node's full bounds - * cache, but old value will always be null. - */ - public static final String PROPERTY_FULL_BOUNDS = "fullBounds"; + /** + * The property name that identifies a change of this node's full bounds + * (see {@link #getFullBounds getFullBounds}, + * {@link #getFullBoundsReference getFullBoundsReference}). In any property + * change event the new value will be a reference to this node's full bounds + * cache, but old value will always be null. + */ + public static final String PROPERTY_FULL_BOUNDS = "fullBounds"; - /** - * The property code that identifies a change of this node's full bounds - * (see {@link #getFullBounds getFullBounds}, - * {@link #getFullBoundsReference getFullBoundsReference}). In any property - * change event the new value will be a reference to this node's full bounds - * cache, but old value will always be null. - */ - public static final int PROPERTY_CODE_FULL_BOUNDS = 1 << 2; + /** + * The property code that identifies a change of this node's full bounds + * (see {@link #getFullBounds getFullBounds}, + * {@link #getFullBoundsReference getFullBoundsReference}). In any property + * change event the new value will be a reference to this node's full bounds + * cache, but old value will always be null. + */ + public static final int PROPERTY_CODE_FULL_BOUNDS = 1 << 2; - /** - * The property name that identifies a change of this node's transform (see - * {@link #getTransform getTransform}, {@link #getTransformReference - * getTransformReference}). In any property change event the new value will - * be a reference to this node's transform, but old value will always be - * null. - */ - public static final String PROPERTY_TRANSFORM = "transform"; + /** + * The property name that identifies a change of this node's transform (see + * {@link #getTransform getTransform}, {@link #getTransformReference + * getTransformReference}). In any property change event the new value will + * be a reference to this node's transform, but old value will always be + * null. + */ + public static final String PROPERTY_TRANSFORM = "transform"; - /** - * The property code that identifies a change of this node's transform (see - * {@link #getTransform getTransform}, {@link #getTransformReference - * getTransformReference}). In any property change event the new value will - * be a reference to this node's transform, but old value will always be - * null. - */ - public static final int PROPERTY_CODE_TRANSFORM = 1 << 3; + /** + * The property code that identifies a change of this node's transform (see + * {@link #getTransform getTransform}, {@link #getTransformReference + * getTransformReference}). In any property change event the new value will + * be a reference to this node's transform, but old value will always be + * null. + */ + public static final int PROPERTY_CODE_TRANSFORM = 1 << 3; - /** - * The property name that identifies a change of this node's visibility (see - * {@link #getVisible getVisible}). Both old value and new value will be - * null in any property change event. - */ - public static final String PROPERTY_VISIBLE = "visible"; + /** + * The property name that identifies a change of this node's visibility (see + * {@link #getVisible getVisible}). Both old value and new value will be + * null in any property change event. + */ + public static final String PROPERTY_VISIBLE = "visible"; - /** - * The property code that identifies a change of this node's visibility (see - * {@link #getVisible getVisible}). Both old value and new value will be - * null in any property change event. - */ - public static final int PROPERTY_CODE_VISIBLE = 1 << 4; + /** + * The property code that identifies a change of this node's visibility (see + * {@link #getVisible getVisible}). Both old value and new value will be + * null in any property change event. + */ + public static final int PROPERTY_CODE_VISIBLE = 1 << 4; - /** - * The property name that identifies a change of this node's paint (see - * {@link #getPaint getPaint}). Both old value and new value will be set - * correctly in any property change event. - */ - public static final String PROPERTY_PAINT = "paint"; + /** + * The property name that identifies a change of this node's paint (see + * {@link #getPaint getPaint}). Both old value and new value will be set + * correctly in any property change event. + */ + public static final String PROPERTY_PAINT = "paint"; - /** - * The property code that identifies a change of this node's paint (see - * {@link #getPaint getPaint}). Both old value and new value will be set - * correctly in any property change event. - */ - public static final int PROPERTY_CODE_PAINT = 1 << 5; + /** + * The property code that identifies a change of this node's paint (see + * {@link #getPaint getPaint}). Both old value and new value will be set + * correctly in any property change event. + */ + public static final int PROPERTY_CODE_PAINT = 1 << 5; - /** - * The property name that identifies a change of this node's transparency - * (see {@link #getTransparency getTransparency}). Both old value and new - * value will be null in any property change event. - */ - public static final String PROPERTY_TRANSPARENCY = "transparency"; + /** + * The property name that identifies a change of this node's transparency + * (see {@link #getTransparency getTransparency}). Both old value and new + * value will be null in any property change event. + */ + public static final String PROPERTY_TRANSPARENCY = "transparency"; - /** - * The property code that identifies a change of this node's transparency - * (see {@link #getTransparency getTransparency}). Both old value and new - * value will be null in any property change event. - */ - public static final int PROPERTY_CODE_TRANSPARENCY = 1 << 6; + /** + * The property code that identifies a change of this node's transparency + * (see {@link #getTransparency getTransparency}). Both old value and new + * value will be null in any property change event. + */ + public static final int PROPERTY_CODE_TRANSPARENCY = 1 << 6; - /** - * The property name that identifies a change of this node's pickable status - * (see {@link #getPickable getPickable}). Both old value and new value will - * be null in any property change event. - */ - public static final String PROPERTY_PICKABLE = "pickable"; - /** - * The property code that identifies a change of this node's pickable status - * (see {@link #getPickable getPickable}). Both old value and new value will - * be null in any property change event. - */ - public static final int PROPERTY_CODE_PICKABLE = 1 << 7; + /** + * The property name that identifies a change of this node's pickable status + * (see {@link #getPickable getPickable}). Both old value and new value will + * be null in any property change event. + */ + public static final String PROPERTY_PICKABLE = "pickable"; + /** + * The property code that identifies a change of this node's pickable status + * (see {@link #getPickable getPickable}). Both old value and new value will + * be null in any property change event. + */ + public static final int PROPERTY_CODE_PICKABLE = 1 << 7; - /** - * The property name that identifies a change of this node's children - * pickable status (see {@link #getChildrenPickable getChildrenPickable}). - * Both old value and new value will be null in any property change event. - */ - public static final String PROPERTY_CHILDREN_PICKABLE = "childrenPickable"; + /** + * The property name that identifies a change of this node's children + * pickable status (see {@link #getChildrenPickable getChildrenPickable}). + * Both old value and new value will be null in any property change event. + */ + public static final String PROPERTY_CHILDREN_PICKABLE = "childrenPickable"; - /** - * The property code that identifies a change of this node's children - * pickable status (see {@link #getChildrenPickable getChildrenPickable}). - * Both old value and new value will be null in any property change event. - */ - public static final int PROPERTY_CODE_CHILDREN_PICKABLE = 1 << 8; + /** + * The property code that identifies a change of this node's children + * pickable status (see {@link #getChildrenPickable getChildrenPickable}). + * Both old value and new value will be null in any property change event. + */ + public static final int PROPERTY_CODE_CHILDREN_PICKABLE = 1 << 8; - /** - * The property name that identifies a change in the set of this node's - * direct children (see {@link #getChildrenReference getChildrenReference}, - * {@link #getChildrenIterator getChildrenIterator}). In any property change - * event the new value will be a reference to this node's children, but old - * value will always be null. - */ - public static final String PROPERTY_CHILDREN = "children"; + /** + * The property name that identifies a change in the set of this node's + * direct children (see {@link #getChildrenReference getChildrenReference}, + * {@link #getChildrenIterator getChildrenIterator}). In any property change + * event the new value will be a reference to this node's children, but old + * value will always be null. + */ + public static final String PROPERTY_CHILDREN = "children"; - /** - * The property code that identifies a change in the set of this node's - * direct children (see {@link #getChildrenReference getChildrenReference}, - * {@link #getChildrenIterator getChildrenIterator}). In any property change - * event the new value will be a reference to this node's children, but old - * value will always be null. - */ - public static final int PROPERTY_CODE_CHILDREN = 1 << 9; + /** + * The property code that identifies a change in the set of this node's + * direct children (see {@link #getChildrenReference getChildrenReference}, + * {@link #getChildrenIterator getChildrenIterator}). In any property change + * event the new value will be a reference to this node's children, but old + * value will always be null. + */ + public static final int PROPERTY_CODE_CHILDREN = 1 << 9; - /** - * The property name that identifies a change of this node's parent (see - * {@link #getParent getParent}). Both old value and new value will be set - * correctly in any property change event. - */ - public static final String PROPERTY_PARENT = "parent"; + /** + * The property name that identifies a change of this node's parent (see + * {@link #getParent getParent}). Both old value and new value will be set + * correctly in any property change event. + */ + public static final String PROPERTY_PARENT = "parent"; - /** - * The property code that identifies a change of this node's parent (see - * {@link #getParent getParent}). Both old value and new value will be set - * correctly in any property change event. - */ - public static final int PROPERTY_CODE_PARENT = 1 << 10; + /** + * The property code that identifies a change of this node's parent (see + * {@link #getParent getParent}). Both old value and new value will be set + * correctly in any property change event. + */ + public static final int PROPERTY_CODE_PARENT = 1 << 10; - /** Is an optimization for use during repaints. */ - private static final PBounds TEMP_REPAINT_BOUNDS = new PBounds(); + /** Is an optimization for use during repaints. */ + private static final PBounds TEMP_REPAINT_BOUNDS = new PBounds(); - /** The single scene graph delegate that receives low level node events. */ - public static PSceneGraphDelegate SCENE_GRAPH_DELEGATE = null; + /** The single scene graph delegate that receives low level node events. */ + public static PSceneGraphDelegate SCENE_GRAPH_DELEGATE = null; - /** Tracks the parent of this node, may be null. */ - private transient PNode parent; + /** Tracks the parent of this node, may be null. */ + private transient PNode parent; - /** Tracks all immediate child nodes. */ - private List children; + /** Tracks all immediate child nodes. */ + private List children; - /** Bounds of the PNode. */ - private final PBounds bounds; + /** Bounds of the PNode. */ + private final PBounds bounds; - /** Transform that applies to this node in relation to its parent. */ - private PAffineTransform transform; + /** Transform that applies to this node in relation to its parent. */ + private PAffineTransform transform; - /** The paint to use for the background of this node. */ - private Paint paint; + /** The paint to use for the background of this node. */ + private Paint paint; - /** - * How Opaque this node should be 1f = fully opaque, 0f = completely - * transparent. - */ - private float transparency; + /** + * How Opaque this node should be 1f = fully opaque, 0f = completely + * transparent. + */ + private float transparency; - /** A modifiable set of client properties. */ - private MutableAttributeSet clientProperties; + /** A modifiable set of client properties. */ + private MutableAttributeSet clientProperties; - /** - * An optimization that remembers the full bounds of a node rather than - * computing it every time. - */ - private PBounds fullBoundsCache; + /** + * An optimization that remembers the full bounds of a node rather than + * computing it every time. + */ + private PBounds fullBoundsCache; - /** - * Mask used when deciding whether to bubble up property change events to - * parents. - */ - private int propertyChangeParentMask = 0; + /** + * Mask used when deciding whether to bubble up property change events to + * parents. + */ + private int propertyChangeParentMask = 0; - /** Used to handle property change listeners. */ - private transient SwingPropertyChangeSupport changeSupport; + /** Used to handle property change listeners. */ + private transient SwingPropertyChangeSupport changeSupport; - /** List of event listeners. */ - private transient EventListenerList listenerList; + /** List of event listeners. */ + private transient EventListenerList listenerList; - /** Whether this node is pickable or not. */ - private boolean pickable; + /** Whether this node is pickable or not. */ + private boolean pickable; - /** - * Whether to stop processing pick at this node and not bother drilling down - * into children. - */ - private boolean childrenPickable; + /** + * Whether to stop processing pick at this node and not bother drilling down + * into children. + */ + private boolean childrenPickable; - /** Whether this node will be rendered. */ - private boolean visible; + /** Whether this node will be rendered. */ + private boolean visible; - private boolean childBoundsVolatile; + private boolean childBoundsVolatile; - /** Whether this node needs to be repainted. */ - private boolean paintInvalid; + /** Whether this node needs to be repainted. */ + private boolean paintInvalid; - /** Whether children need to be repainted. */ - private boolean childPaintInvalid; + /** Whether children need to be repainted. */ + private boolean childPaintInvalid; - /** Whether this node's bounds have changed, and so needs to be relaid out. */ - private boolean boundsChanged; + /** Whether this node's bounds have changed, and so needs to be relaid out. */ + private boolean boundsChanged; - /** Whether this node's full bounds need to be recomputed. */ - private boolean fullBoundsInvalid; + /** Whether this node's full bounds need to be recomputed. */ + private boolean fullBoundsInvalid; - /** Whether this node's child bounds need to be recomputed. */ - private boolean childBoundsInvalid; + /** Whether this node's child bounds need to be recomputed. */ + private boolean childBoundsInvalid; - private boolean occluded; + private boolean occluded; - /** Stores the name associated to this node. */ - private String name; + /** Stores the name associated to this node. */ + private String name; - /** - * toImage fill strategy that stretches the node be as large as possible - * while still retaining its aspect ratio. - * - * @since 1.3 - */ - public static final int FILL_STRATEGY_ASPECT_FIT = 1; + /** + * toImage fill strategy that stretches the node be as large as possible + * while still retaining its aspect ratio. + * + * @since 1.3 + */ + public static final int FILL_STRATEGY_ASPECT_FIT = 1; - /** - * toImage fill strategy that stretches the node be large enough to cover - * the image, and centers it. - * - * @since 1.3 - */ - public static final int FILL_STRATEGY_ASPECT_COVER = 2; + /** + * toImage fill strategy that stretches the node be large enough to cover + * the image, and centers it. + * + * @since 1.3 + */ + public static final int FILL_STRATEGY_ASPECT_COVER = 2; - /** - * toImage fill strategy that stretches the node to be exactly the - * dimensions of the image. Will result in distortion if the aspect ratios - * are different. - * - * @since 1.3 - */ - public static final int FILL_STRATEGY_EXACT_FIT = 4; + /** + * toImage fill strategy that stretches the node to be exactly the + * dimensions of the image. Will result in distortion if the aspect ratios + * are different. + * + * @since 1.3 + */ + public static final int FILL_STRATEGY_EXACT_FIT = 4; - /** - * Creates a new PNode with the given name. - * - * @since 1.3 - * @param newName name to assign to node - */ - public PNode(final String newName) { - this(); - setName(newName); - } + /** + * Creates a new PNode with the given name. + * + * @since 1.3 + * @param newName + * name to assign to node + */ + public PNode(final String newName) { + this(); + setName(newName); + } - /** - * Constructs a new PNode. - *
- * By default a node's paint is null, and bounds are empty. These values - * must be set for the node to show up on the screen once it's added to a - * scene graph. - */ - public PNode() { - bounds = new PBounds(); - fullBoundsCache = new PBounds(); - transparency = 1.0f; - pickable = true; - childrenPickable = true; - visible = true; - } + /** + * Constructs a new PNode. + *
+	 * By default a node's paint is null, and bounds are empty. These values
+	 * must be set for the node to show up on the screen once it's added to a
+	 * scene graph.
+	 */
+	public PNode() {
+		bounds = new PBounds();
+		fullBoundsCache = new PBounds();
+		transparency = 1.0f;
+		pickable = true;
+		childrenPickable = true;
+		visible = true;
+	}
 
-    // ****************************************************************
-    // Animation - Methods to animate this node.
-    //
-    // Note that animation is implemented by activities (PActivity),
-    // so if you need more control over your animation look at the
-    // activities package. Each animate method creates an animation that
-    // will animate the node from its current state to the new state
-    // specified over the given duration. These methods will try to
-    // automatically schedule the new activity, but if the node does not
-    // descend from the root node when the method is called then the
-    // activity will not be scheduled and you must schedule it manually.
-    // ****************************************************************
+	// ****************************************************************
+	// Animation - Methods to animate this node.
+	//
+	// Note that animation is implemented by activities (PActivity),
+	// so if you need more control over your animation look at the
+	// activities package. Each animate method creates an animation that
+	// will animate the node from its current state to the new state
+	// specified over the given duration. These methods will try to
+	// automatically schedule the new activity, but if the node does not
+	// descend from the root node when the method is called then the
+	// activity will not be scheduled and you must schedule it manually.
+	// ****************************************************************
 
-    /**
-     * Animate this node's bounds from their current location when the activity
-     * starts to the specified bounds. If this node descends from the root then
-     * the activity will be scheduled, else the returned activity should be
-     * scheduled manually. If two different transform activities are scheduled
-     * for the same node at the same time, they will both be applied to the
-     * node, but the last one scheduled will be applied last on each frame, so
-     * it will appear to have replaced the original. Generally you will not want
-     * to do that. Note this method animates the node's bounds, but does not
-     * change the node's transform. Use animateTransformToBounds() to animate
-     * the node's transform instead.
-     * 
-     * @param x left of target bounds
-     * @param y top of target bounds
-     * @param width width of target bounds
-     * @param height height of target bounds
-     * @param duration amount of time that the animation should take
-     * @return the newly scheduled activity
-     */
-    public PInterpolatingActivity animateToBounds(final double x, final double y, final double width,
-            final double height, final long duration) {
-        if (duration == 0) {
-            setBounds(x, y, width, height);
-            return null;
-        }
+	/**
+	 * Animate this node's bounds from their current location when the activity
+	 * starts to the specified bounds. If this node descends from the root then
+	 * the activity will be scheduled, else the returned activity should be
+	 * scheduled manually. If two different transform activities are scheduled
+	 * for the same node at the same time, they will both be applied to the
+	 * node, but the last one scheduled will be applied last on each frame, so
+	 * it will appear to have replaced the original. Generally you will not want
+	 * to do that. Note this method animates the node's bounds, but does not
+	 * change the node's transform. Use animateTransformToBounds() to animate
+	 * the node's transform instead.
+	 * 
+	 * @param x
+	 *            left of target bounds
+	 * @param y
+	 *            top of target bounds
+	 * @param width
+	 *            width of target bounds
+	 * @param height
+	 *            height of target bounds
+	 * @param duration
+	 *            amount of time that the animation should take
+	 * @return the newly scheduled activity
+	 */
+	public PInterpolatingActivity animateToBounds(final double x,
+			final double y, final double width, final double height,
+			final long duration) {
+		if (duration == 0) {
+			setBounds(x, y, width, height);
+			return null;
+		}
 
-        final PBounds dst = new PBounds(x, y, width, height);
+		final PBounds dst = new PBounds(x, y, width, height);
 
-        final PInterpolatingActivity interpolatingActivity = new PInterpolatingActivity(duration,
-                PUtil.DEFAULT_ACTIVITY_STEP_RATE) {
-            private PBounds src;
+		final PInterpolatingActivity interpolatingActivity = new PInterpolatingActivity(
+				duration, PUtil.DEFAULT_ACTIVITY_STEP_RATE) {
+			private PBounds src;
 
-            protected void activityStarted() {
-                src = getBounds();
-                startResizeBounds();
-                super.activityStarted();
-            }
+			protected void activityStarted() {
+				src = getBounds();
+				startResizeBounds();
+				super.activityStarted();
+			}
 
-            public void setRelativeTargetValue(final float zeroToOne) {
-                PNode.this.setBounds(src.x + zeroToOne * (dst.x - src.x), src.y + zeroToOne * (dst.y - src.y),
-                        src.width + zeroToOne * (dst.width - src.width), src.height + zeroToOne
-                        * (dst.height - src.height));
-            }
+			public void setRelativeTargetValue(final float zeroToOne) {
+				PNode.this.setBounds(src.x + zeroToOne * (dst.x - src.x), src.y
+						+ zeroToOne * (dst.y - src.y), src.width + zeroToOne
+						* (dst.width - src.width), src.height + zeroToOne
+						* (dst.height - src.height));
+			}
 
-            protected void activityFinished() {
-                super.activityFinished();
-                endResizeBounds();
-            }
-        };
+			protected void activityFinished() {
+				super.activityFinished();
+				endResizeBounds();
+			}
+		};
 
-        addActivity(interpolatingActivity);
-        return interpolatingActivity;
-    }
+		addActivity(interpolatingActivity);
+		return interpolatingActivity;
+	}
 
-    /**
-     * Animate this node from it's current transform when the activity starts a
-     * new transform that will fit the node into the given bounds. If this node
-     * descends from the root then the activity will be scheduled, else the
-     * returned activity should be scheduled manually. If two different
-     * transform activities are scheduled for the same node at the same time,
-     * they will both be applied to the node, but the last one scheduled will be
-     * applied last on each frame, so it will appear to have replaced the
-     * original. Generally you will not want to do that. Note this method
-     * animates the node's transform, but does not directly change the node's
-     * bounds rectangle. Use animateToBounds() to animate the node's bounds
-     * rectangle instead.
-     * 
-     * @param x left of target bounds
-     * @param y top of target bounds
-     * @param width width of target bounds
-     * @param height height of target bounds
-     * @param duration amount of time that the animation should take
-     * @return the newly scheduled activity
-     */
-    public PTransformActivity animateTransformToBounds(final double x, final double y, final double width,
-            final double height, final long duration) {
-        final PAffineTransform t = new PAffineTransform();
-        t.setToScale(width / getWidth(), height / getHeight());
-        final double scale = t.getScale();
-        t.setOffset(x - getX() * scale, y - getY() * scale);
-        return animateToTransform(t, duration);
-    }
+	/**
+	 * Animate this node from it's current transform when the activity starts a
+	 * new transform that will fit the node into the given bounds. If this node
+	 * descends from the root then the activity will be scheduled, else the
+	 * returned activity should be scheduled manually. If two different
+	 * transform activities are scheduled for the same node at the same time,
+	 * they will both be applied to the node, but the last one scheduled will be
+	 * applied last on each frame, so it will appear to have replaced the
+	 * original. Generally you will not want to do that. Note this method
+	 * animates the node's transform, but does not directly change the node's
+	 * bounds rectangle. Use animateToBounds() to animate the node's bounds
+	 * rectangle instead.
+	 * 
+	 * @param x
+	 *            left of target bounds
+	 * @param y
+	 *            top of target bounds
+	 * @param width
+	 *            width of target bounds
+	 * @param height
+	 *            height of target bounds
+	 * @param duration
+	 *            amount of time that the animation should take
+	 * @return the newly scheduled activity
+	 */
+	public PTransformActivity animateTransformToBounds(final double x,
+			final double y, final double width, final double height,
+			final long duration) {
+		final PAffineTransform t = new PAffineTransform();
+		t.setToScale(width / getWidth(), height / getHeight());
+		final double scale = t.getScale();
+		t.setOffset(x - getX() * scale, y - getY() * scale);
+		return animateToTransform(t, duration);
+	}
 
-    /**
-     * Animate this node's transform from its current location when the activity
-     * starts to the specified location, scale, and rotation. If this node
-     * descends from the root then the activity will be scheduled, else the
-     * returned activity should be scheduled manually. If two different
-     * transform activities are scheduled for the same node at the same time,
-     * they will both be applied to the node, but the last one scheduled will be
-     * applied last on each frame, so it will appear to have replaced the
-     * original. Generally you will not want to do that.
-     * 
-     * @param x the final target x position of node
-     * @param y the final target y position of node
-     * @param duration amount of time that the animation should take
-     * @param scale the final scale for the duration
-     * @param theta final theta value (in radians) for the animation
-     * @return the newly scheduled activity
-     */
-    public PTransformActivity animateToPositionScaleRotation(final double x, final double y, final double scale,
-            final double theta, final long duration) {
-        final PAffineTransform t = getTransform();
-        t.setOffset(x, y);
-        t.setScale(scale);
-        t.setRotation(theta);
-        return animateToTransform(t, duration);
-    }
+	/**
+	 * Animate this node's transform from its current location when the activity
+	 * starts to the specified location, scale, and rotation. If this node
+	 * descends from the root then the activity will be scheduled, else the
+	 * returned activity should be scheduled manually. If two different
+	 * transform activities are scheduled for the same node at the same time,
+	 * they will both be applied to the node, but the last one scheduled will be
+	 * applied last on each frame, so it will appear to have replaced the
+	 * original. Generally you will not want to do that.
+	 * 
+	 * @param x
+	 *            the final target x position of node
+	 * @param y
+	 *            the final target y position of node
+	 * @param duration
+	 *            amount of time that the animation should take
+	 * @param scale
+	 *            the final scale for the duration
+	 * @param theta
+	 *            final theta value (in radians) for the animation
+	 * @return the newly scheduled activity
+	 */
+	public PTransformActivity animateToPositionScaleRotation(final double x,
+			final double y, final double scale, final double theta,
+			final long duration) {
+		final PAffineTransform t = getTransform();
+		t.setOffset(x, y);
+		t.setScale(scale);
+		t.setRotation(theta);
+		return animateToTransform(t, duration);
+	}
 
-    /**
-     * Animate this node's transform from its current values when the activity
-     * starts to the new values specified in the given transform. If this node
-     * descends from the root then the activity will be scheduled, else the
-     * returned activity should be scheduled manually. If two different
-     * transform activities are scheduled for the same node at the same time,
-     * they will both be applied to the node, but the last one scheduled will be
-     * applied last on each frame, so it will appear to have replaced the
-     * original. Generally you will not want to do that.
-     * 
-     * @param destTransform the final transform value
-     * @param duration amount of time that the animation should take
-     * @return the newly scheduled activity
-     */
-    public PTransformActivity animateToTransform(final AffineTransform destTransform, final long duration) {
-        if (duration == 0) {
-            setTransform(destTransform);
-            return null;
-        }
-        else {
-            final PTransformActivity.Target t = new PTransformActivity.Target() {
-                public void setTransform(final AffineTransform aTransform) {
-                    PNode.this.setTransform(aTransform);
-                }
+	/**
+	 * Animate this node's transform from its current values when the activity
+	 * starts to the new values specified in the given transform. If this node
+	 * descends from the root then the activity will be scheduled, else the
+	 * returned activity should be scheduled manually. If two different
+	 * transform activities are scheduled for the same node at the same time,
+	 * they will both be applied to the node, but the last one scheduled will be
+	 * applied last on each frame, so it will appear to have replaced the
+	 * original. Generally you will not want to do that.
+	 * 
+	 * @param destTransform
+	 *            the final transform value
+	 * @param duration
+	 *            amount of time that the animation should take
+	 * @return the newly scheduled activity
+	 */
+	public PTransformActivity animateToTransform(
+			final AffineTransform destTransform, final long duration) {
+		if (duration == 0) {
+			setTransform(destTransform);
+			return null;
+		} else {
+			final PTransformActivity.Target t = new PTransformActivity.Target() {
+				public void setTransform(final AffineTransform aTransform) {
+					PNode.this.setTransform(aTransform);
+				}
 
-                public void getSourceMatrix(final double[] aSource) {
-                    PNode.this.getTransformReference(true).getMatrix(aSource);
-                }
-            };
+				public void getSourceMatrix(final double[] aSource) {
+					PNode.this.getTransformReference(true).getMatrix(aSource);
+				}
+			};
 
-            final PTransformActivity ta = new PTransformActivity(duration, PUtil.DEFAULT_ACTIVITY_STEP_RATE, t,
-                    destTransform);
-            addActivity(ta);
-            return ta;
-        }
-    }
+			final PTransformActivity ta = new PTransformActivity(duration,
+					PUtil.DEFAULT_ACTIVITY_STEP_RATE, t, destTransform);
+			addActivity(ta);
+			return ta;
+		}
+	}
 
-    /**
-     * Animate this node's color from its current value to the new value
-     * specified. This meathod assumes that this nodes paint property is of type
-     * color. If this node descends from the root then the activity will be
-     * scheduled, else the returned activity should be scheduled manually. If
-     * two different color activities are scheduled for the same node at the
-     * same time, they will both be applied to the node, but the last one
-     * scheduled will be applied last on each frame, so it will appear to have
-     * replaced the original. Generally you will not want to do that.
-     * 
-     * @param destColor final color value.
-     * @param duration amount of time that the animation should take
-     * @return the newly scheduled activity
-     */
-    public PInterpolatingActivity animateToColor(final Color destColor, final long duration) {
-        if (duration == 0) {
-            setPaint(destColor);
-            return null;
-        }
-        else {
-            final PColorActivity.Target t = new PColorActivity.Target() {
-                public Color getColor() {
-                    return (Color) getPaint();
-                }
+	/**
+	 * Animate this node's color from its current value to the new value
+	 * specified. This meathod assumes that this nodes paint property is of type
+	 * color. If this node descends from the root then the activity will be
+	 * scheduled, else the returned activity should be scheduled manually. If
+	 * two different color activities are scheduled for the same node at the
+	 * same time, they will both be applied to the node, but the last one
+	 * scheduled will be applied last on each frame, so it will appear to have
+	 * replaced the original. Generally you will not want to do that.
+	 * 
+	 * @param destColor
+	 *            final color value.
+	 * @param duration
+	 *            amount of time that the animation should take
+	 * @return the newly scheduled activity
+	 */
+	public PInterpolatingActivity animateToColor(final Color destColor,
+			final long duration) {
+		if (duration == 0) {
+			setPaint(destColor);
+			return null;
+		} else {
+			final PColorActivity.Target t = new PColorActivity.Target() {
+				public Color getColor() {
+					return (Color) getPaint();
+				}
 
-                public void setColor(final Color color) {
-                    setPaint(color);
-                }
-            };
+				public void setColor(final Color color) {
+					setPaint(color);
+				}
+			};
 
-            final PColorActivity ca = new PColorActivity(duration, PUtil.DEFAULT_ACTIVITY_STEP_RATE, t, destColor);
-            addActivity(ca);
-            return ca;
-        }
-    }
+			final PColorActivity ca = new PColorActivity(duration,
+					PUtil.DEFAULT_ACTIVITY_STEP_RATE, t, destColor);
+			addActivity(ca);
+			return ca;
+		}
+	}
 
-    /**
-     * Animate this node's transparency from its current value to the new value
-     * specified. Transparency values must range from zero to one. If this node
-     * descends from the root then the activity will be scheduled, else the
-     * returned activity should be scheduled manually. If two different
-     * transparency activities are scheduled for the same node at the same time,
-     * they will both be applied to the node, but the last one scheduled will be
-     * applied last on each frame, so it will appear to have replaced the
-     * original. Generally you will not want to do that.
-     * 
-     * @param zeroToOne final transparency value.
-     * @param duration amount of time that the animation should take
-     * @return the newly scheduled activity
-     */
-    public PInterpolatingActivity animateToTransparency(final float zeroToOne, final long duration) {
-        if (duration == 0) {
-            setTransparency(zeroToOne);
-            return null;
-        }
-        else {
-            final float dest = zeroToOne;
+	/**
+	 * Animate this node's transparency from its current value to the new value
+	 * specified. Transparency values must range from zero to one. If this node
+	 * descends from the root then the activity will be scheduled, else the
+	 * returned activity should be scheduled manually. If two different
+	 * transparency activities are scheduled for the same node at the same time,
+	 * they will both be applied to the node, but the last one scheduled will be
+	 * applied last on each frame, so it will appear to have replaced the
+	 * original. Generally you will not want to do that.
+	 * 
+	 * @param zeroToOne
+	 *            final transparency value.
+	 * @param duration
+	 *            amount of time that the animation should take
+	 * @return the newly scheduled activity
+	 */
+	public PInterpolatingActivity animateToTransparency(final float zeroToOne,
+			final long duration) {
+		if (duration == 0) {
+			setTransparency(zeroToOne);
+			return null;
+		} else {
+			final float dest = zeroToOne;
 
-            final PInterpolatingActivity ta = new PInterpolatingActivity(duration, PUtil.DEFAULT_ACTIVITY_STEP_RATE) {
-                private float source;
+			final PInterpolatingActivity ta = new PInterpolatingActivity(
+					duration, PUtil.DEFAULT_ACTIVITY_STEP_RATE) {
+				private float source;
 
-                protected void activityStarted() {
-                    source = getTransparency();
-                    super.activityStarted();
-                }
+				protected void activityStarted() {
+					source = getTransparency();
+					super.activityStarted();
+				}
 
-                public void setRelativeTargetValue(final float zeroToOne) {
-                    PNode.this.setTransparency(source + zeroToOne * (dest - source));
-                }
-            };
+				public void setRelativeTargetValue(final float zeroToOne) {
+					PNode.this.setTransparency(source + zeroToOne
+							* (dest - source));
+				}
+			};
 
-            addActivity(ta);
-            return ta;
-        }
-    }
+			addActivity(ta);
+			return ta;
+		}
+	}
 
-    /**
-     * Schedule the given activity with the root, note that only scheduled
-     * activities will be stepped. If the activity is successfully added true is
-     * returned, else false.
-     * 
-     * @param activity new activity to schedule
-     * @return true if the activity is successfully scheduled.
-     */
-    public boolean addActivity(final PActivity activity) {
-        final PRoot r = getRoot();
-        if (r != null) {
-            return r.addActivity(activity);
-        }
-        return false;
-    }
+	/**
+	 * Schedule the given activity with the root, note that only scheduled
+	 * activities will be stepped. If the activity is successfully added true is
+	 * returned, else false.
+	 * 
+	 * @param activity
+	 *            new activity to schedule
+	 * @return true if the activity is successfully scheduled.
+	 */
+	public boolean addActivity(final PActivity activity) {
+		final PRoot r = getRoot();
+		if (r != null) {
+			return r.addActivity(activity);
+		}
+		return false;
+	}
 
-    // ****************************************************************
-    // Client Properties - Methods for managing client properties for
-    // this node.
-    //
-    // Client properties provide a way for programmers to attach
-    // extra information to a node without having to subclass it and
-    // add new instance variables.
-    // ****************************************************************
+	// ****************************************************************
+	// Client Properties - Methods for managing client properties for
+	// this node.
+	//
+	// Client properties provide a way for programmers to attach
+	// extra information to a node without having to subclass it and
+	// add new instance variables.
+	// ****************************************************************
 
-    /**
-     * Return mutable attributed set of client properties associated with this
-     * node.
-     * 
-     * @return the client properties associated to this node
-     */
-    public MutableAttributeSet getClientProperties() {
-        if (clientProperties == null) {
-            clientProperties = new SimpleAttributeSet();
-        }
-        return clientProperties;
-    }
+	/**
+	 * Return mutable attributed set of client properties associated with this
+	 * node.
+	 * 
+	 * @return the client properties associated to this node
+	 */
+	public MutableAttributeSet getClientProperties() {
+		if (clientProperties == null) {
+			clientProperties = new SimpleAttributeSet();
+		}
+		return clientProperties;
+	}
 
-    /**
-     * Returns the value of the client attribute with the specified key. Only
-     * attributes added with addAttribute will return a non-null
-     * value.
-     * 
-     * @param key key to use while fetching client attribute
-     * 
-     * @return the value of this attribute or null
-     */
-    public Object getAttribute(final Object key) {
-        if (clientProperties == null || key == null) {
-            return null;
-        }
-        else {
-            return clientProperties.getAttribute(key);
-        }
-    }
+	/**
+	 * Returns the value of the client attribute with the specified key. Only
+	 * attributes added with addAttribute will return a non-null
+	 * value.
+	 * 
+	 * @param key
+	 *            key to use while fetching client attribute
+	 * 
+	 * @return the value of this attribute or null
+	 */
+	public Object getAttribute(final Object key) {
+		if (clientProperties == null || key == null) {
+			return null;
+		} else {
+			return clientProperties.getAttribute(key);
+		}
+	}
 
-    /**
-     * Add an arbitrary key/value to this node.
-     * 
-     * The get/add attribute methods provide access to a small
-     * per-instance attribute set. Callers can use get/add attribute to annotate
-     * nodes that were created by another module.
-     * 
- * If value is null this method will remove the attribute. - * - * @param key to use when adding the attribute - * @param value value to associate to the new attribute - */ - public void addAttribute(final Object key, final Object value) { - if (value == null && clientProperties == null) { - return; - } + /** + * Add an arbitrary key/value to this node. + *
+	 * The get/add attribute methods provide access to a small
+	 * per-instance attribute set. Callers can use get/add attribute to annotate
+	 * nodes that were created by another module.
+	 * 
+	 * If value is null this method will remove the attribute.
+	 * 
+	 * @param key
+	 *            to use when adding the attribute
+	 * @param value
+	 *            value to associate to the new attribute
+	 */
+	public void addAttribute(final Object key, final Object value) {
+		if (value == null && clientProperties == null) {
+			return;
+		}
 
-        final Object oldValue = getAttribute(key);
+		final Object oldValue = getAttribute(key);
 
-        if (value != oldValue) {
-            if (clientProperties == null) {
-                clientProperties = new SimpleAttributeSet();
-            }
+		if (value != oldValue) {
+			if (clientProperties == null) {
+				clientProperties = new SimpleAttributeSet();
+			}
 
-            if (value == null) {
-                clientProperties.removeAttribute(key);
-            }
-            else {
-                clientProperties.addAttribute(key, value);
-            }
+			if (value == null) {
+				clientProperties.removeAttribute(key);
+			} else {
+				clientProperties.addAttribute(key, value);
+			}
 
-            if (clientProperties.getAttributeCount() == 0 && clientProperties.getResolveParent() == null) {
-                clientProperties = null;
-            }
+			if (clientProperties.getAttributeCount() == 0
+					&& clientProperties.getResolveParent() == null) {
+				clientProperties = null;
+			}
 
-            firePropertyChange(PROPERTY_CODE_CLIENT_PROPERTIES, PROPERTY_CLIENT_PROPERTIES, null, clientProperties);
-            firePropertyChange(PROPERTY_CODE_CLIENT_PROPERTIES, key.toString(), oldValue, value);
-        }
-    }
+			firePropertyChange(PROPERTY_CODE_CLIENT_PROPERTIES,
+					PROPERTY_CLIENT_PROPERTIES, null, clientProperties);
+			firePropertyChange(PROPERTY_CODE_CLIENT_PROPERTIES, key.toString(),
+					oldValue, value);
+		}
+	}
 
-    /**
-     * Returns an enumeration of all keys maped to attribute values values.
-     * 
-     * @return an Enumeration over attribute keys
-     */
-    public Enumeration getClientPropertyKeysEnumeration() {
-        if (clientProperties == null) {
-            return PUtil.NULL_ENUMERATION;
-        }
-        else {
-            return clientProperties.getAttributeNames();
-        }
-    }
+	/**
+	 * Returns an enumeration of all keys maped to attribute values values.
+	 * 
+	 * @return an Enumeration over attribute keys
+	 */
+	public Enumeration getClientPropertyKeysEnumeration() {
+		if (clientProperties == null) {
+			return PUtil.NULL_ENUMERATION;
+		} else {
+			return clientProperties.getAttributeNames();
+		}
+	}
 
-    // convenience methods for attributes
+	// convenience methods for attributes
+
+	/**
+	 * Fetches the value of the requested attribute, returning defaultValue is
+	 * not found.
+	 * 
+	 * @param key
+	 *            attribute to search for
+	 * @param defaultValue
+	 *            value to return if attribute is not found
+	 * 
+	 * @return value of attribute or defaultValue if not found
+	 */
+	public Object getAttribute(final Object key, final Object defaultValue) {
+		final Object value = getAttribute(key);
+		if (value == null) {
+			return defaultValue;
+		}
 
-    /**
-     * Fetches the value of the requested attribute, returning defaultValue is
-     * not found.
-     * 
-     * @param key attribute to search for
-     * @param defaultValue value to return if attribute is not found
-     * 
-     * @return value of attribute or defaultValue if not found
-     */
-    public Object getAttribute(final Object key, final Object defaultValue) {
-        final Object value = getAttribute(key);
-        if (value == null) {
-            return defaultValue;
-        }
+		return value;
+	}
 
-        return value;
-    }
+	/**
+	 * Fetches the boolean value of the requested attribute, returning
+	 * defaultValue is not found.
+	 * 
+	 * @param key
+	 *            attribute to search for
+	 * @param defaultValue
+	 *            value to return if attribute is not found
+	 * 
+	 * @return value of attribute or defaultValue if not found
+	 */
+	public boolean getBooleanAttribute(final Object key,
+			final boolean defaultValue) {
+		final Boolean value = (Boolean) getAttribute(key);
+		if (value == null) {
+			return defaultValue;
+		}
 
-    /**
-     * Fetches the boolean value of the requested attribute, returning
-     * defaultValue is not found.
-     * 
-     * @param key attribute to search for
-     * @param defaultValue value to return if attribute is not found
-     * 
-     * @return value of attribute or defaultValue if not found
-     */
-    public boolean getBooleanAttribute(final Object key, final boolean defaultValue) {
-        final Boolean value = (Boolean) getAttribute(key);
-        if (value == null) {
-            return defaultValue;
-        }
+		return value.booleanValue();
+	}
 
-        return value.booleanValue();
-    }
+	/**
+	 * Fetches the integer value of the requested attribute, returning
+	 * defaultValue is not found.
+	 * 
+	 * @param key
+	 *            attribute to search for
+	 * @param defaultValue
+	 *            value to return if attribute is not found
+	 * 
+	 * @return value of attribute or defaultValue if not found
+	 */
+	public int getIntegerAttribute(final Object key, final int defaultValue) {
+		final Number value = (Number) getAttribute(key);
+		if (value == null) {
+			return defaultValue;
+		}
 
-    /**
-     * Fetches the integer value of the requested attribute, returning
-     * defaultValue is not found.
-     * 
-     * @param key attribute to search for
-     * @param defaultValue value to return if attribute is not found
-     * 
-     * @return value of attribute or defaultValue if not found
-     */
-    public int getIntegerAttribute(final Object key, final int defaultValue) {
-        final Number value = (Number) getAttribute(key);
-        if (value == null) {
-            return defaultValue;
-        }
+		return value.intValue();
+	}
 
-        return value.intValue();
-    }
+	/**
+	 * Fetches the double value of the requested attribute, returning
+	 * defaultValue is not found.
+	 * 
+	 * @param key
+	 *            attribute to search for
+	 * @param defaultValue
+	 *            value to return if attribute is not found
+	 * 
+	 * @return value of attribute or defaultValue if not found
+	 */
+	public double getDoubleAttribute(final Object key, final double defaultValue) {
+		final Number value = (Number) getAttribute(key);
+		if (value == null) {
+			return defaultValue;
+		}
 
-    /**
-     * Fetches the double value of the requested attribute, returning
-     * defaultValue is not found.
-     * 
-     * @param key attribute to search for
-     * @param defaultValue value to return if attribute is not found
-     * 
-     * @return value of attribute or defaultValue if not found
-     */
-    public double getDoubleAttribute(final Object key, final double defaultValue) {
-        final Number value = (Number) getAttribute(key);
-        if (value == null) {
-            return defaultValue;
-        }
+		return value.doubleValue();
+	}
 
-        return value.doubleValue();
-    }
+	/**
+	 * @deprecated use getAttribute(Object key)instead.
+	 * 
+	 * @param key
+	 *            name of property to search for
+	 * @return value of matching client property
+	 */
+	public Object getClientProperty(final Object key) {
+		return getAttribute(key);
+	}
 
-    /**
-     * @deprecated use getAttribute(Object key)instead.
-     * 
-     * @param key name of property to search for
-     * @return value of matching client property
-     */
-    public Object getClientProperty(final Object key) {
-        return getAttribute(key);
-    }
+	/**
+	 * @deprecated use addAttribute(Object key, Object value)instead.
+	 * 
+	 * @param key
+	 *            name of property to add
+	 * @param value
+	 *            value or new attribute
+	 */
+	public void addClientProperty(final Object key, final Object value) {
+		addAttribute(key, value);
+	}
 
-    /**
-     * @deprecated use addAttribute(Object key, Object value)instead.
-     * 
-     * @param key name of property to add
-     * @param value value or new attribute
-     */
-    public void addClientProperty(final Object key, final Object value) {
-        addAttribute(key, value);
-    }
+	/**
+	 * @deprecated use getClientPropertyKeysEnumerator() instead.
+	 * 
+	 * @return iterator for client property keys
+	 */
+	public Iterator getClientPropertyKeysIterator() {
+		final Enumeration enumeration = getClientPropertyKeysEnumeration();
 
-    /**
-     * @deprecated use getClientPropertyKeysEnumerator() instead.
-     * 
-     * @return iterator for client property keys
-     */
-    public Iterator getClientPropertyKeysIterator() {
-        final Enumeration enumeration = getClientPropertyKeysEnumeration();
+		return new ClientPropertyKeyIterator(enumeration);
+	}
 
-        return new ClientPropertyKeyIterator(enumeration);
-    }
+	// ****************************************************************
+	// Copying - Methods for copying this node and its descendants.
+	// Copying is implemented in terms of serialization.
+	// ****************************************************************
 
-    // ****************************************************************
-    // Copying - Methods for copying this node and its descendants.
-    // Copying is implemented in terms of serialization.
-    // ****************************************************************
+	/**
+	 * The copy method copies this node and all of its descendants. Note that
+	 * copying is implemented in terms of java serialization. See the
+	 * serialization notes for more information.
+	 * 
+	 * @return new copy of this node or null if the node was not serializable
+	 */
+	public Object clone() {
+		try {
+			final byte[] ser = PObjectOutputStream.toByteArray(this);
+			return new ObjectInputStream(new ByteArrayInputStream(ser))
+					.readObject();
+		} catch (final IOException e) {
+			return null;
+		} catch (final ClassNotFoundException e) {
+			return null;
+		}
+	}
 
-    /**
-     * The copy method copies this node and all of its descendants. Note that
-     * copying is implemented in terms of java serialization. See the
-     * serialization notes for more information.
-     * 
-     * @return new copy of this node or null if the node was not serializable
-     */
-    public Object clone() {
-        try {
-            final byte[] ser = PObjectOutputStream.toByteArray(this);
-            return new ObjectInputStream(new ByteArrayInputStream(ser)).readObject();
-        }
-        catch (final IOException e) {
-            return null;
-        }
-        catch (final ClassNotFoundException e) {
-            return null;
-        }
-    }
+	// ****************************************************************
+	// Coordinate System Conversions - Methods for converting
+	// geometry between this nodes local coordinates and the other
+	// major coordinate systems.
+	//
+	// Each nodes has an affine transform that it uses to define its
+	// own coordinate system. For example if you create a new node and
+	// add it to the canvas it will appear in the upper right corner. Its
+	// coordinate system matches the coordinate system of its parent
+	// (the root node) at this point. But if you move this node by calling
+	// node.translate() the nodes affine transform will be modified and the
+	// node will appear at a different location on the screen. The node
+	// coordinate system no longer matches the coordinate system of its
+	// parent.
+	//
+	// This is useful because it means that the node's methods for
+	// rendering and picking don't need to worry about the fact that
+	// the node has been moved to another position on the screen, they
+	// keep working just like they did when it was in the upper right
+	// hand corner of the screen.
+	//
+	// The problem is now that each node defines its own coordinate
+	// system it is difficult to compare the positions of two node with
+	// each other. These methods are all meant to help solve that problem.
+	//
+	// The terms used in the methods are as follows:
+	//
+	// local - The local or base coordinate system of a node.
+	// parent - The coordinate system of a node's parent
+	// global - The topmost coordinate system, above the root node.
+	//
+	// Normally when comparing the positions of two nodes you will
+	// convert the local position of each node to the global coordinate
+	// system, and then compare the positions in that common coordinate
+	// system.
+	// ***************************************************************
 
-    // ****************************************************************
-    // Coordinate System Conversions - Methods for converting
-    // geometry between this nodes local coordinates and the other
-    // major coordinate systems.
-    //
-    // Each nodes has an affine transform that it uses to define its
-    // own coordinate system. For example if you create a new node and
-    // add it to the canvas it will appear in the upper right corner. Its
-    // coordinate system matches the coordinate system of its parent
-    // (the root node) at this point. But if you move this node by calling
-    // node.translate() the nodes affine transform will be modified and the
-    // node will appear at a different location on the screen. The node
-    // coordinate system no longer matches the coordinate system of its
-    // parent.
-    //
-    // This is useful because it means that the node's methods for
-    // rendering and picking don't need to worry about the fact that
-    // the node has been moved to another position on the screen, they
-    // keep working just like they did when it was in the upper right
-    // hand corner of the screen.
-    //
-    // The problem is now that each node defines its own coordinate
-    // system it is difficult to compare the positions of two node with
-    // each other. These methods are all meant to help solve that problem.
-    //
-    // The terms used in the methods are as follows:
-    //
-    // local - The local or base coordinate system of a node.
-    // parent - The coordinate system of a node's parent
-    // global - The topmost coordinate system, above the root node.
-    //
-    // Normally when comparing the positions of two nodes you will
-    // convert the local position of each node to the global coordinate
-    // system, and then compare the positions in that common coordinate
-    // system.
-    // ***************************************************************
+	/**
+	 * Transform the given point from this node's local coordinate system to its
+	 * parent's local coordinate system. Note that this will modify the point
+	 * parameter.
+	 * 
+	 * @param localPoint
+	 *            point in local coordinate system to be transformed.
+	 * @return point in parent's local coordinate system
+	 */
+	public Point2D localToParent(final Point2D localPoint) {
+		if (transform == null) {
+			return localPoint;
+		}
+		return transform.transform(localPoint, localPoint);
+	}
 
-    /**
-     * Transform the given point from this node's local coordinate system to its
-     * parent's local coordinate system. Note that this will modify the point
-     * parameter.
-     * 
-     * @param localPoint point in local coordinate system to be transformed.
-     * @return point in parent's local coordinate system
-     */
-    public Point2D localToParent(final Point2D localPoint) {
-        if (transform == null) {
-            return localPoint;
-        }
-        return transform.transform(localPoint, localPoint);
-    }
+	/**
+	 * Transform the given dimension from this node's local coordinate system to
+	 * its parent's local coordinate system. Note that this will modify the
+	 * dimension parameter.
+	 * 
+	 * @param localDimension
+	 *            dimension in local coordinate system to be transformed.
+	 * @return dimension in parent's local coordinate system
+	 */
+	public Dimension2D localToParent(final Dimension2D localDimension) {
+		if (transform == null) {
+			return localDimension;
+		}
+		return transform.transform(localDimension, localDimension);
+	}
 
-    /**
-     * Transform the given dimension from this node's local coordinate system to
-     * its parent's local coordinate system. Note that this will modify the
-     * dimension parameter.
-     * 
-     * @param localDimension dimension in local coordinate system to be
-     *            transformed.
-     * @return dimension in parent's local coordinate system
-     */
-    public Dimension2D localToParent(final Dimension2D localDimension) {
-        if (transform == null) {
-            return localDimension;
-        }
-        return transform.transform(localDimension, localDimension);
-    }
+	/**
+	 * Transform the given rectangle from this node's local coordinate system to
+	 * its parent's local coordinate system. Note that this will modify the
+	 * rectangle parameter.
+	 * 
+	 * @param localRectangle
+	 *            rectangle in local coordinate system to be transformed.
+	 * @return rectangle in parent's local coordinate system
+	 */
+	public Rectangle2D localToParent(final Rectangle2D localRectangle) {
+		if (transform == null) {
+			return localRectangle;
+		}
+		return transform.transform(localRectangle, localRectangle);
+	}
 
-    /**
-     * Transform the given rectangle from this node's local coordinate system to
-     * its parent's local coordinate system. Note that this will modify the
-     * rectangle parameter.
-     * 
-     * @param localRectangle rectangle in local coordinate system to be
-     *            transformed.
-     * @return rectangle in parent's local coordinate system
-     */
-    public Rectangle2D localToParent(final Rectangle2D localRectangle) {
-        if (transform == null) {
-            return localRectangle;
-        }
-        return transform.transform(localRectangle, localRectangle);
-    }
+	/**
+	 * Transform the given point from this node's parent's local coordinate
+	 * system to the local coordinate system of this node. Note that this will
+	 * modify the point parameter.
+	 * 
+	 * @param parentPoint
+	 *            point in parent's coordinate system to be transformed.
+	 * @return point in this node's local coordinate system
+	 */
+	public Point2D parentToLocal(final Point2D parentPoint) {
+		if (transform == null) {
+			return parentPoint;
+		}
 
-    /**
-     * Transform the given point from this node's parent's local coordinate
-     * system to the local coordinate system of this node. Note that this will
-     * modify the point parameter.
-     * 
-     * @param parentPoint point in parent's coordinate system to be transformed.
-     * @return point in this node's local coordinate system
-     */
-    public Point2D parentToLocal(final Point2D parentPoint) {
-        if (transform == null) {
-            return parentPoint;
-        }
+		return transform.inverseTransform(parentPoint, parentPoint);
+	}
 
-        return transform.inverseTransform(parentPoint, parentPoint);
-    }
+	/**
+	 * Transform the given dimension from this node's parent's local coordinate
+	 * system to the local coordinate system of this node. Note that this will
+	 * modify the dimension parameter.
+	 * 
+	 * @param parentDimension
+	 *            dimension in parent's coordinate system to be transformed.
+	 * @return dimension in this node's local coordinate system
+	 */
+	public Dimension2D parentToLocal(final Dimension2D parentDimension) {
+		if (transform == null) {
+			return parentDimension;
+		}
+		return transform.inverseTransform(parentDimension, parentDimension);
+	}
 
-    /**
-     * Transform the given dimension from this node's parent's local coordinate
-     * system to the local coordinate system of this node. Note that this will
-     * modify the dimension parameter.
-     * 
-     * @param parentDimension dimension in parent's coordinate system to be
-     *            transformed.
-     * @return dimension in this node's local coordinate system
-     */
-    public Dimension2D parentToLocal(final Dimension2D parentDimension) {
-        if (transform == null) {
-            return parentDimension;
-        }
-        return transform.inverseTransform(parentDimension, parentDimension);
-    }
+	/**
+	 * Transform the given rectangle from this node's parent's local coordinate
+	 * system to the local coordinate system of this node. Note that this will
+	 * modify the rectangle parameter.
+	 * 
+	 * @param parentRectangle
+	 *            rectangle in parent's coordinate system to be transformed.
+	 * @return rectangle in this node's local coordinate system
+	 */
+	public Rectangle2D parentToLocal(final Rectangle2D parentRectangle) {
+		if (transform == null) {
+			return parentRectangle;
+		}
+		return transform.inverseTransform(parentRectangle, parentRectangle);
+	}
 
-    /**
-     * Transform the given rectangle from this node's parent's local coordinate
-     * system to the local coordinate system of this node. Note that this will
-     * modify the rectangle parameter.
-     * 
-     * @param parentRectangle rectangle in parent's coordinate system to be
-     *            transformed.
-     * @return rectangle in this node's local coordinate system
-     */
-    public Rectangle2D parentToLocal(final Rectangle2D parentRectangle) {
-        if (transform == null) {
-            return parentRectangle;
-        }
-        return transform.inverseTransform(parentRectangle, parentRectangle);
-    }
+	/**
+	 * Transform the given point from this node's local coordinate system to the
+	 * global coordinate system. Note that this will modify the point parameter.
+	 * 
+	 * @param localPoint
+	 *            point in local coordinate system to be transformed.
+	 * @return point in global coordinates
+	 */
+	public Point2D localToGlobal(final Point2D localPoint) {
+		PNode n = this;
+		while (n != null) {
+			n.localToParent(localPoint);
+			n = n.parent;
+		}
+		return localPoint;
+	}
 
-    /**
-     * Transform the given point from this node's local coordinate system to the
-     * global coordinate system. Note that this will modify the point parameter.
-     * 
-     * @param localPoint point in local coordinate system to be transformed.
-     * @return point in global coordinates
-     */
-    public Point2D localToGlobal(final Point2D localPoint) {
-        PNode n = this;
-        while (n != null) {
-            n.localToParent(localPoint);
-            n = n.parent;
-        }
-        return localPoint;
-    }
+	/**
+	 * Transform the given dimension from this node's local coordinate system to
+	 * the global coordinate system. Note that this will modify the dimension
+	 * parameter.
+	 * 
+	 * @param localDimension
+	 *            dimension in local coordinate system to be transformed.
+	 * @return dimension in global coordinates
+	 */
+	public Dimension2D localToGlobal(final Dimension2D localDimension) {
+		PNode n = this;
+		while (n != null) {
+			n.localToParent(localDimension);
+			n = n.parent;
+		}
+		return localDimension;
+	}
 
-    /**
-     * Transform the given dimension from this node's local coordinate system to
-     * the global coordinate system. Note that this will modify the dimension
-     * parameter.
-     * 
-     * @param localDimension dimension in local coordinate system to be
-     *            transformed.
-     * @return dimension in global coordinates
-     */
-    public Dimension2D localToGlobal(final Dimension2D localDimension) {
-        PNode n = this;
-        while (n != null) {
-            n.localToParent(localDimension);
-            n = n.parent;
-        }
-        return localDimension;
-    }
+	/**
+	 * Transform the given rectangle from this node's local coordinate system to
+	 * the global coordinate system. Note that this will modify the rectangle
+	 * parameter.
+	 * 
+	 * @param localRectangle
+	 *            rectangle in local coordinate system to be transformed.
+	 * @return rectangle in global coordinates
+	 */
+	public Rectangle2D localToGlobal(final Rectangle2D localRectangle) {
+		PNode n = this;
+		while (n != null) {
+			n.localToParent(localRectangle);
+			n = n.parent;
+		}
+		return localRectangle;
+	}
 
-    /**
-     * Transform the given rectangle from this node's local coordinate system to
-     * the global coordinate system. Note that this will modify the rectangle
-     * parameter.
-     * 
-     * @param localRectangle rectangle in local coordinate system to be
-     *            transformed.
-     * @return rectangle in global coordinates
-     */
-    public Rectangle2D localToGlobal(final Rectangle2D localRectangle) {
-        PNode n = this;
-        while (n != null) {
-            n.localToParent(localRectangle);
-            n = n.parent;
-        }
-        return localRectangle;
-    }
+	/**
+	 * Transform the given point from global coordinates to this node's local
+	 * coordinate system. Note that this will modify the point parameter.
+	 * 
+	 * @param globalPoint
+	 *            point in global coordinates to be transformed.
+	 * @return point in this node's local coordinate system.
+	 */
+	public Point2D globalToLocal(final Point2D globalPoint) {
+		final PAffineTransform globalTransform = computeGlobalTransform(this);
+		return globalTransform.inverseTransform(globalPoint, globalPoint);
+	}
 
-    /**
-     * Transform the given point from global coordinates to this node's local
-     * coordinate system. Note that this will modify the point parameter.
-     * 
-     * @param globalPoint point in global coordinates to be transformed.
-     * @return point in this node's local coordinate system.
-     */
-    public Point2D globalToLocal(final Point2D globalPoint) {
-        if (parent != null) {
-            parent.globalToLocal(globalPoint);
-        }
-        return parentToLocal(globalPoint);
-    }
+	private PAffineTransform computeGlobalTransform(final PNode node) {
+		if (node == null) {
+			return new PAffineTransform();
+		}
+		
+		final PAffineTransform parentGlobalTransform = computeGlobalTransform(node.parent);
+		if (node.transform != null) {
+			parentGlobalTransform.concatenate(node.transform);
+		}
+		return parentGlobalTransform;
+	}
 
-    /**
-     * Transform the given dimension from global coordinates to this node's
-     * local coordinate system. Note that this will modify the dimension
-     * parameter.
-     * 
-     * @param globalDimension dimension in global coordinates to be transformed.
-     * @return dimension in this node's local coordinate system.
-     */
-    public Dimension2D globalToLocal(final Dimension2D globalDimension) {
-        if (parent != null) {
-            parent.globalToLocal(globalDimension);
-        }
-        return parentToLocal(globalDimension);
-    }
+	/**
+	 * Transform the given dimension from global coordinates to this node's
+	 * local coordinate system. Note that this will modify the dimension
+	 * parameter.
+	 * 
+	 * @param globalDimension
+	 *            dimension in global coordinates to be transformed.
+	 * @return dimension in this node's local coordinate system.
+	 */
+	public Dimension2D globalToLocal(final Dimension2D globalDimension) {
+		if (parent != null) {
+			parent.globalToLocal(globalDimension);
+		}
+		return parentToLocal(globalDimension);
+	}
 
-    /**
-     * Transform the given rectangle from global coordinates to this node's
-     * local coordinate system. Note that this will modify the rectangle
-     * parameter.
-     * 
-     * @param globalRectangle rectangle in global coordinates to be transformed.
-     * @return rectangle in this node's local coordinate system.
-     */
-    public Rectangle2D globalToLocal(final Rectangle2D globalRectangle) {
-        if (parent != null) {
-            parent.globalToLocal(globalRectangle);
-        }
-        return parentToLocal(globalRectangle);
-    }
+	/**
+	 * Transform the given rectangle from global coordinates to this node's
+	 * local coordinate system. Note that this will modify the rectangle
+	 * parameter.
+	 * 
+	 * @param globalRectangle
+	 *            rectangle in global coordinates to be transformed.
+	 * @return rectangle in this node's local coordinate system.
+	 */
+	public Rectangle2D globalToLocal(final Rectangle2D globalRectangle) {
+		if (parent != null) {
+			parent.globalToLocal(globalRectangle);
+		}
+		return parentToLocal(globalRectangle);
+	}
 
-    /**
-     * Return the transform that converts local coordinates at this node to the
-     * global coordinate system.
-     * 
-     * @param dest PAffineTransform to transform to global coordinates
-     * @return The concatenation of transforms from the top node down to this
-     *         node.
-     */
-    public PAffineTransform getLocalToGlobalTransform(final PAffineTransform dest) {
-        PAffineTransform result = dest;
-        if (parent != null) {
-            result = parent.getLocalToGlobalTransform(result);
-            if (transform != null) {
-                result.concatenate(transform);
-            }
-        }
-        else if (dest == null) {
-            result = getTransform();
-        }
-        else if (transform != null) {
-            result.setTransform(transform);
-        }
-        else {
-            result.setToIdentity();
-        }
+	/**
+	 * Return the transform that converts local coordinates at this node to the
+	 * global coordinate system.
+	 * 
+	 * @param dest
+	 *            PAffineTransform to transform to global coordinates
+	 * @return The concatenation of transforms from the top node down to this
+	 *         node.
+	 */
+	public PAffineTransform getLocalToGlobalTransform(
+			final PAffineTransform dest) {
+		PAffineTransform result = dest;
+		if (parent != null) {
+			result = parent.getLocalToGlobalTransform(result);
+			if (transform != null) {
+				result.concatenate(transform);
+			}
+		} else if (dest == null) {
+			result = getTransform();
+		} else if (transform != null) {
+			result.setTransform(transform);
+		} else {
+			result.setToIdentity();
+		}
 
-        return result;
-    }
+		return result;
+	}
 
-    /**
-     * Return the transform that converts global coordinates to local
-     * coordinates of this node.
-     * 
-     * @param dest PAffineTransform to transform from global to local
-     * 
-     * @return The inverse of the concatenation of transforms from the root down
-     *         to this node.
-     */
-    public PAffineTransform getGlobalToLocalTransform(final PAffineTransform dest) {
-        PAffineTransform result = getLocalToGlobalTransform(dest);
-        try {
-            result.setTransform(result.createInverse());
-        }
-        catch (final NoninvertibleTransformException e) {
-            throw new PAffineTransformException(e, result);
-        }
-        return result;
-    }
+	/**
+	 * Return the transform that converts global coordinates to local
+	 * coordinates of this node.
+	 * 
+	 * @param dest
+	 *            PAffineTransform to transform from global to local
+	 * 
+	 * @return The inverse of the concatenation of transforms from the root down
+	 *         to this node.
+	 */
+	public PAffineTransform getGlobalToLocalTransform(
+			final PAffineTransform dest) {
+		PAffineTransform result = getLocalToGlobalTransform(dest);
+		try {
+			result.setTransform(result.createInverse());
+		} catch (final NoninvertibleTransformException e) {
+			throw new PAffineTransformException(e, result);
+		}
+		return result;
+	}
 
-    // ****************************************************************
-    // Event Listeners - Methods for adding and removing event listeners
-    // from a node.
-    //
-    // Here methods are provided to add property change listeners and
-    // input event listeners. The property change listeners are notified
-    // when certain properties of this node change, and the input event
-    // listeners are notified when the nodes receives new key and mouse
-    // events.
-    // ****************************************************************
+	// ****************************************************************
+	// Event Listeners - Methods for adding and removing event listeners
+	// from a node.
+	//
+	// Here methods are provided to add property change listeners and
+	// input event listeners. The property change listeners are notified
+	// when certain properties of this node change, and the input event
+	// listeners are notified when the nodes receives new key and mouse
+	// events.
+	// ****************************************************************
 
-    /**
-     * Return the list of event listeners associated with this node.
-     * 
-     * @return event listener list or null
-     */
-    public EventListenerList getListenerList() {
-        return listenerList;
-    }
+	/**
+	 * Return the list of event listeners associated with this node.
+	 * 
+	 * @return event listener list or null
+	 */
+	public EventListenerList getListenerList() {
+		return listenerList;
+	}
 
-    /**
-     * Adds the specified input event listener to receive input events from this
-     * node.
-     * 
-     * @param listener the new input listener
-     */
-    public void addInputEventListener(final PInputEventListener listener) {
-        if (listenerList == null) {
-            listenerList = new EventListenerList();
-        }
-        getListenerList().add(PInputEventListener.class, listener);
-    }
+	/**
+	 * Adds the specified input event listener to receive input events from this
+	 * node.
+	 * 
+	 * @param listener
+	 *            the new input listener
+	 */
+	public void addInputEventListener(final PInputEventListener listener) {
+		if (listenerList == null) {
+			listenerList = new EventListenerList();
+		}
+		getListenerList().add(PInputEventListener.class, listener);
+	}
 
-    /**
-     * Removes the specified input event listener so that it no longer receives
-     * input events from this node.
-     * 
-     * @param listener the input listener to remove
-     */
-    public void removeInputEventListener(final PInputEventListener listener) {
-        if (listenerList == null) {
-            return;
-        }
-        getListenerList().remove(PInputEventListener.class, listener);
-        if (listenerList.getListenerCount() == 0) {
-            listenerList = null;
-        }
-    }
+	/**
+	 * Removes the specified input event listener so that it no longer receives
+	 * input events from this node.
+	 * 
+	 * @param listener
+	 *            the input listener to remove
+	 */
+	public void removeInputEventListener(final PInputEventListener listener) {
+		if (listenerList == null) {
+			return;
+		}
+		getListenerList().remove(PInputEventListener.class, listener);
+		if (listenerList.getListenerCount() == 0) {
+			listenerList = null;
+		}
+	}
 
-    /**
-     * Add a PropertyChangeListener to the listener list. The listener is
-     * registered for all properties. See the fields in PNode and subclasses
-     * that start with PROPERTY_ to find out which properties exist.
-     * 
-     * @param listener The PropertyChangeListener to be added
-     */
-    public void addPropertyChangeListener(final PropertyChangeListener listener) {
-        if (changeSupport == null) {
-            changeSupport = new SwingPropertyChangeSupport(this);
-        }
-        changeSupport.addPropertyChangeListener(listener);
-    }
+	/**
+	 * Add a PropertyChangeListener to the listener list. The listener is
+	 * registered for all properties. See the fields in PNode and subclasses
+	 * that start with PROPERTY_ to find out which properties exist.
+	 * 
+	 * @param listener
+	 *            The PropertyChangeListener to be added
+	 */
+	public void addPropertyChangeListener(final PropertyChangeListener listener) {
+		if (changeSupport == null) {
+			changeSupport = new SwingPropertyChangeSupport(this);
+		}
+		changeSupport.addPropertyChangeListener(listener);
+	}
 
-    /**
-     * Add a PropertyChangeListener for a specific property. The listener will
-     * be invoked only when a call on firePropertyChange names that specific
-     * property. See the fields in PNode and subclasses that start with
-     * PROPERTY_ to find out which properties are supported.
-     * 
-     * @param propertyName The name of the property to listen on.
-     * @param listener The PropertyChangeListener to be added
-     */
-    public void addPropertyChangeListener(final String propertyName, final PropertyChangeListener listener) {
-        if (listener == null) {
-            return;
-        }
-        if (changeSupport == null) {
-            changeSupport = new SwingPropertyChangeSupport(this);
-        }
-        changeSupport.addPropertyChangeListener(propertyName, listener);
-    }
+	/**
+	 * Add a PropertyChangeListener for a specific property. The listener will
+	 * be invoked only when a call on firePropertyChange names that specific
+	 * property. See the fields in PNode and subclasses that start with
+	 * PROPERTY_ to find out which properties are supported.
+	 * 
+	 * @param propertyName
+	 *            The name of the property to listen on.
+	 * @param listener
+	 *            The PropertyChangeListener to be added
+	 */
+	public void addPropertyChangeListener(final String propertyName,
+			final PropertyChangeListener listener) {
+		if (listener == null) {
+			return;
+		}
+		if (changeSupport == null) {
+			changeSupport = new SwingPropertyChangeSupport(this);
+		}
+		changeSupport.addPropertyChangeListener(propertyName, listener);
+	}
 
-    /**
-     * Remove a PropertyChangeListener from the listener list. This removes a
-     * PropertyChangeListener that was registered for all properties.
-     * 
-     * @param listener The PropertyChangeListener to be removed
-     */
-    public void removePropertyChangeListener(final PropertyChangeListener listener) {
-        if (changeSupport != null) {
-            changeSupport.removePropertyChangeListener(listener);
-        }
-    }
+	/**
+	 * Remove a PropertyChangeListener from the listener list. This removes a
+	 * PropertyChangeListener that was registered for all properties.
+	 * 
+	 * @param listener
+	 *            The PropertyChangeListener to be removed
+	 */
+	public void removePropertyChangeListener(
+			final PropertyChangeListener listener) {
+		if (changeSupport != null) {
+			changeSupport.removePropertyChangeListener(listener);
+		}
+	}
 
-    /**
-     * Remove a PropertyChangeListener for a specific property.
-     * 
-     * @param propertyName The name of the property that was listened on.
-     * @param listener The PropertyChangeListener to be removed
-     */
-    public void removePropertyChangeListener(final String propertyName, final PropertyChangeListener listener) {
-        if (listener == null) {
-            return;
-        }
-        if (changeSupport == null) {
-            return;
-        }
-        changeSupport.removePropertyChangeListener(propertyName, listener);
-    }
+	/**
+	 * Remove a PropertyChangeListener for a specific property.
+	 * 
+	 * @param propertyName
+	 *            The name of the property that was listened on.
+	 * @param listener
+	 *            The PropertyChangeListener to be removed
+	 */
+	public void removePropertyChangeListener(final String propertyName,
+			final PropertyChangeListener listener) {
+		if (listener == null) {
+			return;
+		}
+		if (changeSupport == null) {
+			return;
+		}
+		changeSupport.removePropertyChangeListener(propertyName, listener);
+	}
 
-    /**
-     * Return the propertyChangeParentMask that determines which property change
-     * events are forwared to this nodes parent so that its property change
-     * listeners will also be notified.
-     * 
-     * @return mask used for deciding whether to bubble property changes up to
-     *         parent
-     */
-    public int getPropertyChangeParentMask() {
-        return propertyChangeParentMask;
-    }
+	/**
+	 * Return the propertyChangeParentMask that determines which property change
+	 * events are forwared to this nodes parent so that its property change
+	 * listeners will also be notified.
+	 * 
+	 * @return mask used for deciding whether to bubble property changes up to
+	 *         parent
+	 */
+	public int getPropertyChangeParentMask() {
+		return propertyChangeParentMask;
+	}
 
-    /**
-     * Set the propertyChangeParentMask that determines which property change
-     * events are forwared to this nodes parent so that its property change
-     * listeners will also be notified.
-     * 
-     * @param propertyChangeParentMask new mask for property change bubble up
-     */
-    public void setPropertyChangeParentMask(final int propertyChangeParentMask) {
-        this.propertyChangeParentMask = propertyChangeParentMask;
-    }
+	/**
+	 * Set the propertyChangeParentMask that determines which property change
+	 * events are forwared to this nodes parent so that its property change
+	 * listeners will also be notified.
+	 * 
+	 * @param propertyChangeParentMask
+	 *            new mask for property change bubble up
+	 */
+	public void setPropertyChangeParentMask(final int propertyChangeParentMask) {
+		this.propertyChangeParentMask = propertyChangeParentMask;
+	}
 
-    /**
-     * Report a bound property update to any registered listeners. No event is
-     * fired if old and new are equal and non-null. If the propertyCode exists
-     * in this node's propertyChangeParentMask then a property change event will
-     * also be fired on this nodes parent.
-     * 
-     * @param propertyCode The code of the property changed.
-     * @param propertyName The name of the property that was changed.
-     * @param oldValue The old value of the property.
-     * @param newValue The new value of the property.
-     */
-    protected void firePropertyChange(final int propertyCode, final String propertyName, final Object oldValue,
-            final Object newValue) {
-        PropertyChangeEvent event = null;
+	/**
+	 * Report a bound property update to any registered listeners. No event is
+	 * fired if old and new are equal and non-null. If the propertyCode exists
+	 * in this node's propertyChangeParentMask then a property change event will
+	 * also be fired on this nodes parent.
+	 * 
+	 * @param propertyCode
+	 *            The code of the property changed.
+	 * @param propertyName
+	 *            The name of the property that was changed.
+	 * @param oldValue
+	 *            The old value of the property.
+	 * @param newValue
+	 *            The new value of the property.
+	 */
+	protected void firePropertyChange(final int propertyCode,
+			final String propertyName, final Object oldValue,
+			final Object newValue) {
+		PropertyChangeEvent event = null;
 
-        if (changeSupport != null) {
-            event = new PropertyChangeEvent(this, propertyName, oldValue, newValue);
-            changeSupport.firePropertyChange(event);
-        }
-        if (parent != null && (propertyCode & propertyChangeParentMask) != 0) {
-            if (event == null) {
-                event = new PropertyChangeEvent(this, propertyName, oldValue, newValue);
-            }
-            parent.fireChildPropertyChange(event, propertyCode);
-        }
-    }
+		if (changeSupport != null) {
+			event = new PropertyChangeEvent(this, propertyName, oldValue,
+					newValue);
+			changeSupport.firePropertyChange(event);
+		}
+		if (parent != null && (propertyCode & propertyChangeParentMask) != 0) {
+			if (event == null) {
+				event = new PropertyChangeEvent(this, propertyName, oldValue,
+						newValue);
+			}
+			parent.fireChildPropertyChange(event, propertyCode);
+		}
+	}
 
-    /**
-     * Called by child node to forward property change events up the node tree
-     * so that property change listeners registered with this node will be
-     * notified of property changes of its children nodes. For performance
-     * reason only propertyCodes listed in the propertyChangeParentMask are
-     * forwarded.
-     * 
-     * @param event The property change event containing source node and changed
-     *            values.
-     * @param propertyCode The code of the property changed.
-     */
-    protected void fireChildPropertyChange(final PropertyChangeEvent event, final int propertyCode) {
-        if (changeSupport != null) {
-            changeSupport.firePropertyChange(event);
-        }
-        if (parent != null && (propertyCode & propertyChangeParentMask) != 0) {
-            parent.fireChildPropertyChange(event, propertyCode);
-        }
-    }
+	/**
+	 * Called by child node to forward property change events up the node tree
+	 * so that property change listeners registered with this node will be
+	 * notified of property changes of its children nodes. For performance
+	 * reason only propertyCodes listed in the propertyChangeParentMask are
+	 * forwarded.
+	 * 
+	 * @param event
+	 *            The property change event containing source node and changed
+	 *            values.
+	 * @param propertyCode
+	 *            The code of the property changed.
+	 */
+	protected void fireChildPropertyChange(final PropertyChangeEvent event,
+			final int propertyCode) {
+		if (changeSupport != null) {
+			changeSupport.firePropertyChange(event);
+		}
+		if (parent != null && (propertyCode & propertyChangeParentMask) != 0) {
+			parent.fireChildPropertyChange(event, propertyCode);
+		}
+	}
 
-    // ****************************************************************
-    // Bounds Geometry - Methods for setting and querying the bounds
-    // of this node.
-    //
-    // The bounds of a node store the node's position and size in
-    // the nodes local coordinate system. Many node subclasses will need
-    // to override the setBounds method so that they can update their
-    // internal state appropriately. See PPath for an example.
-    //
-    // Since the bounds are stored in the local coordinate system
-    // they WILL NOT change if the node is scaled, translated, or rotated.
-    //
-    // The bounds may be accessed with either getBounds, or
-    // getBoundsReference. The former returns a copy of the bounds
-    // the latter returns a reference to the nodes bounds that should
-    // normally not be modified. If a node is marked as volatile then
-    // it may modify its bounds before returning them from getBoundsReference,
-    // otherwise it may not.
-    // ****************************************************************
+	// ****************************************************************
+	// Bounds Geometry - Methods for setting and querying the bounds
+	// of this node.
+	//
+	// The bounds of a node store the node's position and size in
+	// the nodes local coordinate system. Many node subclasses will need
+	// to override the setBounds method so that they can update their
+	// internal state appropriately. See PPath for an example.
+	//
+	// Since the bounds are stored in the local coordinate system
+	// they WILL NOT change if the node is scaled, translated, or rotated.
+	//
+	// The bounds may be accessed with either getBounds, or
+	// getBoundsReference. The former returns a copy of the bounds
+	// the latter returns a reference to the nodes bounds that should
+	// normally not be modified. If a node is marked as volatile then
+	// it may modify its bounds before returning them from getBoundsReference,
+	// otherwise it may not.
+	// ****************************************************************
 
-    /**
-     * Return a copy of this node's bounds. These bounds are stored in the local
-     * coordinate system of this node and do not include the bounds of any of
-     * this node's children.
-     * 
-     * @return copy of this node's local bounds
-     */
-    public PBounds getBounds() {
-        return (PBounds) getBoundsReference().clone();
-    }
+	/**
+	 * Return a copy of this node's bounds. These bounds are stored in the local
+	 * coordinate system of this node and do not include the bounds of any of
+	 * this node's children.
+	 * 
+	 * @return copy of this node's local bounds
+	 */
+	public PBounds getBounds() {
+		return (PBounds) getBoundsReference().clone();
+	}
 
-    /**
-     * Return a direct reference to this node's bounds. These bounds are stored
-     * in the local coordinate system of this node and do not include the bounds
-     * of any of this node's children. The value returned should not be
-     * modified.
-     * 
-     * @return direct reference to local bounds
-     */
-    public PBounds getBoundsReference() {
-        return bounds;
-    }
+	/**
+	 * Return a direct reference to this node's bounds. These bounds are stored
+	 * in the local coordinate system of this node and do not include the bounds
+	 * of any of this node's children. The value returned should not be
+	 * modified.
+	 * 
+	 * @return direct reference to local bounds
+	 */
+	public PBounds getBoundsReference() {
+		return bounds;
+	}
 
-    /**
-     * Notify this node that you will begin to repeatedly call  
-     * For example, If you have two nodes, A and B, and you call
-     * 
-     *  
+	 * For example, If you have two nodes, A and B, and you call
+	 * 
+	 *  
-     *             For example, If you have two nodes, A and B, and you call
-     * 
-     *              
+	 *             For example, If you have two nodes, A and B, and you call
+	 * 
+	 *             setBounds
+	/**
+	 * Notify this node that you will begin to repeatedly call setBounds
      * . When you
-     * are done call endResizeBounds to let the node know that you
-     * are done.
-     */
-    public void startResizeBounds() {
-    }
+	 * are done call endResizeBounds to let the node know that you
+	 * are done.
+	 */
+	public void startResizeBounds() {
+	}
 
-    /**
-     * Notify this node that you have finished a resize bounds sequence.
-     */
-    public void endResizeBounds() {
-    }
+	/**
+	 * Notify this node that you have finished a resize bounds sequence.
+	 */
+	public void endResizeBounds() {
+	}
 
-    /**
-     * Set's this node's bounds left position, leaving y, width, and height
-     * unchanged.
-     * 
-     * @param x new x position of bounds
-     * 
-     * @return whether the change was successful
-     */
-    public boolean setX(final double x) {
-        return setBounds(x, getY(), getWidth(), getHeight());
-    }
+	/**
+	 * Set's this node's bounds left position, leaving y, width, and height
+	 * unchanged.
+	 * 
+	 * @param x
+	 *            new x position of bounds
+	 * 
+	 * @return whether the change was successful
+	 */
+	public boolean setX(final double x) {
+		return setBounds(x, getY(), getWidth(), getHeight());
+	}
 
-    /**
-     * Set's this node's bounds top position, leaving x, width, and height
-     * unchanged.
-     * 
-     * @param y new y position of bounds
-     * 
-     * @return whether the change was successful
-     */
-    public boolean setY(final double y) {
-        return setBounds(getX(), y, getWidth(), getHeight());
-    }
+	/**
+	 * Set's this node's bounds top position, leaving x, width, and height
+	 * unchanged.
+	 * 
+	 * @param y
+	 *            new y position of bounds
+	 * 
+	 * @return whether the change was successful
+	 */
+	public boolean setY(final double y) {
+		return setBounds(getX(), y, getWidth(), getHeight());
+	}
 
-    /**
-     * Set's this node's bounds width, leaving x, y, and height unchanged.
-     * 
-     * @param width new width position of bounds
-     * 
-     * @return whether the change was successful
-     */
-    public boolean setWidth(final double width) {
-        return setBounds(getX(), getY(), width, getHeight());
-    }
+	/**
+	 * Set's this node's bounds width, leaving x, y, and height unchanged.
+	 * 
+	 * @param width
+	 *            new width position of bounds
+	 * 
+	 * @return whether the change was successful
+	 */
+	public boolean setWidth(final double width) {
+		return setBounds(getX(), getY(), width, getHeight());
+	}
 
-    /**
-     * Set's this node's bounds height, leaving x, y, and width unchanged.
-     * 
-     * @param height new height position of bounds
-     * 
-     * @return whether the change was successful
-     */
-    public boolean setHeight(final double height) {
-        return setBounds(getX(), getY(), getWidth(), height);
-    }
+	/**
+	 * Set's this node's bounds height, leaving x, y, and width unchanged.
+	 * 
+	 * @param height
+	 *            new height position of bounds
+	 * 
+	 * @return whether the change was successful
+	 */
+	public boolean setHeight(final double height) {
+		return setBounds(getX(), getY(), getWidth(), height);
+	}
 
-    /**
-     * Set the bounds of this node to the given value. These bounds are stored
-     * in the local coordinate system of this node.
-     * 
-     * @param newBounds bounds to apply to this node
-     * 
-     * @return true if the bounds changed.
-     */
-    public boolean setBounds(final Rectangle2D newBounds) {
-        return setBounds(newBounds.getX(), newBounds.getY(), newBounds.getWidth(), newBounds.getHeight());
-    }
+	/**
+	 * Set the bounds of this node to the given value. These bounds are stored
+	 * in the local coordinate system of this node.
+	 * 
+	 * @param newBounds
+	 *            bounds to apply to this node
+	 * 
+	 * @return true if the bounds changed.
+	 */
+	public boolean setBounds(final Rectangle2D newBounds) {
+		return setBounds(newBounds.getX(), newBounds.getY(), newBounds
+				.getWidth(), newBounds.getHeight());
+	}
 
-    /**
-     * Set the bounds of this node to the given position and size. These bounds
-     * are stored in the local coordinate system of this node.
-     * 
-     * If the width or height is less then or equal to zero then the bound's
-     * empty bit will be set to true.
-     * 
-     * Subclasses must call the super.setBounds() method.
-     * 
-     * @param x x position of bounds
-     * @param y y position of bounds
-     * @param width width to apply to the bounds
-     * @param height height to apply to the bounds
-     * 
-     * @return true if the bounds changed.
-     */
-    public boolean setBounds(final double x, final double y, final double width, final double height) {
-        if (bounds.x != x || bounds.y != y || bounds.width != width || bounds.height != height) {
-            bounds.setRect(x, y, width, height);
+	/**
+	 * Set the bounds of this node to the given position and size. These bounds
+	 * are stored in the local coordinate system of this node.
+	 * 
+	 * If the width or height is less then or equal to zero then the bound's
+	 * empty bit will be set to true.
+	 * 
+	 * Subclasses must call the super.setBounds() method.
+	 * 
+	 * @param x
+	 *            x position of bounds
+	 * @param y
+	 *            y position of bounds
+	 * @param width
+	 *            width to apply to the bounds
+	 * @param height
+	 *            height to apply to the bounds
+	 * 
+	 * @return true if the bounds changed.
+	 */
+	public boolean setBounds(final double x, final double y,
+			final double width, final double height) {
+		if (bounds.x != x || bounds.y != y || bounds.width != width
+				|| bounds.height != height) {
+			bounds.setRect(x, y, width, height);
 
-            if (width <= 0 || height <= 0) {
-                bounds.reset();
-            }
+			if (width <= 0 || height <= 0) {
+				bounds.reset();
+			}
 
-            internalUpdateBounds(x, y, width, height);
-            invalidatePaint();
-            signalBoundsChanged();
-            return true;
-        }
-        // Don't put any invalidating code here or else nodes with volatile
-        // bounds will
-        // create a soft infinite loop (calling Swing.invokeLater()) when they
-        // validate
-        // their bounds.
-        return false;
-    }
+			internalUpdateBounds(x, y, width, height);
+			invalidatePaint();
+			signalBoundsChanged();
+			return true;
+		}
+		// Don't put any invalidating code here or else nodes with volatile
+		// bounds will
+		// create a soft infinite loop (calling Swing.invokeLater()) when they
+		// validate
+		// their bounds.
+		return false;
+	}
 
-    /**
-     * Gives nodes a chance to update their internal structure before bounds
-     * changed notifications are sent. When this message is recived the nodes
-     * bounds field will contain the new value.
-     * 
-     * See PPath for an example that uses this method.
-     * 
-     * @param x x position of bounds
-     * @param y y position of bounds
-     * @param width width to apply to the bounds
-     * @param height height to apply to the bounds
-     */
-    protected void internalUpdateBounds(final double x, final double y, final double width, final double height) {
-    }
+	/**
+	 * Gives nodes a chance to update their internal structure before bounds
+	 * changed notifications are sent. When this message is recived the nodes
+	 * bounds field will contain the new value.
+	 * 
+	 * See PPath for an example that uses this method.
+	 * 
+	 * @param x
+	 *            x position of bounds
+	 * @param y
+	 *            y position of bounds
+	 * @param width
+	 *            width to apply to the bounds
+	 * @param height
+	 *            height to apply to the bounds
+	 */
+	protected void internalUpdateBounds(final double x, final double y,
+			final double width, final double height) {
+	}
 
-    /**
-     * Set the empty bit of this bounds to true.
-     */
-    public void resetBounds() {
-        setBounds(0, 0, 0, 0);
-    }
+	/**
+	 * Set the empty bit of this bounds to true.
+	 */
+	public void resetBounds() {
+		setBounds(0, 0, 0, 0);
+	}
 
-    /**
-     * Return the x position (in local coords) of this node's bounds.
-     * 
-     * @return local x position of bounds
-     */
-    public double getX() {
-        return getBoundsReference().getX();
-    }
+	/**
+	 * Return the x position (in local coords) of this node's bounds.
+	 * 
+	 * @return local x position of bounds
+	 */
+	public double getX() {
+		return getBoundsReference().getX();
+	}
 
-    /**
-     * Return the y position (in local coords) of this node's bounds.
-     * 
-     * @return local y position of bounds
-     */
-    public double getY() {
-        return getBoundsReference().getY();
-    }
+	/**
+	 * Return the y position (in local coords) of this node's bounds.
+	 * 
+	 * @return local y position of bounds
+	 */
+	public double getY() {
+		return getBoundsReference().getY();
+	}
 
-    /**
-     * Return the width (in local coords) of this node's bounds.
-     * 
-     * @return local width of bounds
-     */
-    public double getWidth() {
-        return getBoundsReference().getWidth();
-    }
+	/**
+	 * Return the width (in local coords) of this node's bounds.
+	 * 
+	 * @return local width of bounds
+	 */
+	public double getWidth() {
+		return getBoundsReference().getWidth();
+	}
 
-    /**
-     * Return the height (in local coords) of this node's bounds.
-     * 
-     * @return local width of bounds
-     */
-    public double getHeight() {
-        return getBoundsReference().getHeight();
-    }
+	/**
+	 * Return the height (in local coords) of this node's bounds.
+	 * 
+	 * @return local width of bounds
+	 */
+	public double getHeight() {
+		return getBoundsReference().getHeight();
+	}
 
-    /**
-     * Return a copy of the bounds of this node in the global coordinate system.
-     * 
-     * @return the bounds in global coordinate system.
-     */
-    public PBounds getGlobalBounds() {
-        return (PBounds) localToGlobal(getBounds());
-    }
+	/**
+	 * Return a copy of the bounds of this node in the global coordinate system.
+	 * 
+	 * @return the bounds in global coordinate system.
+	 */
+	public PBounds getGlobalBounds() {
+		return (PBounds) localToGlobal(getBounds());
+	}
 
-    /**
-     * Center the bounds of this node so that they are centered on the given
-     * point specified on the local coordinates of this node. Note that this
-     * method will modify the nodes bounds, while centerFullBoundsOnPoint will
-     * modify the nodes transform.
-     * 
-     * @param localX x position of point around which to center bounds
-     * @param localY y position of point around which to center bounds
-     * 
-     * @return true if the bounds changed.
-     */
-    public boolean centerBoundsOnPoint(final double localX, final double localY) {
-        final double dx = localX - bounds.getCenterX();
-        final double dy = localY - bounds.getCenterY();
-        return setBounds(bounds.x + dx, bounds.y + dy, bounds.width, bounds.height);
-    }
+	/**
+	 * Center the bounds of this node so that they are centered on the given
+	 * point specified on the local coordinates of this node. Note that this
+	 * method will modify the nodes bounds, while centerFullBoundsOnPoint will
+	 * modify the nodes transform.
+	 * 
+	 * @param localX
+	 *            x position of point around which to center bounds
+	 * @param localY
+	 *            y position of point around which to center bounds
+	 * 
+	 * @return true if the bounds changed.
+	 */
+	public boolean centerBoundsOnPoint(final double localX, final double localY) {
+		final double dx = localX - bounds.getCenterX();
+		final double dy = localY - bounds.getCenterY();
+		return setBounds(bounds.x + dx, bounds.y + dy, bounds.width,
+				bounds.height);
+	}
 
-    /**
-     * Center the full bounds of this node so that they are centered on the
-     * given point specified on the local coordinates of this nodes parent. Note
-     * that this method will modify the nodes transform, while
-     * centerBoundsOnPoint will modify the nodes bounds.
-     * 
-     * @param parentX x position around which to center full bounds
-     * @param parentY y position around which to center full bounds
-     */
-    public void centerFullBoundsOnPoint(final double parentX, final double parentY) {
-        final double dx = parentX - getFullBoundsReference().getCenterX();
-        final double dy = parentY - getFullBoundsReference().getCenterY();
-        offset(dx, dy);
-    }
+	/**
+	 * Center the full bounds of this node so that they are centered on the
+	 * given point specified on the local coordinates of this nodes parent. Note
+	 * that this method will modify the nodes transform, while
+	 * centerBoundsOnPoint will modify the nodes bounds.
+	 * 
+	 * @param parentX
+	 *            x position around which to center full bounds
+	 * @param parentY
+	 *            y position around which to center full bounds
+	 */
+	public void centerFullBoundsOnPoint(final double parentX,
+			final double parentY) {
+		final double dx = parentX - getFullBoundsReference().getCenterX();
+		final double dy = parentY - getFullBoundsReference().getCenterY();
+		offset(dx, dy);
+	}
 
-    /**
-     * Return true if this node intersects the given rectangle specified in
-     * local bounds. If the geometry of this node is complex this method can
-     * become expensive, it is therefore recommended that
-     * fullIntersects is used for quick rejects before calling this
-     * method.
-     * 
-     * @param localBounds the bounds to test for intersection against
-     * @return true if the given rectangle intersects this nodes geometry.
-     */
-    public boolean intersects(final Rectangle2D localBounds) {
-        if (localBounds == null) {
-            return true;
-        }
-        return getBoundsReference().intersects(localBounds);
-    }
+	/**
+	 * Return true if this node intersects the given rectangle specified in
+	 * local bounds. If the geometry of this node is complex this method can
+	 * become expensive, it is therefore recommended that
+	 * fullIntersects is used for quick rejects before calling this
+	 * method.
+	 * 
+	 * @param localBounds
+	 *            the bounds to test for intersection against
+	 * @return true if the given rectangle intersects this nodes geometry.
+	 */
+	public boolean intersects(final Rectangle2D localBounds) {
+		if (localBounds == null) {
+			return true;
+		}
+		return getBoundsReference().intersects(localBounds);
+	}
 
-    // ****************************************************************
-    // Full Bounds - Methods for computing and querying the
-    // full bounds of this node.
-    // 
-    // The full bounds of a node store the nodes bounds
-    // together with the union of the bounds of all the
-    // node's descendants. The full bounds are stored in the parent
-    // coordinate system of this node, the full bounds DOES change
-    // when you translate, scale, or rotate this node.
-    // 
-    // The full bounds may be accessed with either getFullBounds, or
-    // getFullBoundsReference. The former returns a copy of the full bounds
-    // the latter returns a reference to the node's full bounds that should
-    // not be modified.
-    // ****************************************************************
+	// ****************************************************************
+	// Full Bounds - Methods for computing and querying the
+	// full bounds of this node.
+	// 
+	// The full bounds of a node store the nodes bounds
+	// together with the union of the bounds of all the
+	// node's descendants. The full bounds are stored in the parent
+	// coordinate system of this node, the full bounds DOES change
+	// when you translate, scale, or rotate this node.
+	// 
+	// The full bounds may be accessed with either getFullBounds, or
+	// getFullBoundsReference. The former returns a copy of the full bounds
+	// the latter returns a reference to the node's full bounds that should
+	// not be modified.
+	// ****************************************************************
 
-    /**
-     * Return a copy of this node's full bounds. These bounds are stored in the
-     * parent coordinate system of this node and they include the union of this
-     * node's bounds and all the bounds of it's descendants.
-     * 
-     * @return a copy of this node's full bounds.
-     */
-    public PBounds getFullBounds() {
-        return (PBounds) getFullBoundsReference().clone();
-    }
+	/**
+	 * Return a copy of this node's full bounds. These bounds are stored in the
+	 * parent coordinate system of this node and they include the union of this
+	 * node's bounds and all the bounds of it's descendants.
+	 * 
+	 * @return a copy of this node's full bounds.
+	 */
+	public PBounds getFullBounds() {
+		return (PBounds) getFullBoundsReference().clone();
+	}
 
-    /**
-     * Return a reference to this node's full bounds cache. These bounds are
-     * stored in the parent coordinate system of this node and they include the
-     * union of this node's bounds and all the bounds of it's descendants. The
-     * bounds returned by this method should not be modified.
-     * 
-     * @return a reference to this node's full bounds cache.
-     */
-    public PBounds getFullBoundsReference() {
-        validateFullBounds();
-        return fullBoundsCache;
-    }
+	/**
+	 * Return a reference to this node's full bounds cache. These bounds are
+	 * stored in the parent coordinate system of this node and they include the
+	 * union of this node's bounds and all the bounds of it's descendants. The
+	 * bounds returned by this method should not be modified.
+	 * 
+	 * @return a reference to this node's full bounds cache.
+	 */
+	public PBounds getFullBoundsReference() {
+		validateFullBounds();
+		return fullBoundsCache;
+	}
 
-    /**
-     * Compute and return the full bounds of this node. If the dstBounds
-     * parameter is not null then it will be used to return the results instead
-     * of creating a new PBounds.
-     * 
-     * @param dstBounds if not null the new bounds will be stored here
-     * @return the full bounds in the parent coordinate system of this node
-     */
-    public PBounds computeFullBounds(final PBounds dstBounds) {
-        final PBounds result = getUnionOfChildrenBounds(dstBounds);
-        result.add(getBoundsReference());
-        localToParent(result);
-        return result;
-    }
+	/**
+	 * Compute and return the full bounds of this node. If the dstBounds
+	 * parameter is not null then it will be used to return the results instead
+	 * of creating a new PBounds.
+	 * 
+	 * @param dstBounds
+	 *            if not null the new bounds will be stored here
+	 * @return the full bounds in the parent coordinate system of this node
+	 */
+	public PBounds computeFullBounds(final PBounds dstBounds) {
+		final PBounds result = getUnionOfChildrenBounds(dstBounds);
+		result.add(getBoundsReference());
+		localToParent(result);
+		return result;
+	}
 
-    /**
-     * Compute and return the union of the full bounds of all the children of
-     * this node. If the dstBounds parameter is not null then it will be used to
-     * return the results instead of creating a new PBounds.
-     * 
-     * @param dstBounds if not null the new bounds will be stored here
-     * @return union of children bounds
-     */
-    public PBounds getUnionOfChildrenBounds(final PBounds dstBounds) {
-        PBounds resultBounds;
-        if (dstBounds == null) {
-            resultBounds = new PBounds();
-        }
-        else {
-            resultBounds = dstBounds;
-            resultBounds.resetToZero();
-        }
+	/**
+	 * Compute and return the union of the full bounds of all the children of
+	 * this node. If the dstBounds parameter is not null then it will be used to
+	 * return the results instead of creating a new PBounds.
+	 * 
+	 * @param dstBounds
+	 *            if not null the new bounds will be stored here
+	 * @return union of children bounds
+	 */
+	public PBounds getUnionOfChildrenBounds(final PBounds dstBounds) {
+		PBounds resultBounds;
+		if (dstBounds == null) {
+			resultBounds = new PBounds();
+		} else {
+			resultBounds = dstBounds;
+			resultBounds.resetToZero();
+		}
 
-        final int count = getChildrenCount();
-        for (int i = 0; i < count; i++) {
-            final PNode each = (PNode) children.get(i);
-            resultBounds.add(each.getFullBoundsReference());
-        }
+		final int count = getChildrenCount();
+		for (int i = 0; i < count; i++) {
+			final PNode each = (PNode) children.get(i);
+			resultBounds.add(each.getFullBoundsReference());
+		}
 
-        return resultBounds;
-    }
+		return resultBounds;
+	}
 
-    /**
-     * Return a copy of the full bounds of this node in the global coordinate
-     * system.
-     * 
-     * @return the full bounds in global coordinate system.
-     */
-    public PBounds getGlobalFullBounds() {
-        final PBounds b = getFullBounds();
-        if (parent != null) {
-            parent.localToGlobal(b);
-        }
-        return b;
-    }
+	/**
+	 * Return a copy of the full bounds of this node in the global coordinate
+	 * system.
+	 * 
+	 * @return the full bounds in global coordinate system.
+	 */
+	public PBounds getGlobalFullBounds() {
+		final PBounds b = getFullBounds();
+		if (parent != null) {
+			parent.localToGlobal(b);
+		}
+		return b;
+	}
 
-    /**
-     * Return true if the full bounds of this node intersects with the specified
-     * bounds.
-     * 
-     * @param parentBounds the bounds to test for intersection against
-     *            (specified in parent's coordinate system)
-     * @return true if this nodes full bounds intersect the given bounds.
-     */
-    public boolean fullIntersects(final Rectangle2D parentBounds) {
-        if (parentBounds == null) {
-            return true;
-        }
-        return getFullBoundsReference().intersects(parentBounds);
-    }
+	/**
+	 * Return true if the full bounds of this node intersects with the specified
+	 * bounds.
+	 * 
+	 * @param parentBounds
+	 *            the bounds to test for intersection against (specified in
+	 *            parent's coordinate system)
+	 * @return true if this nodes full bounds intersect the given bounds.
+	 */
+	public boolean fullIntersects(final Rectangle2D parentBounds) {
+		if (parentBounds == null) {
+			return true;
+		}
+		return getFullBoundsReference().intersects(parentBounds);
+	}
 
-    // ****************************************************************
-    // Bounds Damage Management - Methods used to invalidate and validate
-    // the bounds of nodes.
-    // ****************************************************************
+	// ****************************************************************
+	// Bounds Damage Management - Methods used to invalidate and validate
+	// the bounds of nodes.
+	// ****************************************************************
 
-    /**
-     * Return true if this nodes bounds may change at any time. The default
-     * behavior is to return false, subclasses that override this method to
-     * return true should also override getBoundsReference() and compute their
-     * volatile bounds there before returning the reference.
-     * 
-     * @return true if this node has volatile bounds
-     */
-    protected boolean getBoundsVolatile() {
-        return false;
-    }
+	/**
+	 * Return true if this nodes bounds may change at any time. The default
+	 * behavior is to return false, subclasses that override this method to
+	 * return true should also override getBoundsReference() and compute their
+	 * volatile bounds there before returning the reference.
+	 * 
+	 * @return true if this node has volatile bounds
+	 */
+	protected boolean getBoundsVolatile() {
+		return false;
+	}
 
-    /**
-     * Return true if this node has a child with volatile bounds.
-     * 
-     * @return true if this node has a child with volatile bounds
-     */
-    protected boolean getChildBoundsVolatile() {
-        return childBoundsVolatile;
-    }
+	/**
+	 * Return true if this node has a child with volatile bounds.
+	 * 
+	 * @return true if this node has a child with volatile bounds
+	 */
+	protected boolean getChildBoundsVolatile() {
+		return childBoundsVolatile;
+	}
 
-    /**
-     * Set if this node has a child with volatile bounds. This should normally
-     * be managed automatically by the bounds validation process.
-     * 
-     * @param childBoundsVolatile true if this node has a descendant with
-     *            volatile bounds
-     */
-    protected void setChildBoundsVolatile(final boolean childBoundsVolatile) {
-        this.childBoundsVolatile = childBoundsVolatile;
-    }
+	/**
+	 * Set if this node has a child with volatile bounds. This should normally
+	 * be managed automatically by the bounds validation process.
+	 * 
+	 * @param childBoundsVolatile
+	 *            true if this node has a descendant with volatile bounds
+	 */
+	protected void setChildBoundsVolatile(final boolean childBoundsVolatile) {
+		this.childBoundsVolatile = childBoundsVolatile;
+	}
 
-    /**
-     * Return true if this node's bounds have recently changed. This flag will
-     * be reset on the next call of validateFullBounds.
-     * 
-     * @return true if this node's bounds have changed.
-     */
-    protected boolean getBoundsChanged() {
-        return boundsChanged;
-    }
+	/**
+	 * Return true if this node's bounds have recently changed. This flag will
+	 * be reset on the next call of validateFullBounds.
+	 * 
+	 * @return true if this node's bounds have changed.
+	 */
+	protected boolean getBoundsChanged() {
+		return boundsChanged;
+	}
 
-    /**
-     * Set the bounds chnaged flag. This flag will be reset on the next call of
-     * validateFullBounds.
-     * 
-     * @param boundsChanged true if this nodes bounds have changed.
-     */
-    protected void setBoundsChanged(final boolean boundsChanged) {
-        this.boundsChanged = boundsChanged;
-    }
+	/**
+	 * Set the bounds chnaged flag. This flag will be reset on the next call of
+	 * validateFullBounds.
+	 * 
+	 * @param boundsChanged
+	 *            true if this nodes bounds have changed.
+	 */
+	protected void setBoundsChanged(final boolean boundsChanged) {
+		this.boundsChanged = boundsChanged;
+	}
 
-    /**
-     * Return true if the full bounds of this node are invalid. This means that
-     * the full bounds of this node have changed and need to be recomputed.
-     * 
-     * @return true if the full bounds of this node are invalid
-     */
-    protected boolean getFullBoundsInvalid() {
-        return fullBoundsInvalid;
-    }
+	/**
+	 * Return true if the full bounds of this node are invalid. This means that
+	 * the full bounds of this node have changed and need to be recomputed.
+	 * 
+	 * @return true if the full bounds of this node are invalid
+	 */
+	protected boolean getFullBoundsInvalid() {
+		return fullBoundsInvalid;
+	}
 
-    /**
-     * Set the full bounds invalid flag. This flag is set when the full bounds
-     * of this node need to be recomputed as is the case when this node is
-     * transformed or when one of this node's children changes geometry.
-     * 
-     * @param fullBoundsInvalid true=invalid, false=valid
-     */
-    protected void setFullBoundsInvalid(final boolean fullBoundsInvalid) {
-        this.fullBoundsInvalid = fullBoundsInvalid;
-    }
+	/**
+	 * Set the full bounds invalid flag. This flag is set when the full bounds
+	 * of this node need to be recomputed as is the case when this node is
+	 * transformed or when one of this node's children changes geometry.
+	 * 
+	 * @param fullBoundsInvalid
+	 *            true=invalid, false=valid
+	 */
+	protected void setFullBoundsInvalid(final boolean fullBoundsInvalid) {
+		this.fullBoundsInvalid = fullBoundsInvalid;
+	}
 
-    /**
-     * Return true if one of this node's descendants has invalid bounds.
-     * 
-     * @return whether child bounds are invalid
-     */
-    protected boolean getChildBoundsInvalid() {
-        return childBoundsInvalid;
-    }
+	/**
+	 * Return true if one of this node's descendants has invalid bounds.
+	 * 
+	 * @return whether child bounds are invalid
+	 */
+	protected boolean getChildBoundsInvalid() {
+		return childBoundsInvalid;
+	}
 
-    /**
-     * Set the flag indicating that one of this node's descendants has invalid
-     * bounds.
-     * 
-     * @param childBoundsInvalid true=invalid, false=valid
-     */
-    protected void setChildBoundsInvalid(final boolean childBoundsInvalid) {
-        this.childBoundsInvalid = childBoundsInvalid;
-    }
+	/**
+	 * Set the flag indicating that one of this node's descendants has invalid
+	 * bounds.
+	 * 
+	 * @param childBoundsInvalid
+	 *            true=invalid, false=valid
+	 */
+	protected void setChildBoundsInvalid(final boolean childBoundsInvalid) {
+		this.childBoundsInvalid = childBoundsInvalid;
+	}
 
-    /**
-     * This method should be called when the bounds of this node are changed. It
-     * invalidates the full bounds of this node, and also notifies each of this
-     * nodes children that their parent's bounds have changed. As a result of
-     * this method getting called this nodes layoutChildren will be called.
-     */
-    public void signalBoundsChanged() {
-        invalidateFullBounds();
-        setBoundsChanged(true);
-        firePropertyChange(PROPERTY_CODE_BOUNDS, PROPERTY_BOUNDS, null, bounds);
+	/**
+	 * This method should be called when the bounds of this node are changed. It
+	 * invalidates the full bounds of this node, and also notifies each of this
+	 * nodes children that their parent's bounds have changed. As a result of
+	 * this method getting called this nodes layoutChildren will be called.
+	 */
+	public void signalBoundsChanged() {
+		invalidateFullBounds();
+		setBoundsChanged(true);
+		firePropertyChange(PROPERTY_CODE_BOUNDS, PROPERTY_BOUNDS, null, bounds);
 
-        final int count = getChildrenCount();
-        for (int i = 0; i < count; i++) {
-            final PNode each = (PNode) children.get(i);
-            each.parentBoundsChanged();
-        }
-    }
+		final int count = getChildrenCount();
+		for (int i = 0; i < count; i++) {
+			final PNode each = (PNode) children.get(i);
+			each.parentBoundsChanged();
+		}
+	}
 
-    /**
-     * Invalidate this node's layout, so that later layoutChildren will get
-     * called.
-     */
-    public void invalidateLayout() {
-        invalidateFullBounds();
-    }
+	/**
+	 * Invalidate this node's layout, so that later layoutChildren will get
+	 * called.
+	 */
+	public void invalidateLayout() {
+		invalidateFullBounds();
+	}
 
-    /**
-     * A notification that the bounds of this node's parent have changed.
-     */
-    protected void parentBoundsChanged() {
-    }
+	/**
+	 * A notification that the bounds of this node's parent have changed.
+	 */
+	protected void parentBoundsChanged() {
+	}
 
-    /**
-     * Invalidates the full bounds of this node, and sets the child bounds
-     * invalid flag on each of this node's ancestors.
-     */
-    public void invalidateFullBounds() {
-        setFullBoundsInvalid(true);
+	/**
+	 * Invalidates the full bounds of this node, and sets the child bounds
+	 * invalid flag on each of this node's ancestors.
+	 */
+	public void invalidateFullBounds() {
+		setFullBoundsInvalid(true);
 
-        PNode n = parent;
-        while (n != null && !n.getChildBoundsInvalid()) {
-            n.setChildBoundsInvalid(true);
-            n = n.parent;
-        }
+		PNode n = parent;
+		while (n != null && !n.getChildBoundsInvalid()) {
+			n.setChildBoundsInvalid(true);
+			n = n.parent;
+		}
 
-        if (SCENE_GRAPH_DELEGATE != null) {
-            SCENE_GRAPH_DELEGATE.nodeFullBoundsInvalidated(this);
-        }
-    }
+		if (SCENE_GRAPH_DELEGATE != null) {
+			SCENE_GRAPH_DELEGATE.nodeFullBoundsInvalidated(this);
+		}
+	}
 
-    /**
-     * This method is called to validate the bounds of this node and all of its
-     * descendants. It returns true if this nodes bounds or the bounds of any of
-     * its descendants are marked as volatile.
-     * 
-     * @return true if this node or any of its descendants have volatile bounds
-     */
-    protected boolean validateFullBounds() {
-        final boolean boundsVolatile = getBoundsVolatile();
+	/**
+	 * This method is called to validate the bounds of this node and all of its
+	 * descendants. It returns true if this nodes bounds or the bounds of any of
+	 * its descendants are marked as volatile.
+	 * 
+	 * @return true if this node or any of its descendants have volatile bounds
+	 */
+	protected boolean validateFullBounds() {
+		final boolean boundsVolatile = getBoundsVolatile();
 
-        // 1. Only compute new bounds if invalid flags are set.
-        if (fullBoundsInvalid || childBoundsInvalid || boundsVolatile || childBoundsVolatile) {
+		// 1. Only compute new bounds if invalid flags are set.
+		if (fullBoundsInvalid || childBoundsInvalid || boundsVolatile
+				|| childBoundsVolatile) {
 
-            // 2. If my bounds are volatile and they have not been changed then
-            // signal a change.
-            //
-            // For most cases this will do nothing, but if a nodes bounds depend
-            // on its model, then
-            // validate bounds has the responsibility of making the bounds match
-            // the models value.
-            // For example PPaths validateBounds method makes sure that the
-            // bounds are equal to the
-            // bounds of the GeneralPath model.
-            if (boundsVolatile && !boundsChanged) {
-                signalBoundsChanged();
-            }
+			// 2. If my bounds are volatile and they have not been changed then
+			// signal a change.
+			//
+			// For most cases this will do nothing, but if a nodes bounds depend
+			// on its model, then
+			// validate bounds has the responsibility of making the bounds match
+			// the models value.
+			// For example PPaths validateBounds method makes sure that the
+			// bounds are equal to the
+			// bounds of the GeneralPath model.
+			if (boundsVolatile && !boundsChanged) {
+				signalBoundsChanged();
+			}
 
-            // 3. If the bounds of on of my decendents are invalidate then
-            // validate the bounds of all of my children.
-            if (childBoundsInvalid || childBoundsVolatile) {
-                childBoundsVolatile = false;
-                final int count = getChildrenCount();
-                for (int i = 0; i < count; i++) {
-                    final PNode each = (PNode) children.get(i);
-                    childBoundsVolatile |= each.validateFullBounds();
-                }
-            }
+			// 3. If the bounds of on of my decendents are invalidate then
+			// validate the bounds of all of my children.
+			if (childBoundsInvalid || childBoundsVolatile) {
+				childBoundsVolatile = false;
+				final int count = getChildrenCount();
+				for (int i = 0; i < count; i++) {
+					final PNode each = (PNode) children.get(i);
+					childBoundsVolatile |= each.validateFullBounds();
+				}
+			}
 
-            // 4. Now that my children's bounds are valid and my own bounds are
-            // valid run any layout algorithm here. Note that if you try to
-            // layout volatile
-            // children piccolo will most likely start a "soft" infinite loop.
-            // It won't freeze
-            // your program, but it will make an infinite number of calls to
-            // SwingUtilities
-            // invoke later. You don't want to do that.
-            layoutChildren();
+			// 4. Now that my children's bounds are valid and my own bounds are
+			// valid run any layout algorithm here. Note that if you try to
+			// layout volatile
+			// children piccolo will most likely start a "soft" infinite loop.
+			// It won't freeze
+			// your program, but it will make an infinite number of calls to
+			// SwingUtilities
+			// invoke later. You don't want to do that.
+			layoutChildren();
 
-            // 5. If the full bounds cache is invalid then recompute the full
-            // bounds cache here after our own bounds and the children's bounds
-            // have been computed above.
-            if (fullBoundsInvalid) {
-                final double oldX = fullBoundsCache.x;
-                final double oldY = fullBoundsCache.y;
-                final double oldWidth = fullBoundsCache.width;
-                final double oldHeight = fullBoundsCache.height;
-                final boolean oldEmpty = fullBoundsCache.isEmpty();
+			// 5. If the full bounds cache is invalid then recompute the full
+			// bounds cache here after our own bounds and the children's bounds
+			// have been computed above.
+			if (fullBoundsInvalid) {
+				final double oldX = fullBoundsCache.x;
+				final double oldY = fullBoundsCache.y;
+				final double oldWidth = fullBoundsCache.width;
+				final double oldHeight = fullBoundsCache.height;
+				final boolean oldEmpty = fullBoundsCache.isEmpty();
 
-                // 6. This will call getFullBoundsReference on all of the
-                // children. So if the above
-                // layoutChildren method changed the bounds of any of the
-                // children they will be
-                // validated again here.
-                fullBoundsCache = computeFullBounds(fullBoundsCache);
+				// 6. This will call getFullBoundsReference on all of the
+				// children. So if the above
+				// layoutChildren method changed the bounds of any of the
+				// children they will be
+				// validated again here.
+				fullBoundsCache = computeFullBounds(fullBoundsCache);
 
-                final boolean fullBoundsChanged = fullBoundsCache.x != oldX || fullBoundsCache.y != oldY
-                        || fullBoundsCache.width != oldWidth || fullBoundsCache.height != oldHeight
-                        || fullBoundsCache.isEmpty() != oldEmpty;
+				final boolean fullBoundsChanged = fullBoundsCache.x != oldX
+						|| fullBoundsCache.y != oldY
+						|| fullBoundsCache.width != oldWidth
+						|| fullBoundsCache.height != oldHeight
+						|| fullBoundsCache.isEmpty() != oldEmpty;
 
-                // 7. If the new full bounds cache differs from the previous
-                // cache then
-                // tell our parent to invalidate their full bounds. This is how
-                // bounds changes
-                // deep in the tree percolate up.
-                if (fullBoundsChanged) {
-                    if (parent != null) {
-                        parent.invalidateFullBounds();
-                    }
-                    firePropertyChange(PROPERTY_CODE_FULL_BOUNDS, PROPERTY_FULL_BOUNDS, null, fullBoundsCache);
+				// 7. If the new full bounds cache differs from the previous
+				// cache then
+				// tell our parent to invalidate their full bounds. This is how
+				// bounds changes
+				// deep in the tree percolate up.
+				if (fullBoundsChanged) {
+					if (parent != null) {
+						parent.invalidateFullBounds();
+					}
+					firePropertyChange(PROPERTY_CODE_FULL_BOUNDS,
+							PROPERTY_FULL_BOUNDS, null, fullBoundsCache);
 
-                    // 8. If our paint was invalid make sure to repaint our old
-                    // full bounds. The
-                    // new bounds will be computed later in the validatePaint
-                    // pass.
-                    if (paintInvalid && !oldEmpty) {
-                        TEMP_REPAINT_BOUNDS.setRect(oldX, oldY, oldWidth, oldHeight);
-                        repaintFrom(TEMP_REPAINT_BOUNDS, this);
-                    }
-                }
-            }
+					// 8. If our paint was invalid make sure to repaint our old
+					// full bounds. The
+					// new bounds will be computed later in the validatePaint
+					// pass.
+					if (paintInvalid && !oldEmpty) {
+						TEMP_REPAINT_BOUNDS.setRect(oldX, oldY, oldWidth,
+								oldHeight);
+						repaintFrom(TEMP_REPAINT_BOUNDS, this);
+					}
+				}
+			}
 
-            // 9. Clear the invalid bounds flags.
-            boundsChanged = false;
-            fullBoundsInvalid = false;
-            childBoundsInvalid = false;
-        }
+			// 9. Clear the invalid bounds flags.
+			boundsChanged = false;
+			fullBoundsInvalid = false;
+			childBoundsInvalid = false;
+		}
 
-        return boundsVolatile || childBoundsVolatile;
-    }
+		return boundsVolatile || childBoundsVolatile;
+	}
 
-    /**
-     * Nodes that apply layout constraints to their children should override
-     * this method and do the layout there.
-     */
-    protected void layoutChildren() {
-    }
+	/**
+	 * Nodes that apply layout constraints to their children should override
+	 * this method and do the layout there.
+	 */
+	protected void layoutChildren() {
+	}
 
-    // ****************************************************************
-    // Node Transform - Methods to manipulate the node's transform.
-    // 
-    // Each node has a transform that is used to define the nodes
-    // local coordinate system. IE it is applied before picking and
-    // rendering the node.
-    // 
-    // The usual way to move nodes about on the canvas is to manipulate
-    // this transform, as opposed to changing the bounds of the
-    // node.
-    // 
-    // Since this transform defines the local coordinate system of this
-    // node the following methods with affect the global position both
-    // this node and all of its descendants.
-    // ****************************************************************
+	// ****************************************************************
+	// Node Transform - Methods to manipulate the node's transform.
+	// 
+	// Each node has a transform that is used to define the nodes
+	// local coordinate system. IE it is applied before picking and
+	// rendering the node.
+	// 
+	// The usual way to move nodes about on the canvas is to manipulate
+	// this transform, as opposed to changing the bounds of the
+	// node.
+	// 
+	// Since this transform defines the local coordinate system of this
+	// node the following methods with affect the global position both
+	// this node and all of its descendants.
+	// ****************************************************************
 
-    /**
-     * Returns the rotation applied by this node's transform in radians. This
-     * rotation affects this node and all its descendants. The value returned
-     * will be between 0 and 2pi radians.
-     * 
-     * @return rotation in radians.
-     */
-    public double getRotation() {
-        if (transform == null) {
-            return 0;
-        }
-        return transform.getRotation();
-    }
+	/**
+	 * Returns the rotation applied by this node's transform in radians. This
+	 * rotation affects this node and all its descendants. The value returned
+	 * will be between 0 and 2pi radians.
+	 * 
+	 * @return rotation in radians.
+	 */
+	public double getRotation() {
+		if (transform == null) {
+			return 0;
+		}
+		return transform.getRotation();
+	}
 
-    /**
-     * Sets the rotation of this nodes transform in radians. This will affect
-     * this node and all its descendents.
-     * 
-     * @param theta rotation in radians
-     */
-    public void setRotation(final double theta) {
-        rotate(theta - getRotation());
-    }
+	/**
+	 * Sets the rotation of this nodes transform in radians. This will affect
+	 * this node and all its descendents.
+	 * 
+	 * @param theta
+	 *            rotation in radians
+	 */
+	public void setRotation(final double theta) {
+		rotate(theta - getRotation());
+	}
 
-    /**
-     * Rotates this node by theta (in radians) about the 0,0 point. This will
-     * affect this node and all its descendants.
-     * 
-     * @param theta the amount to rotate by in radians
-     */
-    public void rotate(final double theta) {
-        rotateAboutPoint(theta, 0, 0);
-    }
+	/**
+	 * Rotates this node by theta (in radians) about the 0,0 point. This will
+	 * affect this node and all its descendants.
+	 * 
+	 * @param theta
+	 *            the amount to rotate by in radians
+	 */
+	public void rotate(final double theta) {
+		rotateAboutPoint(theta, 0, 0);
+	}
 
-    /**
-     * Rotates this node by theta (in radians), and then translates the node so
-     * that the x, y position of its fullBounds stays constant.
-     * 
-     * @param theta the amount to rotate by in radians
-     */
-    public void rotateInPlace(final double theta) {
-        PBounds b = getFullBoundsReference();
-        final double px = b.x;
-        final double py = b.y;
-        rotateAboutPoint(theta, 0, 0);
-        b = getFullBoundsReference();
-        offset(px - b.x, py - b.y);
-    }
+	/**
+	 * Rotates this node by theta (in radians), and then translates the node so
+	 * that the x, y position of its fullBounds stays constant.
+	 * 
+	 * @param theta
+	 *            the amount to rotate by in radians
+	 */
+	public void rotateInPlace(final double theta) {
+		PBounds b = getFullBoundsReference();
+		final double px = b.x;
+		final double py = b.y;
+		rotateAboutPoint(theta, 0, 0);
+		b = getFullBoundsReference();
+		offset(px - b.x, py - b.y);
+	}
 
-    /**
-     * Rotates this node by theta (in radians) about the given point. This will
-     * affect this node and all its descendants.
-     * 
-     * @param theta the amount to rotate by in radians
-     * @param point the point about which to rotate
-     */
-    public void rotateAboutPoint(final double theta, final Point2D point) {
-        rotateAboutPoint(theta, point.getX(), point.getY());
-    }
+	/**
+	 * Rotates this node by theta (in radians) about the given point. This will
+	 * affect this node and all its descendants.
+	 * 
+	 * @param theta
+	 *            the amount to rotate by in radians
+	 * @param point
+	 *            the point about which to rotate
+	 */
+	public void rotateAboutPoint(final double theta, final Point2D point) {
+		rotateAboutPoint(theta, point.getX(), point.getY());
+	}
 
-    /**
-     * Rotates this node by theta (in radians) about the given point. This will
-     * affect this node and all its descendants.
-     * 
-     * @param theta the amount to rotate by in radians
-     * @param x the x coordinate of the point around which to rotate
-     * @param y the y coordinate of the point around which to rotate
-     */
-    public void rotateAboutPoint(final double theta, final double x, final double y) {
-        getTransformReference(true).rotate(theta, x, y);
-        invalidatePaint();
-        invalidateFullBounds();
-        firePropertyChange(PROPERTY_CODE_TRANSFORM, PROPERTY_TRANSFORM, null, transform);
-    }
+	/**
+	 * Rotates this node by theta (in radians) about the given point. This will
+	 * affect this node and all its descendants.
+	 * 
+	 * @param theta
+	 *            the amount to rotate by in radians
+	 * @param x
+	 *            the x coordinate of the point around which to rotate
+	 * @param y
+	 *            the y coordinate of the point around which to rotate
+	 */
+	public void rotateAboutPoint(final double theta, final double x,
+			final double y) {
+		getTransformReference(true).rotate(theta, x, y);
+		invalidatePaint();
+		invalidateFullBounds();
+		firePropertyChange(PROPERTY_CODE_TRANSFORM, PROPERTY_TRANSFORM, null,
+				transform);
+	}
 
-    /**
-     * Return the total amount of rotation applied to this node by its own
-     * transform together with the transforms of all its ancestors. The value
-     * returned will be between 0 and 2pi radians.
-     * 
-     * @return the total amount of rotation applied to this node in radians
-     */
-    public double getGlobalRotation() {
-        return getLocalToGlobalTransform(null).getRotation();
-    }
+	/**
+	 * Return the total amount of rotation applied to this node by its own
+	 * transform together with the transforms of all its ancestors. The value
+	 * returned will be between 0 and 2pi radians.
+	 * 
+	 * @return the total amount of rotation applied to this node in radians
+	 */
+	public double getGlobalRotation() {
+		return getLocalToGlobalTransform(null).getRotation();
+	}
 
-    /**
-     * Set the global rotation (in radians) of this node. This is implemented by
-     * rotating this nodes transform the required amount so that the nodes
-     * global rotation is as requested.
-     * 
-     * @param theta the amount to rotate by in radians relative to the global
-     *            coordinate system.
-     */
-    public void setGlobalRotation(final double theta) {
-        if (parent != null) {
-            setRotation(theta - parent.getGlobalRotation());
-        }
-        else {
-            setRotation(theta);
-        }
-    }
+	/**
+	 * Set the global rotation (in radians) of this node. This is implemented by
+	 * rotating this nodes transform the required amount so that the nodes
+	 * global rotation is as requested.
+	 * 
+	 * @param theta
+	 *            the amount to rotate by in radians relative to the global
+	 *            coordinate system.
+	 */
+	public void setGlobalRotation(final double theta) {
+		if (parent != null) {
+			setRotation(theta - parent.getGlobalRotation());
+		} else {
+			setRotation(theta);
+		}
+	}
 
-    /**
-     * Return the scale applied by this node's transform. The scale is effecting
-     * this node and all its descendants.
-     * 
-     * @return scale applied by this nodes transform.
-     */
-    public double getScale() {
-        if (transform == null) {
-            return 1;
-        }
-        return transform.getScale();
-    }
+	/**
+	 * Return the scale applied by this node's transform. The scale is effecting
+	 * this node and all its descendants.
+	 * 
+	 * @return scale applied by this nodes transform.
+	 */
+	public double getScale() {
+		if (transform == null) {
+			return 1;
+		}
+		return transform.getScale();
+	}
 
-    /**
-     * Set the scale of this node's transform. The scale will affect this node
-     * and all its descendants.
-     * 
-     * @param scale the scale to set the transform to
-     */
-    public void setScale(final double scale) {
-        if (scale == 0) {
-            throw new RuntimeException("Can't set scale to 0");
-        }
-        scale(scale / getScale());
-    }
+	/**
+	 * Set the scale of this node's transform. The scale will affect this node
+	 * and all its descendants.
+	 * 
+	 * @param scale
+	 *            the scale to set the transform to
+	 */
+	public void setScale(final double scale) {
+		if (scale == 0) {
+			throw new RuntimeException("Can't set scale to 0");
+		}
+		scale(scale / getScale());
+	}
 
-    /**
-     * Scale this nodes transform by the given amount. This will affect this
-     * node and all of its descendants.
-     * 
-     * @param scale the amount to scale by
-     */
-    public void scale(final double scale) {
-        scaleAboutPoint(scale, 0, 0);
-    }
+	/**
+	 * Scale this nodes transform by the given amount. This will affect this
+	 * node and all of its descendants.
+	 * 
+	 * @param scale
+	 *            the amount to scale by
+	 */
+	public void scale(final double scale) {
+		scaleAboutPoint(scale, 0, 0);
+	}
 
-    /**
-     * Scale this nodes transform by the given amount about the specified point.
-     * This will affect this node and all of its descendants.
-     * 
-     * @param scale the amount to scale by
-     * @param point the point to scale about
-     */
-    public void scaleAboutPoint(final double scale, final Point2D point) {
-        scaleAboutPoint(scale, point.getX(), point.getY());
-    }
+	/**
+	 * Scale this nodes transform by the given amount about the specified point.
+	 * This will affect this node and all of its descendants.
+	 * 
+	 * @param scale
+	 *            the amount to scale by
+	 * @param point
+	 *            the point to scale about
+	 */
+	public void scaleAboutPoint(final double scale, final Point2D point) {
+		scaleAboutPoint(scale, point.getX(), point.getY());
+	}
 
-    /**
-     * Scale this nodes transform by the given amount about the specified point.
-     * This will affect this node and all of its descendants.
-     * 
-     * @param scale the amount to scale by
-     * @param x the x coordinate of the point around which to scale
-     * @param y the y coordinate of the point around which to scale
-     */
-    public void scaleAboutPoint(final double scale, final double x, final double y) {
-        getTransformReference(true).scaleAboutPoint(scale, x, y);
-        invalidatePaint();
-        invalidateFullBounds();
-        firePropertyChange(PROPERTY_CODE_TRANSFORM, PROPERTY_TRANSFORM, null, transform);
-    }
+	/**
+	 * Scale this nodes transform by the given amount about the specified point.
+	 * This will affect this node and all of its descendants.
+	 * 
+	 * @param scale
+	 *            the amount to scale by
+	 * @param x
+	 *            the x coordinate of the point around which to scale
+	 * @param y
+	 *            the y coordinate of the point around which to scale
+	 */
+	public void scaleAboutPoint(final double scale, final double x,
+			final double y) {
+		getTransformReference(true).scaleAboutPoint(scale, x, y);
+		invalidatePaint();
+		invalidateFullBounds();
+		firePropertyChange(PROPERTY_CODE_TRANSFORM, PROPERTY_TRANSFORM, null,
+				transform);
+	}
 
-    /**
-     * Return the global scale that is being applied to this node by its
-     * transform together with the transforms of all its ancestors.
-     * 
-     * @return global scale of this node
-     */
-    public double getGlobalScale() {
-        return getLocalToGlobalTransform(null).getScale();
-    }
+	/**
+	 * Return the global scale that is being applied to this node by its
+	 * transform together with the transforms of all its ancestors.
+	 * 
+	 * @return global scale of this node
+	 */
+	public double getGlobalScale() {
+		return getLocalToGlobalTransform(null).getScale();
+	}
 
-    /**
-     * Set the global scale of this node. This is implemented by scaling this
-     * nodes transform the required amount so that the nodes global scale is as
-     * requested.
-     * 
-     * @param scale the desired global scale
-     */
-    public void setGlobalScale(final double scale) {
-        if (parent != null) {
-            setScale(scale / parent.getGlobalScale());
-        }
-        else {
-            setScale(scale);
-        }
-    }
+	/**
+	 * Set the global scale of this node. This is implemented by scaling this
+	 * nodes transform the required amount so that the nodes global scale is as
+	 * requested.
+	 * 
+	 * @param scale
+	 *            the desired global scale
+	 */
+	public void setGlobalScale(final double scale) {
+		if (parent != null) {
+			setScale(scale / parent.getGlobalScale());
+		} else {
+			setScale(scale);
+		}
+	}
 
-    /**
-     * Returns the x offset of this node as applied by its transform.
-     * 
-     * @return x offset of this node as applied by its transform
-     */
-    public double getXOffset() {
-        if (transform == null) {
-            return 0;
-        }
-        return transform.getTranslateX();
-    }
+	/**
+	 * Returns the x offset of this node as applied by its transform.
+	 * 
+	 * @return x offset of this node as applied by its transform
+	 */
+	public double getXOffset() {
+		if (transform == null) {
+			return 0;
+		}
+		return transform.getTranslateX();
+	}
 
-    /**
-     * Returns the y offset of this node as applied by its transform.
-     * 
-     * @return y offset of this node as applied by its transform
-     */
-    public double getYOffset() {
-        if (transform == null) {
-            return 0;
-        }
-        return transform.getTranslateY();
-    }
+	/**
+	 * Returns the y offset of this node as applied by its transform.
+	 * 
+	 * @return y offset of this node as applied by its transform
+	 */
+	public double getYOffset() {
+		if (transform == null) {
+			return 0;
+		}
+		return transform.getTranslateY();
+	}
 
-    /**
-     * Return the offset that is being applied to this node by its transform.
-     * This offset effects this node and all of its descendants and is specified
-     * in the parent coordinate system. This returns the values that are in the
-     * m02 and m12 positions in the affine transform.
-     * 
-     * @return a point representing the x and y offset
-     */
-    public Point2D getOffset() {
-        if (transform == null) {
-            return new Point2D.Double();
-        }
-        return new Point2D.Double(transform.getTranslateX(), transform.getTranslateY());
-    }
+	/**
+	 * Return the offset that is being applied to this node by its transform.
+	 * This offset effects this node and all of its descendants and is specified
+	 * in the parent coordinate system. This returns the values that are in the
+	 * m02 and m12 positions in the affine transform.
+	 * 
+	 * @return a point representing the x and y offset
+	 */
+	public Point2D getOffset() {
+		if (transform == null) {
+			return new Point2D.Double();
+		}
+		return new Point2D.Double(transform.getTranslateX(), transform
+				.getTranslateY());
+	}
 
-    /**
-     * Set the offset that is being applied to this node by its transform. This
-     * offset effects this node and all of its descendants and is specified in
-     * the nodes parent coordinate system. This directly sets the values of the
-     * m02 and m12 positions in the affine transform. Unlike "PNode.translate()"
-     * it is not effected by the transforms scale.
-     * 
-     * @param point value of new offset
-     */
-    public void setOffset(final Point2D point) {
-        setOffset(point.getX(), point.getY());
-    }
+	/**
+	 * Set the offset that is being applied to this node by its transform. This
+	 * offset effects this node and all of its descendants and is specified in
+	 * the nodes parent coordinate system. This directly sets the values of the
+	 * m02 and m12 positions in the affine transform. Unlike "PNode.translate()"
+	 * it is not effected by the transforms scale.
+	 * 
+	 * @param point
+	 *            value of new offset
+	 */
+	public void setOffset(final Point2D point) {
+		setOffset(point.getX(), point.getY());
+	}
 
-    /**
-     * Set the offset that is being applied to this node by its transform. This
-     * offset effects this node and all of its descendants and is specified in
-     * the nodes parent coordinate system. This directly sets the values of the
-     * m02 and m12 positions in the affine transform. Unlike "PNode.translate()"
-     * it is not effected by the transforms scale.
-     * 
-     * @param x amount of x offset
-     * @param y amount of y offset
-     */
-    public void setOffset(final double x, final double y) {
-        getTransformReference(true).setOffset(x, y);
-        invalidatePaint();
-        invalidateFullBounds();
-        firePropertyChange(PROPERTY_CODE_TRANSFORM, PROPERTY_TRANSFORM, null, transform);
-    }
+	/**
+	 * Set the offset that is being applied to this node by its transform. This
+	 * offset effects this node and all of its descendants and is specified in
+	 * the nodes parent coordinate system. This directly sets the values of the
+	 * m02 and m12 positions in the affine transform. Unlike "PNode.translate()"
+	 * it is not effected by the transforms scale.
+	 * 
+	 * @param x
+	 *            amount of x offset
+	 * @param y
+	 *            amount of y offset
+	 */
+	public void setOffset(final double x, final double y) {
+		getTransformReference(true).setOffset(x, y);
+		invalidatePaint();
+		invalidateFullBounds();
+		firePropertyChange(PROPERTY_CODE_TRANSFORM, PROPERTY_TRANSFORM, null,
+				transform);
+	}
 
-    /**
-     * Offset this node relative to the parents coordinate system, and is NOT
-     * effected by this nodes current scale or rotation. This is implemented by
-     * directly adding dx to the m02 position and dy to the m12 position in the
-     * affine transform.
-     * 
-     * @param dx amount to add to this nodes current x Offset
-     * @param dy amount to add to this nodes current y Offset
-     */
-    public void offset(final double dx, final double dy) {
-        getTransformReference(true);
-        setOffset(transform.getTranslateX() + dx, transform.getTranslateY() + dy);
-    }
+	/**
+	 * Offset this node relative to the parents coordinate system, and is NOT
+	 * effected by this nodes current scale or rotation. This is implemented by
+	 * directly adding dx to the m02 position and dy to the m12 position in the
+	 * affine transform.
+	 * 
+	 * @param dx
+	 *            amount to add to this nodes current x Offset
+	 * @param dy
+	 *            amount to add to this nodes current y Offset
+	 */
+	public void offset(final double dx, final double dy) {
+		getTransformReference(true);
+		setOffset(transform.getTranslateX() + dx, transform.getTranslateY()
+				+ dy);
+	}
 
-    /**
-     * Translate this node's transform by the given amount, using the standard
-     * affine transform translate method. This translation effects this node and
-     * all of its descendants.
-     * 
-     * @param dx amount to add to this nodes current x translation
-     * @param dy amount to add to this nodes current y translation
-     */
-    public void translate(final double dx, final double dy) {
-        getTransformReference(true).translate(dx, dy);
-        invalidatePaint();
-        invalidateFullBounds();
-        firePropertyChange(PROPERTY_CODE_TRANSFORM, PROPERTY_TRANSFORM, null, transform);
-    }
+	/**
+	 * Translate this node's transform by the given amount, using the standard
+	 * affine transform translate method. This translation effects this node and
+	 * all of its descendants.
+	 * 
+	 * @param dx
+	 *            amount to add to this nodes current x translation
+	 * @param dy
+	 *            amount to add to this nodes current y translation
+	 */
+	public void translate(final double dx, final double dy) {
+		getTransformReference(true).translate(dx, dy);
+		invalidatePaint();
+		invalidateFullBounds();
+		firePropertyChange(PROPERTY_CODE_TRANSFORM, PROPERTY_TRANSFORM, null,
+				transform);
+	}
 
-    /**
-     * Return the global translation that is being applied to this node by its
-     * transform together with the transforms of all its ancestors.
-     * 
-     * @return the global translation applied to this node
-     */
-    public Point2D getGlobalTranslation() {
-        final Point2D p = getOffset();
-        if (parent != null) {
-            parent.localToGlobal(p);
-        }
-        return p;
-    }
+	/**
+	 * Return the global translation that is being applied to this node by its
+	 * transform together with the transforms of all its ancestors.
+	 * 
+	 * @return the global translation applied to this node
+	 */
+	public Point2D getGlobalTranslation() {
+		final Point2D p = getOffset();
+		if (parent != null) {
+			parent.localToGlobal(p);
+		}
+		return p;
+	}
 
-    /**
-     * Set the global translation of this node. This is implemented by
-     * translating this nodes transform the required amount so that the nodes
-     * global scale is as requested.
-     * 
-     * @param globalPoint the desired global translation
-     */
-    public void setGlobalTranslation(final Point2D globalPoint) {
-        if (parent != null) {
-            parent.getGlobalToLocalTransform(null).transform(globalPoint, globalPoint);
-        }
-        setOffset(globalPoint);
-    }
+	/**
+	 * Set the global translation of this node. This is implemented by
+	 * translating this nodes transform the required amount so that the nodes
+	 * global scale is as requested.
+	 * 
+	 * @param globalPoint
+	 *            the desired global translation
+	 */
+	public void setGlobalTranslation(final Point2D globalPoint) {
+		if (parent != null) {
+			parent.getGlobalToLocalTransform(null).transform(globalPoint,
+					globalPoint);
+		}
+		setOffset(globalPoint);
+	}
 
-    /**
-     * Transform this nodes transform by the given transform.
-     * 
-     * @param aTransform the transform to apply.
-     */
-    public void transformBy(final AffineTransform aTransform) {
-        getTransformReference(true).concatenate(aTransform);
-        invalidatePaint();
-        invalidateFullBounds();
-        firePropertyChange(PROPERTY_CODE_TRANSFORM, PROPERTY_TRANSFORM, null, transform);
-    }
+	/**
+	 * Transform this nodes transform by the given transform.
+	 * 
+	 * @param aTransform
+	 *            the transform to apply.
+	 */
+	public void transformBy(final AffineTransform aTransform) {
+		getTransformReference(true).concatenate(aTransform);
+		invalidatePaint();
+		invalidateFullBounds();
+		firePropertyChange(PROPERTY_CODE_TRANSFORM, PROPERTY_TRANSFORM, null,
+				transform);
+	}
 
-    /**
-     * Linearly interpolates between a and b, based on t. Specifically, it
-     * computes lerp(a, b, t) = a + t*(b - a). This produces a result that
-     * changes from a (when t = 0) to b (when t = 1).
-     * 
-     * @param t variable 'time' parameter
-     * @param a from point
-     * @param b to Point
-     * 
-     * @return linear interpolation between and b at time interval t (given as #
-     *         between 0f and 1f)
-     */
-    public static double lerp(final double t, final double a, final double b) {
-        return a + t * (b - a);
-    }
+	/**
+	 * Linearly interpolates between a and b, based on t. Specifically, it
+	 * computes lerp(a, b, t) = a + t*(b - a). This produces a result that
+	 * changes from a (when t = 0) to b (when t = 1).
+	 * 
+	 * @param t
+	 *            variable 'time' parameter
+	 * @param a
+	 *            from point
+	 * @param b
+	 *            to Point
+	 * 
+	 * @return linear interpolation between and b at time interval t (given as #
+	 *         between 0f and 1f)
+	 */
+	public static double lerp(final double t, final double a, final double b) {
+		return a + t * (b - a);
+	}
 
-    /**
-     * This will calculate the necessary transform in order to make this node
-     * appear at a particular position relative to the specified bounding box.
-     * The source point specifies a point in the unit square (0, 0) - (1, 1)
-     * that represents an anchor point on the corresponding node to this
-     * transform. The destination point specifies an anchor point on the
-     * reference node. The position method then computes the transform that
-     * results in transforming this node so that the source anchor point
-     * coincides with the reference anchor point. This can be useful for layout
-     * algorithms as it is straightforward to position one object relative to
-     * another.
-     * 
-     * Point2D srcPt = new Point2D.Double(1.0, 0.0);
-     * Point2D destPt = new Point2D.Double(0.0, 0.0);
-     * A.position(srcPt, destPt, B.getGlobalBounds(), 750, null);
-     * 
-     * 
-     * The result is that A will move so that its upper-right corner is at the
-     * same place as the upper-left corner of B, and the transition will be
-     * smoothly animated over a period of 750 milliseconds.
-     * 
-     * @since 1.3
-     * @param srcPt The anchor point on this transform's node (normalized to a
-     *            unit square)
-     * @param destPt The anchor point on destination bounds (normalized to a
-     *            unit square)
-     * @param destBounds The bounds (in global coordinates) used to calculate
-     *            this transform's node
-     * @param millis Number of milliseconds over which to perform the animation
-     * 
-     * @return newly scheduled activity or node if activity could not be
-     *         scheduled
-     */
-    public PActivity animateToRelativePosition(final Point2D srcPt, final Point2D destPt, final Rectangle2D destBounds,
-            final int millis) {
-        double srcx, srcy;
-        double destx, desty;
-        double dx, dy;
-        Point2D pt1, pt2;
+	/**
+	 * This will calculate the necessary transform in order to make this node
+	 * appear at a particular position relative to the specified bounding box.
+	 * The source point specifies a point in the unit square (0, 0) - (1, 1)
+	 * that represents an anchor point on the corresponding node to this
+	 * transform. The destination point specifies an anchor point on the
+	 * reference node. The position method then computes the transform that
+	 * results in transforming this node so that the source anchor point
+	 * coincides with the reference anchor point. This can be useful for layout
+	 * algorithms as it is straightforward to position one object relative to
+	 * another.
+	 * 
+	 * Point2D srcPt = new Point2D.Double(1.0, 0.0);
+	 * Point2D destPt = new Point2D.Double(0.0, 0.0);
+	 * A.position(srcPt, destPt, B.getGlobalBounds(), 750, null);
+	 * 
+	 * 
+	 * The result is that A will move so that its upper-right corner is at the
+	 * same place as the upper-left corner of B, and the transition will be
+	 * smoothly animated over a period of 750 milliseconds.
+	 * 
+	 * @since 1.3
+	 * @param srcPt
+	 *            The anchor point on this transform's node (normalized to a
+	 *            unit square)
+	 * @param destPt
+	 *            The anchor point on destination bounds (normalized to a unit
+	 *            square)
+	 * @param destBounds
+	 *            The bounds (in global coordinates) used to calculate this
+	 *            transform's node
+	 * @param millis
+	 *            Number of milliseconds over which to perform the animation
+	 * 
+	 * @return newly scheduled activity or node if activity could not be
+	 *         scheduled
+	 */
+	public PActivity animateToRelativePosition(final Point2D srcPt,
+			final Point2D destPt, final Rectangle2D destBounds, final int millis) {
+		double srcx, srcy;
+		double destx, desty;
+		double dx, dy;
+		Point2D pt1, pt2;
 
-        if (parent == null) {
-            return null;
-        }
-        else {
-            // First compute translation amount in global coordinates
-            final Rectangle2D srcBounds = getGlobalFullBounds();
-            srcx = lerp(srcPt.getX(), srcBounds.getX(), srcBounds.getX() + srcBounds.getWidth());
-            srcy = lerp(srcPt.getY(), srcBounds.getY(), srcBounds.getY() + srcBounds.getHeight());
-            destx = lerp(destPt.getX(), destBounds.getX(), destBounds.getX() + destBounds.getWidth());
-            desty = lerp(destPt.getY(), destBounds.getY(), destBounds.getY() + destBounds.getHeight());
+		if (parent == null) {
+			return null;
+		} else {
+			// First compute translation amount in global coordinates
+			final Rectangle2D srcBounds = getGlobalFullBounds();
+			srcx = lerp(srcPt.getX(), srcBounds.getX(), srcBounds.getX()
+					+ srcBounds.getWidth());
+			srcy = lerp(srcPt.getY(), srcBounds.getY(), srcBounds.getY()
+					+ srcBounds.getHeight());
+			destx = lerp(destPt.getX(), destBounds.getX(), destBounds.getX()
+					+ destBounds.getWidth());
+			desty = lerp(destPt.getY(), destBounds.getY(), destBounds.getY()
+					+ destBounds.getHeight());
 
-            // Convert vector to local coordinates
-            pt1 = new Point2D.Double(srcx, srcy);
-            globalToLocal(pt1);
-            pt2 = new Point2D.Double(destx, desty);
-            globalToLocal(pt2);
-            dx = pt2.getX() - pt1.getX();
-            dy = pt2.getY() - pt1.getY();
+			// Convert vector to local coordinates
+			pt1 = new Point2D.Double(srcx, srcy);
+			globalToLocal(pt1);
+			pt2 = new Point2D.Double(destx, desty);
+			globalToLocal(pt2);
+			dx = pt2.getX() - pt1.getX();
+			dy = pt2.getY() - pt1.getY();
 
-            // Finally, animate change
-            final PAffineTransform at = new PAffineTransform(getTransformReference(true));
-            at.translate(dx, dy);
-            return animateToTransform(at, millis);
-        }
-    }
+			// Finally, animate change
+			final PAffineTransform at = new PAffineTransform(
+					getTransformReference(true));
+			at.translate(dx, dy);
+			return animateToTransform(at, millis);
+		}
+	}
 
-    /**
-     * @deprecated in favor of animateToRelativePosition
-     * 
-     *             It will calculate the necessary transform in order to make
-     *             this node appear at a particular position relative to the
-     *             specified bounding box. The source point specifies a point in
-     *             the unit square (0, 0) - (1, 1) that represents an anchor
-     *             point on the corresponding node to this transform. The
-     *             destination point specifies an anchor point on the reference
-     *             node. The position method then computes the transform that
-     *             results in transforming this node so that the source anchor
-     *             point coincides with the reference anchor point. This can be
-     *             useful for layout algorithms as it is straightforward to
-     *             position one object relative to another.
-     *             
-     * Point2D srcPt = new Point2D.Double(1.0, 0.0);
-     * Point2D destPt = new Point2D.Double(0.0, 0.0);
-     * A.position(srcPt, destPt, B.getGlobalBounds(), 750, null);
-     * 
-     * 
-     *             The result is that A will move so that its upper-right corner
-     *             is at the same place as the upper-left corner of B, and the
-     *             transition will be smoothly animated over a period of 750
-     *             milliseconds.
-     * 
-     * @param srcPt The anchor point on this transform's node (normalized to a
-     *            unit square)
-     * @param destPt The anchor point on destination bounds (normalized to a
-     *            unit square)
-     * @param destBounds The bounds (in global coordinates) used to calculate
-     *            this transform's node
-     * @param millis Number of milliseconds over which to perform the animation
-     */
-    public void position(final Point2D srcPt, final Point2D destPt, final Rectangle2D destBounds, final int millis) {
-        animateToRelativePosition(srcPt, destPt, destBounds, millis);
-    };
+	/**
+	 * @deprecated in favor of animateToRelativePosition
+	 * 
+	 *             It will calculate the necessary transform in order to make
+	 *             this node appear at a particular position relative to the
+	 *             specified bounding box. The source point specifies a point in
+	 *             the unit square (0, 0) - (1, 1) that represents an anchor
+	 *             point on the corresponding node to this transform. The
+	 *             destination point specifies an anchor point on the reference
+	 *             node. The position method then computes the transform that
+	 *             results in transforming this node so that the source anchor
+	 *             point coincides with the reference anchor point. This can be
+	 *             useful for layout algorithms as it is straightforward to
+	 *             position one object relative to another.
+	 *             
+	 * Point2D srcPt = new Point2D.Double(1.0, 0.0);
+	 * Point2D destPt = new Point2D.Double(0.0, 0.0);
+	 * A.position(srcPt, destPt, B.getGlobalBounds(), 750, null);
+	 * 
+	 * 
+	 *             The result is that A will move so that its upper-right corner
+	 *             is at the same place as the upper-left corner of B, and the
+	 *             transition will be smoothly animated over a period of 750
+	 *             milliseconds.
+	 * 
+	 * @param srcPt
+	 *            The anchor point on this transform's node (normalized to a
+	 *            unit square)
+	 * @param destPt
+	 *            The anchor point on destination bounds (normalized to a unit
+	 *            square)
+	 * @param destBounds
+	 *            The bounds (in global coordinates) used to calculate this
+	 *            transform's node
+	 * @param millis
+	 *            Number of milliseconds over which to perform the animation
+	 */
+	public void position(final Point2D srcPt, final Point2D destPt,
+			final Rectangle2D destBounds, final int millis) {
+		animateToRelativePosition(srcPt, destPt, destBounds, millis);
+	};
 
-    /**
-     * Return a copy of the transform associated with this node.
-     * 
-     * @return copy of this node's transform
-     */
-    public PAffineTransform getTransform() {
-        if (transform == null) {
-            return new PAffineTransform();
-        }
-        else {
-            return (PAffineTransform) transform.clone();
-        }
-    }
+	/**
+	 * Return a copy of the transform associated with this node.
+	 * 
+	 * @return copy of this node's transform
+	 */
+	public PAffineTransform getTransform() {
+		if (transform == null) {
+			return new PAffineTransform();
+		} else {
+			return (PAffineTransform) transform.clone();
+		}
+	}
 
-    /**
-     * Return a reference to the transform associated with this node. This
-     * returned transform should not be modified. PNode transforms are created
-     * lazily when needed. If you access the transform reference before the
-     * transform has been created it may return null. The
-     * createNewTransformIfNull parameter is used to specify that the PNode
-     * should create a new transform (and assign that transform to the nodes
-     * local transform variable) instead of returning null.
-     * 
-     * @param createNewTransformIfNull if the transform has not been
-     *            initialised, should it be?
-     * 
-     * @return reference to this node's transform
-     */
-    public PAffineTransform getTransformReference(final boolean createNewTransformIfNull) {
-        if (transform == null && createNewTransformIfNull) {
-            transform = new PAffineTransform();
-        }
-        return transform;
-    }
+	/**
+	 * Return a reference to the transform associated with this node. This
+	 * returned transform should not be modified. PNode transforms are created
+	 * lazily when needed. If you access the transform reference before the
+	 * transform has been created it may return null. The
+	 * createNewTransformIfNull parameter is used to specify that the PNode
+	 * should create a new transform (and assign that transform to the nodes
+	 * local transform variable) instead of returning null.
+	 * 
+	 * @param createNewTransformIfNull
+	 *            if the transform has not been initialised, should it be?
+	 * 
+	 * @return reference to this node's transform
+	 */
+	public PAffineTransform getTransformReference(
+			final boolean createNewTransformIfNull) {
+		if (transform == null && createNewTransformIfNull) {
+			transform = new PAffineTransform();
+		}
+		return transform;
+	}
 
-    /**
-     * Return an inverted copy of the transform associated with this node.
-     * 
-     * @return inverted copy of this node's transform
-     */
-    public PAffineTransform getInverseTransform() {
-        if (transform == null) {
-            return new PAffineTransform();
-        }
+	/**
+	 * Return an inverted copy of the transform associated with this node.
+	 * 
+	 * @return inverted copy of this node's transform
+	 */
+	public PAffineTransform getInverseTransform() {
+		if (transform == null) {
+			return new PAffineTransform();
+		}
 
-        try {
-            return new PAffineTransform(transform.createInverse());
-        }
-        catch (final NoninvertibleTransformException e) {
-            throw new PAffineTransformException(e, transform);
-        }
-    }
+		try {
+			return new PAffineTransform(transform.createInverse());
+		} catch (final NoninvertibleTransformException e) {
+			throw new PAffineTransformException(e, transform);
+		}
+	}
 
-    /**
-     * Set the transform applied to this node.
-     * 
-     * @param transform the new transform value
-     */
-    public void setTransform(final AffineTransform transform) {
-        if (transform == null) {
-            this.transform = null;
-        }
-        else {
-            getTransformReference(true).setTransform(transform);
-        }
+	/**
+	 * Set the transform applied to this node.
+	 * 
+	 * @param transform
+	 *            the new transform value
+	 */
+	public void setTransform(final AffineTransform transform) {
+		if (transform == null) {
+			this.transform = null;
+		} else {
+			getTransformReference(true).setTransform(transform);
+		}
 
-        invalidatePaint();
-        invalidateFullBounds();
-        firePropertyChange(PROPERTY_CODE_TRANSFORM, PROPERTY_TRANSFORM, null, this.transform);
-    }
+		invalidatePaint();
+		invalidateFullBounds();
+		firePropertyChange(PROPERTY_CODE_TRANSFORM, PROPERTY_TRANSFORM, null,
+				this.transform);
+	}
 
-    // ****************************************************************
-    // Paint Damage Management - Methods used to invalidate the areas of
-    // the screen that this node appears in so that they will later get
-    // painted.
-    // 
-    // Generally you will not need to call these invalidate methods
-    // when starting out with Piccolo2d because methods such as setPaint
-    // already automatically call them for you. You will need to call
-    // them when you start creating your own nodes.
-    // 
-    // When you do create you own nodes the only method that you will
-    // normally need to call is invalidatePaint. This method marks the
-    // nodes as having invalid paint, the root node's UI cycle will then
-    // later discover this damage and report it to the Java repaint manager.
-    // 
-    // Repainting is normally done with PNode.invalidatePaint() instead of
-    // directly calling PNode.repaint() because PNode.repaint() requires
-    // the nodes bounds to be computed right away. But with invalidatePaint
-    // the bounds computation can be delayed until the end of the root's UI
-    // cycle, and this can add up to a bit savings when modifying a
-    // large number of nodes all at once.
-    // 
-    // The other methods here will rarely be called except internally
-    // from the framework.
-    // ****************************************************************
+	// ****************************************************************
+	// Paint Damage Management - Methods used to invalidate the areas of
+	// the screen that this node appears in so that they will later get
+	// painted.
+	// 
+	// Generally you will not need to call these invalidate methods
+	// when starting out with Piccolo2d because methods such as setPaint
+	// already automatically call them for you. You will need to call
+	// them when you start creating your own nodes.
+	// 
+	// When you do create you own nodes the only method that you will
+	// normally need to call is invalidatePaint. This method marks the
+	// nodes as having invalid paint, the root node's UI cycle will then
+	// later discover this damage and report it to the Java repaint manager.
+	// 
+	// Repainting is normally done with PNode.invalidatePaint() instead of
+	// directly calling PNode.repaint() because PNode.repaint() requires
+	// the nodes bounds to be computed right away. But with invalidatePaint
+	// the bounds computation can be delayed until the end of the root's UI
+	// cycle, and this can add up to a bit savings when modifying a
+	// large number of nodes all at once.
+	// 
+	// The other methods here will rarely be called except internally
+	// from the framework.
+	// ****************************************************************
 
-    /**
-     * Return true if this nodes paint is invalid, in which case the node needs
-     * to be repainted.
-     * 
-     * @return true if this node needs to be repainted
-     */
-    public boolean getPaintInvalid() {
-        return paintInvalid;
-    }
+	/**
+	 * Return true if this nodes paint is invalid, in which case the node needs
+	 * to be repainted.
+	 * 
+	 * @return true if this node needs to be repainted
+	 */
+	public boolean getPaintInvalid() {
+		return paintInvalid;
+	}
+
+	/**
+	 * Mark this node as having invalid paint. If this is set the node will
+	 * later be repainted. Node this method is most often used internally.
+	 * 
+	 * @param paintInvalid
+	 *            true if this node should be repainted
+	 */
+	public void setPaintInvalid(final boolean paintInvalid) {
+		this.paintInvalid = paintInvalid;
+	}
 
-    /**
-     * Mark this node as having invalid paint. If this is set the node will
-     * later be repainted. Node this method is most often used internally.
-     * 
-     * @param paintInvalid true if this node should be repainted
-     */
-    public void setPaintInvalid(final boolean paintInvalid) {
-        this.paintInvalid = paintInvalid;
-    }
+	/**
+	 * Return true if this node has a child with invalid paint.
+	 * 
+	 * @return true if this node has a child with invalid paint
+	 */
+	public boolean getChildPaintInvalid() {
+		return childPaintInvalid;
+	}
 
-    /**
-     * Return true if this node has a child with invalid paint.
-     * 
-     * @return true if this node has a child with invalid paint
-     */
-    public boolean getChildPaintInvalid() {
-        return childPaintInvalid;
-    }
+	/**
+	 * Mark this node as having a child with invalid paint.
+	 * 
+	 * @param childPaintInvalid
+	 *            true if this node has a child with invalid paint
+	 */
+	public void setChildPaintInvalid(final boolean childPaintInvalid) {
+		this.childPaintInvalid = childPaintInvalid;
+	}
 
-    /**
-     * Mark this node as having a child with invalid paint.
-     * 
-     * @param childPaintInvalid true if this node has a child with invalid paint
-     */
-    public void setChildPaintInvalid(final boolean childPaintInvalid) {
-        this.childPaintInvalid = childPaintInvalid;
-    }
+	/**
+	 * Invalidate this node's paint, and mark all of its ancestors as having a
+	 * node with invalid paint.
+	 */
+	public void invalidatePaint() {
+		setPaintInvalid(true);
 
-    /**
-     * Invalidate this node's paint, and mark all of its ancestors as having a
-     * node with invalid paint.
-     */
-    public void invalidatePaint() {
-        setPaintInvalid(true);
+		PNode n = parent;
+		while (n != null && !n.getChildPaintInvalid()) {
+			n.setChildPaintInvalid(true);
+			n = n.parent;
+		}
 
-        PNode n = parent;
-        while (n != null && !n.getChildPaintInvalid()) {
-            n.setChildPaintInvalid(true);
-            n = n.parent;
-        }
+		if (SCENE_GRAPH_DELEGATE != null) {
+			SCENE_GRAPH_DELEGATE.nodePaintInvalidated(this);
+		}
+	}
 
-        if (SCENE_GRAPH_DELEGATE != null) {
-            SCENE_GRAPH_DELEGATE.nodePaintInvalidated(this);
-        }
-    }
+	/**
+	 * Repaint this node and any of its descendants if they have invalid paint.
+	 */
+	public void validateFullPaint() {
+		if (getPaintInvalid()) {
+			repaint();
+			setPaintInvalid(false);
+		}
 
-    /**
-     * Repaint this node and any of its descendants if they have invalid paint.
-     */
-    public void validateFullPaint() {
-        if (getPaintInvalid()) {
-            repaint();
-            setPaintInvalid(false);
-        }
+		if (getChildPaintInvalid()) {
+			final int count = getChildrenCount();
+			for (int i = 0; i < count; i++) {
+				final PNode each = (PNode) children.get(i);
+				each.validateFullPaint();
+			}
+			setChildPaintInvalid(false);
+		}
+	}
 
-        if (getChildPaintInvalid()) {
-            final int count = getChildrenCount();
-            for (int i = 0; i < count; i++) {
-                final PNode each = (PNode) children.get(i);
-                each.validateFullPaint();
-            }
-            setChildPaintInvalid(false);
-        }
-    }
+	/**
+	 * Mark the area on the screen represented by this nodes full bounds as
+	 * needing a repaint.
+	 */
+	public void repaint() {
+		TEMP_REPAINT_BOUNDS.setRect(getFullBoundsReference());
+		repaintFrom(TEMP_REPAINT_BOUNDS, this);
+	}
 
-    /**
-     * Mark the area on the screen represented by this nodes full bounds as
-     * needing a repaint.
-     */
-    public void repaint() {
-        TEMP_REPAINT_BOUNDS.setRect(getFullBoundsReference());
-        repaintFrom(TEMP_REPAINT_BOUNDS, this);
-    }
+	/**
+	 * Pass the given repaint request up the tree, so that any cameras can
+	 * invalidate that region on their associated canvas.
+	 * 
+	 * @param localBounds
+	 *            the bounds to repaint
+	 * @param childOrThis
+	 *            if childOrThis does not equal this then this nodes transform
+	 *            will be applied to the localBounds param
+	 */
+	public void repaintFrom(final PBounds localBounds, final PNode childOrThis) {
+		if (parent != null) {
+			if (childOrThis != this) {
+				localToParent(localBounds);
+			} else if (!getVisible()) {
+				return;
+			}
+			parent.repaintFrom(localBounds, this);
+		}
+	}
 
-    /**
-     * Pass the given repaint request up the tree, so that any cameras can
-     * invalidate that region on their associated canvas.
-     * 
-     * @param localBounds the bounds to repaint
-     * @param childOrThis if childOrThis does not equal this then this nodes
-     *            transform will be applied to the localBounds param
-     */
-    public void repaintFrom(final PBounds localBounds, final PNode childOrThis) {
-        if (parent != null) {
-            if (childOrThis != this) {
-                localToParent(localBounds);
-            }
-            else if (!getVisible()) {
-                return;
-            }
-            parent.repaintFrom(localBounds, this);
-        }
-    }
+	// ****************************************************************
+	// Occluding - Methods to support occluding optimisation. Not yet
+	// complete.
+	// ****************************************************************
 
-    // ****************************************************************
-    // Occluding - Methods to support occluding optimisation. Not yet
-    // complete.
-    // ****************************************************************
+	/**
+	 * Returns whether this node is Opaque.
+	 * 
+	 * @param boundary
+	 *            boundary to check and see if this node covers completely.
+	 * 
+	 * @return true if opaque
+	 */
+	public boolean isOpaque(final Rectangle2D boundary) {
+		return false;
+	}
 
-    /**
-     * Returns whether this node is Opaque.
-     * 
-     * @param boundary boundary to check and see if this node covers completely.
-     * 
-     * @return true if opaque
-     */
-    public boolean isOpaque(final Rectangle2D boundary) {
-        return false;
-    }
+	/**
+	 * Returns whether this node has been flagged as occluded.
+	 * 
+	 * @return true if occluded
+	 */
+	public boolean getOccluded() {
+		return occluded;
+	}
 
-    /**
-     * Returns whether this node has been flagged as occluded.
-     * 
-     * @return true if occluded
-     */
-    public boolean getOccluded() {
-        return occluded;
-    }
+	/**
+	 * Flags this node as occluded.
+	 * 
+	 * @param occluded
+	 *            new value for occluded
+	 */
+	public void setOccluded(final boolean occluded) {
+		this.occluded = occluded;
+	}
 
-    /**
-     * Flags this node as occluded.
-     * 
-     * @param occluded new value for occluded
-     */
-    public void setOccluded(final boolean occluded) {
-        this.occluded = occluded;
-    }
+	// ****************************************************************
+	// Painting - Methods for painting this node and its children
+	// 
+	// Painting is how a node defines its visual representation on the
+	// screen, and is done in the local coordinate system of the node.
+	// 
+	// The default painting behavior is to first paint the node, and
+	// then paint the node's children on top of the node. If a node
+	// needs wants specialised painting behavior it can override:
+	// 
+	// paint() - Painting here will happen before the children
+	// are painted, so the children will be painted on top of painting done
+	// here.
+	// paintAfterChildren() - Painting here will happen after the children
+	// are painted, so it will paint on top of them.
+	// 
+	// Note that you should not normally need to override fullPaint().
+	// 
+	// The visible flag can be used to make a node invisible so that
+	// it will never get painted.
+	// ****************************************************************
 
-    // ****************************************************************
-    // Painting - Methods for painting this node and its children
-    // 
-    // Painting is how a node defines its visual representation on the
-    // screen, and is done in the local coordinate system of the node.
-    // 
-    // The default painting behavior is to first paint the node, and
-    // then paint the node's children on top of the node. If a node
-    // needs wants specialised painting behavior it can override:
-    // 
-    // paint() - Painting here will happen before the children
-    // are painted, so the children will be painted on top of painting done
-    // here.
-    // paintAfterChildren() - Painting here will happen after the children
-    // are painted, so it will paint on top of them.
-    // 
-    // Note that you should not normally need to override fullPaint().
-    // 
-    // The visible flag can be used to make a node invisible so that
-    // it will never get painted.
-    // ****************************************************************
+	/**
+	 * Return true if this node is visible, that is if it will paint itself and
+	 * descendants.
+	 * 
+	 * @return true if this node and its descendants are visible.
+	 */
+	public boolean getVisible() {
+		return visible;
+	}
 
-    /**
-     * Return true if this node is visible, that is if it will paint itself and
-     * descendants.
-     * 
-     * @return true if this node and its descendants are visible.
-     */
-    public boolean getVisible() {
-        return visible;
-    }
+	/**
+	 * Set the visibility of this node and its descendants.
+	 * 
+	 * @param isVisible
+	 *            true if this node and its descendants are visible
+	 */
+	public void setVisible(final boolean isVisible) {
+		if (getVisible() != isVisible) {
+			if (!isVisible) {
+				repaint();
+			}
+			visible = isVisible;
+			firePropertyChange(PROPERTY_CODE_VISIBLE, PROPERTY_VISIBLE, null,
+					null);
+			invalidatePaint();
+		}
+	}
 
-    /**
-     * Set the visibility of this node and its descendants.
-     * 
-     * @param isVisible true if this node and its descendants are visible
-     */
-    public void setVisible(final boolean isVisible) {
-        if (getVisible() != isVisible) {
-            if (!isVisible) {
-                repaint();
-            }
-            visible = isVisible;
-            firePropertyChange(PROPERTY_CODE_VISIBLE, PROPERTY_VISIBLE, null, null);
-            invalidatePaint();
-        }
-    }
+	/**
+	 * Return the paint used while painting this node. This value may be null.
+	 * 
+	 * @return the paint used while painting this node.
+	 */
+	public Paint getPaint() {
+		return paint;
+	}
 
-    /**
-     * Return the paint used while painting this node. This value may be null.
-     * 
-     * @return the paint used while painting this node.
-     */
-    public Paint getPaint() {
-        return paint;
-    }
+	/**
+	 * Set the paint used to paint this node, which may be null.
+	 * 
+	 * @param newPaint
+	 *            paint that this node should use when painting itself.
+	 */
+	public void setPaint(final Paint newPaint) {
+		if (paint == newPaint) {
+			return;
+		}
 
-    /**
-     * Set the paint used to paint this node, which may be null.
-     * 
-     * @param newPaint paint that this node should use when painting itself.
-     */
-    public void setPaint(final Paint newPaint) {
-        if (paint == newPaint) {
-            return;
-        }
+		final Paint oldPaint = paint;
+		paint = newPaint;
+		invalidatePaint();
+		firePropertyChange(PROPERTY_CODE_PAINT, PROPERTY_PAINT, oldPaint, paint);
+	}
 
-        final Paint oldPaint = paint;
-        paint = newPaint;
-        invalidatePaint();
-        firePropertyChange(PROPERTY_CODE_PAINT, PROPERTY_PAINT, oldPaint, paint);
-    }
+	/**
+	 * Return the transparency used when painting this node. Note that this
+	 * transparency is also applied to all of the node's descendants.
+	 * 
+	 * @return how transparent this node is 0f = completely transparent, 1f =
+	 *         completely opaque
+	 */
+	public float getTransparency() {
+		return transparency;
+	}
 
-    /**
-     * Return the transparency used when painting this node. Note that this
-     * transparency is also applied to all of the node's descendants.
-     * 
-     * @return how transparent this node is 0f = completely transparent, 1f =
-     *         completely opaque
-     */
-    public float getTransparency() {
-        return transparency;
-    }
+	/**
+	 * Set the transparency used to paint this node. Note that this transparency
+	 * applies to this node and all of its descendants.
+	 * 
+	 * @param newTransparency
+	 *            transparency value for this node. 0f = fully transparent, 1f =
+	 *            fully opaque
+	 */
+	public void setTransparency(final float newTransparency) {
+		if (Math.abs(transparency - newTransparency) > TRANSPARENCY_RESOLUTION) {
+			final float oldTransparency = transparency;
+			transparency = newTransparency;
+			invalidatePaint();
+			firePropertyChange(PROPERTY_CODE_TRANSPARENCY,
+					PROPERTY_TRANSPARENCY, new Float(oldTransparency),
+					new Float(newTransparency));
+		}
+	}
 
-    /**
-     * Set the transparency used to paint this node. Note that this transparency
-     * applies to this node and all of its descendants.
-     * 
-     * @param newTransparency transparency value for this node. 0f = fully
-     *            transparent, 1f = fully opaque
-     */
-    public void setTransparency(final float newTransparency) {
-        if (Math.abs(transparency - newTransparency) > TRANSPARENCY_RESOLUTION) {
-            final float oldTransparency = transparency;
-            transparency = newTransparency;
-            invalidatePaint();
-            firePropertyChange(PROPERTY_CODE_TRANSPARENCY, PROPERTY_TRANSPARENCY, new Float(oldTransparency),
-                    new Float(newTransparency));
-        }
-    }
+	/**
+	 * Paint this node behind any of its children nodes. Subclasses that define
+	 * a different appearance should override this method and paint themselves
+	 * there.
+	 * 
+	 * @param paintContext
+	 *            the paint context to use for painting the node
+	 */
+	protected void paint(final PPaintContext paintContext) {
+		if (paint != null) {
+			final Graphics2D g2 = paintContext.getGraphics();
+			g2.setPaint(paint);
+			g2.fill(getBoundsReference());
+		}
+	}
 
-    /**
-     * Paint this node behind any of its children nodes. Subclasses that define
-     * a different appearance should override this method and paint themselves
-     * there.
-     * 
-     * @param paintContext the paint context to use for painting the node
-     */
-    protected void paint(final PPaintContext paintContext) {
-        if (paint != null) {
-            final Graphics2D g2 = paintContext.getGraphics();
-            g2.setPaint(paint);
-            g2.fill(getBoundsReference());
-        }
-    }
+	/**
+	 * Paint this node and all of its descendants. Most subclasses do not need
+	 * to override this method, they should override paint or
+	 * paintAfterChildren instead.
+	 * 
+	 * @param paintContext
+	 *            the paint context to use for painting this node and its
+	 *            children
+	 */
+	public void fullPaint(final PPaintContext paintContext) {
+		if (getVisible() && fullIntersects(paintContext.getLocalClip())) {
+			paintContext.pushTransform(transform);
+			paintContext.pushTransparency(transparency);
 
-    /**
-     * Paint this node and all of its descendants. Most subclasses do not need
-     * to override this method, they should override paint or
-     * paintAfterChildren instead.
-     * 
-     * @param paintContext the paint context to use for painting this node and
-     *            its children
-     */
-    public void fullPaint(final PPaintContext paintContext) {
-        if (getVisible() && fullIntersects(paintContext.getLocalClip())) {
-            paintContext.pushTransform(transform);
-            paintContext.pushTransparency(transparency);
+			if (!getOccluded()) {
+				paint(paintContext);
+			}
 
-            if (!getOccluded()) {
-                paint(paintContext);
-            }
+			final int count = getChildrenCount();
+			for (int i = 0; i < count; i++) {
+				final PNode each = (PNode) children.get(i);
+				each.fullPaint(paintContext);
+			}
 
-            final int count = getChildrenCount();
-            for (int i = 0; i < count; i++) {
-                final PNode each = (PNode) children.get(i);
-                each.fullPaint(paintContext);
-            }
+			paintAfterChildren(paintContext);
 
-            paintAfterChildren(paintContext);
+			paintContext.popTransparency(transparency);
+			paintContext.popTransform(transform);
+		}
+	}
 
-            paintContext.popTransparency(transparency);
-            paintContext.popTransform(transform);
-        }
-    }
+	/**
+	 * Subclasses that wish to do additional painting after their children are
+	 * painted should override this method and do that painting here.
+	 * 
+	 * @param paintContext
+	 *            the paint context to sue for painting after the children are
+	 *            painted
+	 */
+	protected void paintAfterChildren(final PPaintContext paintContext) {
+	}
 
-    /**
-     * Subclasses that wish to do additional painting after their children are
-     * painted should override this method and do that painting here.
-     * 
-     * @param paintContext the paint context to sue for painting after the
-     *            children are painted
-     */
-    protected void paintAfterChildren(final PPaintContext paintContext) {
-    }
+	/**
+	 * Return a new Image representing this node and all of its children. The
+	 * image size will be equal to the size of this nodes full bounds.
+	 * 
+	 * @return a new image representing this node and its descendants
+	 */
+	public Image toImage() {
+		final PBounds b = getFullBoundsReference();
+		return toImage((int) Math.ceil(b.getWidth()), (int) Math.ceil(b
+				.getHeight()), null);
+	}
 
-    /**
-     * Return a new Image representing this node and all of its children. The
-     * image size will be equal to the size of this nodes full bounds.
-     * 
-     * @return a new image representing this node and its descendants
-     */
-    public Image toImage() {
-        final PBounds b = getFullBoundsReference();
-        return toImage((int) Math.ceil(b.getWidth()), (int) Math.ceil(b.getHeight()), null);
-    }
+	/**
+	 * Return a new Image of the requested size representing this node and all
+	 * of its children. If backGroundPaint is null the resulting image will have
+	 * transparent regions, otherwise those regions will be filled with the
+	 * backgroundPaint.
+	 * 
+	 * @param width
+	 *            pixel width of the resulting image
+	 * @param height
+	 *            pixel height of the resulting image
+	 * @param backgroundPaint
+	 *            paint to fill the image with before drawing this node, may be
+	 *            null
+	 * 
+	 * @return a new image representing this node and its descendants
+	 */
+	public Image toImage(final int width, final int height,
+			final Paint backgroundPaint) {
+		BufferedImage result;
 
-    /**
-     * Return a new Image of the requested size representing this node and all
-     * of its children. If backGroundPaint is null the resulting image will have
-     * transparent regions, otherwise those regions will be filled with the
-     * backgroundPaint.
-     * 
-     * @param width pixel width of the resulting image
-     * @param height pixel height of the resulting image
-     * @param backgroundPaint paint to fill the image with before drawing this
-     *            node, may be null
-     * 
-     * @return a new image representing this node and its descendants
-     */
-    public Image toImage(final int width, final int height, final Paint backgroundPaint) {
-        BufferedImage result;
+		if (GraphicsEnvironment.isHeadless()) {
+			result = new BufferedImage(width, height,
+					BufferedImage.TYPE_INT_ARGB);
+		} else {
+			final GraphicsConfiguration graphicsConfiguration = GraphicsEnvironment
+					.getLocalGraphicsEnvironment().getDefaultScreenDevice()
+					.getDefaultConfiguration();
+			result = graphicsConfiguration.createCompatibleImage(width, height,
+					Transparency.TRANSLUCENT);
+		}
 
-        if (GraphicsEnvironment.isHeadless()) {
-            result = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
-        }
-        else {
-            final GraphicsConfiguration graphicsConfiguration = GraphicsEnvironment.getLocalGraphicsEnvironment()
-                    .getDefaultScreenDevice().getDefaultConfiguration();
-            result = graphicsConfiguration.createCompatibleImage(width, height, Transparency.TRANSLUCENT);
-        }
+		return toImage(result, backgroundPaint);
+	}
 
-        return toImage(result, backgroundPaint);
-    }
+	/**
+	 * Paint a representation of this node into the specified buffered image. If
+	 * background, paint is null, then the image will not be filled with a color
+	 * prior to rendering
+	 * 
+	 * @param image
+	 *            Image onto which this node will be painted
+	 * @param backGroundPaint
+	 *            will fill background of image with this. May be null.
+	 * @return a rendering of this image and its descendants onto the specified
+	 *         image
+	 */
+	public Image toImage(final BufferedImage image, final Paint backGroundPaint) {
+		return toImage(image, backGroundPaint, FILL_STRATEGY_ASPECT_FIT);
+	}
 
-    /**
-     * Paint a representation of this node into the specified buffered image. If
-     * background, paint is null, then the image will not be filled with a color
-     * prior to rendering
-     * 
-     * @param image Image onto which this node will be painted
-     * @param backGroundPaint will fill background of image with this. May be
-     *            null.
-     * @return a rendering of this image and its descendants onto the specified
-     *         image
-     */
-    public Image toImage(final BufferedImage image, final Paint backGroundPaint) {
-        return toImage(image, backGroundPaint, FILL_STRATEGY_ASPECT_FIT);
-    }
+	/**
+	 * Paint a representation of this node into the specified buffered image. If
+	 * background, paint is null, then the image will not be filled with a color
+	 * prior to rendering
+	 * 
+	 * @since 1.3
+	 * @param image
+	 *            Image onto which this node will be painted
+	 * @param backGroundPaint
+	 *            will fill background of image with this. May be null.
+	 * @param fillStrategy
+	 *            strategy to use regarding how node will cover the image
+	 * @return a rendering of this image and its descendants onto the specified
+	 *         image
+	 */
+	public Image toImage(final BufferedImage image,
+			final Paint backGroundPaint, final int fillStrategy) {
+		final int imageWidth = image.getWidth();
+		final int imageHeight = image.getHeight();
+		final Graphics2D g2 = image.createGraphics();
 
-    /**
-     * Paint a representation of this node into the specified buffered image. If
-     * background, paint is null, then the image will not be filled with a color
-     * prior to rendering
-     * 
-     * @since 1.3
-     * @param image Image onto which this node will be painted
-     * @param backGroundPaint will fill background of image with this. May be
-     *            null.
-     * @param fillStrategy strategy to use regarding how node will cover the
-     *            image
-     * @return a rendering of this image and its descendants onto the specified
-     *         image
-     */
-    public Image toImage(final BufferedImage image, final Paint backGroundPaint, final int fillStrategy) {
-        final int imageWidth = image.getWidth();
-        final int imageHeight = image.getHeight();
-        final Graphics2D g2 = image.createGraphics();
+		if (backGroundPaint != null) {
+			g2.setPaint(backGroundPaint);
+			g2.fillRect(0, 0, imageWidth, imageHeight);
+		}
+		g2.setClip(0, 0, imageWidth, imageHeight);
 
-        if (backGroundPaint != null) {
-            g2.setPaint(backGroundPaint);
-            g2.fillRect(0, 0, imageWidth, imageHeight);
-        }
-        g2.setClip(0, 0, imageWidth, imageHeight);
+		final PBounds nodeBounds = getFullBounds();
+		nodeBounds.expandNearestIntegerDimensions();
 
-        final PBounds nodeBounds = getFullBounds();
-        nodeBounds.expandNearestIntegerDimensions();
+		final double nodeWidth = nodeBounds.getWidth();
+		final double nodeHeight = nodeBounds.getHeight();
 
-        final double nodeWidth = nodeBounds.getWidth();
-        final double nodeHeight = nodeBounds.getHeight();
+		double imageRatio = imageWidth / (imageHeight * 1.0);
+		double nodeRatio = nodeWidth / nodeHeight;
+		double scale;
+		switch (fillStrategy) {
+		case FILL_STRATEGY_ASPECT_FIT:
+			// scale the graphics so node's full bounds fit in the imageable
+			// bounds but aspect ration is retained
 
-        double imageRatio = imageWidth / (imageHeight * 1.0);
-        double nodeRatio = nodeWidth / nodeHeight;
-        double scale;
-        switch (fillStrategy) {
-            case FILL_STRATEGY_ASPECT_FIT:
-                // scale the graphics so node's full bounds fit in the imageable
-                // bounds but aspect ration is retained
+			if (nodeRatio <= imageRatio) {
+				scale = image.getHeight() / nodeHeight;
+			} else {
+				scale = image.getWidth() / nodeWidth;
+			}
+			g2.scale(scale, scale);
+			g2.translate(-nodeBounds.x, -nodeBounds.y);
+			break;
+		case FILL_STRATEGY_ASPECT_COVER:
+			// scale the graphics so node completely covers the imageable
+			// area, but retains its aspect ratio.
+			if (nodeRatio <= imageRatio) {
+				scale = image.getWidth() / nodeWidth;
+			} else {
+				scale = image.getHeight() / nodeHeight;
+			}
+			g2.scale(scale, scale);
+			break;
+		case FILL_STRATEGY_EXACT_FIT:
+			// scale the node so that it covers then entire image,
+			// distorting it if necessary.
+			g2.scale(image.getWidth() / nodeWidth, image.getHeight()
+					/ nodeHeight);
+			g2.translate(-nodeBounds.x, -nodeBounds.y);
+			break;
+		default:
+			throw new IllegalArgumentException(
+					"Fill strategy provided is invalid");
+		}
 
-                if (nodeRatio <= imageRatio) {
-                    scale = image.getHeight() / nodeHeight;
-                }
-                else {
-                    scale = image.getWidth() / nodeWidth;
-                }
-                g2.scale(scale, scale);
-                g2.translate(-nodeBounds.x, -nodeBounds.y);
-                break;
-            case FILL_STRATEGY_ASPECT_COVER:
-                // scale the graphics so node completely covers the imageable
-                // area, but retains its aspect ratio.
-                if (nodeRatio <= imageRatio) {
-                    scale = image.getWidth() / nodeWidth;
-                }
-                else {
-                    scale = image.getHeight() / nodeHeight;
-                }                           
-                g2.scale(scale, scale);               
-                break;
-            case FILL_STRATEGY_EXACT_FIT:
-                // scale the node so that it covers then entire image,
-                // distorting it if necessary.
-                g2.scale(image.getWidth() / nodeWidth, image.getHeight() / nodeHeight);
-                g2.translate(-nodeBounds.x, -nodeBounds.y);
-                break;
-            default:
-                throw new IllegalArgumentException("Fill strategy provided is invalid");
-        }
+		final PPaintContext pc = new PPaintContext(g2);
+		pc.setRenderQuality(PPaintContext.HIGH_QUALITY_RENDERING);
+		fullPaint(pc);
+		return image;
+	}
 
-        final PPaintContext pc = new PPaintContext(g2);
-        pc.setRenderQuality(PPaintContext.HIGH_QUALITY_RENDERING);
-        fullPaint(pc);
-        return image;
-    }
+	/**
+	 * Constructs a new PrinterJob, allows the user to select which printer to
+	 * print to, And then prints the node.
+	 */
+	public void print() {
+		final PrinterJob printJob = PrinterJob.getPrinterJob();
+		final PageFormat pageFormat = printJob.defaultPage();
+		final Book book = new Book();
+		book.append(this, pageFormat);
+		printJob.setPageable(book);
 
-    /**
-     * Constructs a new PrinterJob, allows the user to select which printer to
-     * print to, And then prints the node.
-     */
-    public void print() {
-        final PrinterJob printJob = PrinterJob.getPrinterJob();
-        final PageFormat pageFormat = printJob.defaultPage();
-        final Book book = new Book();
-        book.append(this, pageFormat);
-        printJob.setPageable(book);
+		if (printJob.printDialog()) {
+			try {
+				printJob.print();
+			} catch (final PrinterException e) {
+				throw new RuntimeException("Error Printing", e);
+			}
+		}
+	}
 
-        if (printJob.printDialog()) {
-            try {
-                printJob.print();
-            }
-            catch (final PrinterException e) {
-                throw new RuntimeException("Error Printing", e);
-            }
-        }
-    }
+	/**
+	 * Prints the node into the given Graphics context using the specified
+	 * format. The zero based index of the requested page is specified by
+	 * pageIndex. If the requested page does not exist then this method returns
+	 * NO_SUCH_PAGE; otherwise PAGE_EXISTS is returned. If the printable object
+	 * aborts the print job then it throws a PrinterException.
+	 * 
+	 * @param graphics
+	 *            the context into which the node is drawn
+	 * @param pageFormat
+	 *            the size and orientation of the page
+	 * @param pageIndex
+	 *            the zero based index of the page to be drawn
+	 * 
+	 * @return Either NO_SUCH_PAGE or PAGE_EXISTS
+	 */
+	public int print(final Graphics graphics, final PageFormat pageFormat,
+			final int pageIndex) {
+		if (pageIndex != 0) {
+			return NO_SUCH_PAGE;
+		}
 
-    /**
-     * Prints the node into the given Graphics context using the specified
-     * format. The zero based index of the requested page is specified by
-     * pageIndex. If the requested page does not exist then this method returns
-     * NO_SUCH_PAGE; otherwise PAGE_EXISTS is returned. If the printable object
-     * aborts the print job then it throws a PrinterException.
-     * 
-     * @param graphics the context into which the node is drawn
-     * @param pageFormat the size and orientation of the page
-     * @param pageIndex the zero based index of the page to be drawn
-     * 
-     * @return Either NO_SUCH_PAGE or PAGE_EXISTS
-     */
-    public int print(final Graphics graphics, final PageFormat pageFormat, final int pageIndex) {
-        if (pageIndex != 0) {
-            return NO_SUCH_PAGE;
-        }
-        
-        if (!(graphics instanceof Graphics2D)) {
-            throw new IllegalArgumentException("Provided graphics context is not a Graphics2D object");
-        }
-        
+		if (!(graphics instanceof Graphics2D)) {
+			throw new IllegalArgumentException(
+					"Provided graphics context is not a Graphics2D object");
+		}
 
-        final Graphics2D g2 = (Graphics2D) graphics;
-        final PBounds imageBounds = getFullBounds();
+		final Graphics2D g2 = (Graphics2D) graphics;
+		final PBounds imageBounds = getFullBounds();
 
-        imageBounds.expandNearestIntegerDimensions();
+		imageBounds.expandNearestIntegerDimensions();
 
-        g2.setClip(0, 0, (int) pageFormat.getWidth(), (int) pageFormat.getHeight());
-        g2.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
+		g2.setClip(0, 0, (int) pageFormat.getWidth(), (int) pageFormat
+				.getHeight());
+		g2.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
 
-        // scale the graphics so node's full bounds fit in the imageable bounds.
-        double scale = pageFormat.getImageableWidth() / imageBounds.getWidth();
-        if (pageFormat.getImageableHeight() / imageBounds.getHeight() < scale) {
-            scale = pageFormat.getImageableHeight() / imageBounds.getHeight();
-        }
+		// scale the graphics so node's full bounds fit in the imageable bounds.
+		double scale = pageFormat.getImageableWidth() / imageBounds.getWidth();
+		if (pageFormat.getImageableHeight() / imageBounds.getHeight() < scale) {
+			scale = pageFormat.getImageableHeight() / imageBounds.getHeight();
+		}
 
-        g2.scale(scale, scale);
-        g2.translate(-imageBounds.x, -imageBounds.y);
+		g2.scale(scale, scale);
+		g2.translate(-imageBounds.x, -imageBounds.y);
 
-        final PPaintContext pc = new PPaintContext(g2);
-        pc.setRenderQuality(PPaintContext.HIGH_QUALITY_RENDERING);
-        fullPaint(pc);
+		final PPaintContext pc = new PPaintContext(g2);
+		pc.setRenderQuality(PPaintContext.HIGH_QUALITY_RENDERING);
+		fullPaint(pc);
 
-        return PAGE_EXISTS;
-    }
+		return PAGE_EXISTS;
+	}
 
-    // ****************************************************************
-    // Picking - Methods for picking this node and its children.
-    // 
-    // Picking is used to determine the node that intersects a point or
-    // rectangle on the screen. It is most frequently used by the
-    // PInputManager to determine the node that the cursor is over.
-    // 
-    // The intersects() method is used to determine if a node has
-    // been picked or not. The default implementation just test to see
-    // if the pick bounds intersects the bounds of the node. Subclasses
-    // whose geometry (a circle for example) does not match up exactly with
-    // the bounds should override the intersects() method.
-    // 
-    // The default picking behavior is to first try to pick the nodes
-    // children, and then try to pick the nodes own bounds. If a node
-    // wants specialized picking behavior it can override:
-    // 
-    // pick() - Pick nodes here that should be picked before the nodes
-    // children are picked.
-    // pickAfterChildren() - Pick nodes here that should be picked after the
-    // node's children are picked.
-    // 
-    // Note that fullPick should not normally be overridden.
-    // 
-    // The pickable and childrenPickable flags can be used to make a
-    // node or it children not pickable even if their geometry does
-    // intersect the pick bounds.
-    // ****************************************************************
+	// ****************************************************************
+	// Picking - Methods for picking this node and its children.
+	// 
+	// Picking is used to determine the node that intersects a point or
+	// rectangle on the screen. It is most frequently used by the
+	// PInputManager to determine the node that the cursor is over.
+	// 
+	// The intersects() method is used to determine if a node has
+	// been picked or not. The default implementation just test to see
+	// if the pick bounds intersects the bounds of the node. Subclasses
+	// whose geometry (a circle for example) does not match up exactly with
+	// the bounds should override the intersects() method.
+	// 
+	// The default picking behavior is to first try to pick the nodes
+	// children, and then try to pick the nodes own bounds. If a node
+	// wants specialized picking behavior it can override:
+	// 
+	// pick() - Pick nodes here that should be picked before the nodes
+	// children are picked.
+	// pickAfterChildren() - Pick nodes here that should be picked after the
+	// node's children are picked.
+	// 
+	// Note that fullPick should not normally be overridden.
+	// 
+	// The pickable and childrenPickable flags can be used to make a
+	// node or it children not pickable even if their geometry does
+	// intersect the pick bounds.
+	// ****************************************************************
 
-    /**
-     * Return true if this node is pickable. Only pickable nodes can receive
-     * input events. Nodes are pickable by default.
-     * 
-     * @return true if this node is pickable
-     */
-    public boolean getPickable() {
-        return pickable;
-    }
+	/**
+	 * Return true if this node is pickable. Only pickable nodes can receive
+	 * input events. Nodes are pickable by default.
+	 * 
+	 * @return true if this node is pickable
+	 */
+	public boolean getPickable() {
+		return pickable;
+	}
 
-    /**
-     * Set the pickable flag for this node. Only pickable nodes can receive
-     * input events. Nodes are pickable by default.
-     * 
-     * @param isPickable true if this node is pickable
-     */
-    public void setPickable(final boolean isPickable) {
-        if (getPickable() != isPickable) {
-            pickable = isPickable;
-            firePropertyChange(PROPERTY_CODE_PICKABLE, PROPERTY_PICKABLE, null, null);
-        }
-    }
+	/**
+	 * Set the pickable flag for this node. Only pickable nodes can receive
+	 * input events. Nodes are pickable by default.
+	 * 
+	 * @param isPickable
+	 *            true if this node is pickable
+	 */
+	public void setPickable(final boolean isPickable) {
+		if (getPickable() != isPickable) {
+			pickable = isPickable;
+			firePropertyChange(PROPERTY_CODE_PICKABLE, PROPERTY_PICKABLE, null,
+					null);
+		}
+	}
 
-    /**
-     * Return true if the children of this node should be picked. If this flag
-     * is false then this node will not try to pick its children. Children are
-     * pickable by default.
-     * 
-     * @return true if this node tries to pick its children
-     */
-    public boolean getChildrenPickable() {
-        return childrenPickable;
-    }
+	/**
+	 * Return true if the children of this node should be picked. If this flag
+	 * is false then this node will not try to pick its children. Children are
+	 * pickable by default.
+	 * 
+	 * @return true if this node tries to pick its children
+	 */
+	public boolean getChildrenPickable() {
+		return childrenPickable;
+	}
 
-    /**
-     * Set the children pickable flag. If this flag is false then this node will
-     * not try to pick its children. Children are pickable by default.
-     * 
-     * @param areChildrenPickable true if this node tries to pick its children
-     */
-    public void setChildrenPickable(final boolean areChildrenPickable) {
-        if (getChildrenPickable() != areChildrenPickable) {
-            childrenPickable = areChildrenPickable;
-            firePropertyChange(PROPERTY_CODE_CHILDREN_PICKABLE, PROPERTY_CHILDREN_PICKABLE, null, null);
-        }
-    }
+	/**
+	 * Set the children pickable flag. If this flag is false then this node will
+	 * not try to pick its children. Children are pickable by default.
+	 * 
+	 * @param areChildrenPickable
+	 *            true if this node tries to pick its children
+	 */
+	public void setChildrenPickable(final boolean areChildrenPickable) {
+		if (getChildrenPickable() != areChildrenPickable) {
+			childrenPickable = areChildrenPickable;
+			firePropertyChange(PROPERTY_CODE_CHILDREN_PICKABLE,
+					PROPERTY_CHILDREN_PICKABLE, null, null);
+		}
+	}
 
-    /**
-     * Try to pick this node before its children have had a chance to be picked.
-     * Nodes that paint on top of their children may want to override this
-     * method to if the pick path intersects that paint.
-     * 
-     * @param pickPath the pick path used for the pick operation
-     * @return true if this node was picked
-     */
-    protected boolean pick(final PPickPath pickPath) {
-        return false;
-    }
+	/**
+	 * Try to pick this node before its children have had a chance to be picked.
+	 * Nodes that paint on top of their children may want to override this
+	 * method to if the pick path intersects that paint.
+	 * 
+	 * @param pickPath
+	 *            the pick path used for the pick operation
+	 * @return true if this node was picked
+	 */
+	protected boolean pick(final PPickPath pickPath) {
+		return false;
+	}
 
-    /**
-     * Try to pick this node and all of its descendants. Most subclasses should
-     * not need to override this method. Instead they should override
-     * pick or pickAfterChildren.
-     * 
-     * @param pickPath the pick path to add the node to if its picked
-     * @return true if this node or one of its descendants was picked.
-     */
-    public boolean fullPick(final PPickPath pickPath) {
-        if (getVisible() && (getPickable() || getChildrenPickable()) && fullIntersects(pickPath.getPickBounds())) {
-            pickPath.pushNode(this);
-            pickPath.pushTransform(transform);
+	/**
+	 * Try to pick this node and all of its descendants. Most subclasses should
+	 * not need to override this method. Instead they should override
+	 * pick or pickAfterChildren.
+	 * 
+	 * @param pickPath
+	 *            the pick path to add the node to if its picked
+	 * @return true if this node or one of its descendants was picked.
+	 */
+	public boolean fullPick(final PPickPath pickPath) {
+		if (getVisible() && (getPickable() || getChildrenPickable())
+				&& fullIntersects(pickPath.getPickBounds())) {
+			pickPath.pushNode(this);
+			pickPath.pushTransform(transform);
 
-            final boolean thisPickable = getPickable() && pickPath.acceptsNode(this);
+			final boolean thisPickable = getPickable()
+					&& pickPath.acceptsNode(this);
 
-            if (thisPickable && pick(pickPath)) {
-                return true;
-            }
+			if (thisPickable && pick(pickPath)) {
+				return true;
+			}
 
-            if (getChildrenPickable()) {
-                final int count = getChildrenCount();
-                for (int i = count - 1; i >= 0; i--) {
-                    final PNode each = (PNode) children.get(i);
-                    if (each.fullPick(pickPath)) {
-                        return true;
-                    }
-                }
-            }
+			if (getChildrenPickable()) {
+				final int count = getChildrenCount();
+				for (int i = count - 1; i >= 0; i--) {
+					final PNode each = (PNode) children.get(i);
+					if (each.fullPick(pickPath)) {
+						return true;
+					}
+				}
+			}
 
-            if (thisPickable && pickAfterChildren(pickPath)) {
-                return true;
-            }
+			if (thisPickable && pickAfterChildren(pickPath)) {
+				return true;
+			}
 
-            pickPath.popTransform(transform);
-            pickPath.popNode(this);
-        }
+			pickPath.popTransform(transform);
+			pickPath.popNode(this);
+		}
 
-        return false;
-    }
+		return false;
+	}
 
-    /**
-     * Finds all descendants of this node that intersect with the given bounds
-     * and adds them to the results array.
-     * 
-     * @param fullBounds bounds to compare against
-     * @param results array into which to add matches
-     */
-    public void findIntersectingNodes(final Rectangle2D fullBounds, final ArrayList results) {
-        if (fullIntersects(fullBounds)) {
-            final Rectangle2D localBounds = parentToLocal((Rectangle2D) fullBounds.clone());
+	/**
+	 * Finds all descendants of this node that intersect with the given bounds
+	 * and adds them to the results array.
+	 * 
+	 * @param fullBounds
+	 *            bounds to compare against
+	 * @param results
+	 *            array into which to add matches
+	 */
+	public void findIntersectingNodes(final Rectangle2D fullBounds,
+			final ArrayList results) {
+		if (fullIntersects(fullBounds)) {
+			final Rectangle2D localBounds = parentToLocal((Rectangle2D) fullBounds
+					.clone());
 
-            if (intersects(localBounds)) {
-                results.add(this);
-            }
+			if (intersects(localBounds)) {
+				results.add(this);
+			}
 
-            final int count = getChildrenCount();
-            for (int i = count - 1; i >= 0; i--) {
-                final PNode each = (PNode) children.get(i);
-                each.findIntersectingNodes(localBounds, results);
-            }
-        }
-    }
+			final int count = getChildrenCount();
+			for (int i = count - 1; i >= 0; i--) {
+				final PNode each = (PNode) children.get(i);
+				each.findIntersectingNodes(localBounds, results);
+			}
+		}
+	}
 
-    /**
-     * Try to pick this node after its children have had a chance to be picked.
-     * Most subclasses the define a different geometry will need to override
-     * this method.
-     * 
-     * @param pickPath the pick path used for the pick operation
-     * @return true if this node was picked
-     */
-    protected boolean pickAfterChildren(final PPickPath pickPath) {
-        if (intersects(pickPath.getPickBounds())) {
-            return true;
-        }
-        return false;
-    }
+	/**
+	 * Try to pick this node after its children have had a chance to be picked.
+	 * Most subclasses the define a different geometry will need to override
+	 * this method.
+	 * 
+	 * @param pickPath
+	 *            the pick path used for the pick operation
+	 * @return true if this node was picked
+	 */
+	protected boolean pickAfterChildren(final PPickPath pickPath) {
+		if (intersects(pickPath.getPickBounds())) {
+			return true;
+		}
+		return false;
+	}
 
-    // ****************************************************************
-    // Structure - Methods for manipulating and traversing the
-    // parent child relationship
-    // 
-    // Most of these methods won't need to be overridden by subclasses
-    // but you will use them frequently to build up your node structures.
-    // ****************************************************************
+	// ****************************************************************
+	// Structure - Methods for manipulating and traversing the
+	// parent child relationship
+	// 
+	// Most of these methods won't need to be overridden by subclasses
+	// but you will use them frequently to build up your node structures.
+	// ****************************************************************
 
-    /**
-     * Add a node to be a new child of this node. The new node is added to the
-     * end of the list of this node's children. If child was previously a child
-     * of another node, it is removed from that first.
-     * 
-     * @param child the new child to add to this node
-     */
-    public void addChild(final PNode child) {
-        int insertIndex = getChildrenCount();
-        if (child.parent == this) {
-            insertIndex--;
-        }
-        addChild(insertIndex, child);
-    }
+	/**
+	 * Add a node to be a new child of this node. The new node is added to the
+	 * end of the list of this node's children. If child was previously a child
+	 * of another node, it is removed from that first.
+	 * 
+	 * @param child
+	 *            the new child to add to this node
+	 */
+	public void addChild(final PNode child) {
+		int insertIndex = getChildrenCount();
+		if (child.parent == this) {
+			insertIndex--;
+		}
+		addChild(insertIndex, child);
+	}
 
-    /**
-     * Add a node to be a new child of this node at the specified index. If
-     * child was previously a child of another node, it is removed from that
-     * node first.
-     * 
-     * @param index where in the children list to insert the child
-     * @param child the new child to add to this node
-     */
-    public void addChild(final int index, final PNode child) {
-        final PNode oldParent = child.getParent();
+	/**
+	 * Add a node to be a new child of this node at the specified index. If
+	 * child was previously a child of another node, it is removed from that
+	 * node first.
+	 * 
+	 * @param index
+	 *            where in the children list to insert the child
+	 * @param child
+	 *            the new child to add to this node
+	 */
+	public void addChild(final int index, final PNode child) {
+		final PNode oldParent = child.getParent();
 
-        if (oldParent != null) {
-            oldParent.removeChild(child);
-        }
+		if (oldParent != null) {
+			oldParent.removeChild(child);
+		}
 
-        child.setParent(this);
-        getChildrenReference().add(index, child);
-        child.invalidatePaint();
-        invalidateFullBounds();
+		child.setParent(this);
+		getChildrenReference().add(index, child);
+		child.invalidatePaint();
+		invalidateFullBounds();
 
-        firePropertyChange(PROPERTY_CODE_CHILDREN, PROPERTY_CHILDREN, null, children);
-    }
+		firePropertyChange(PROPERTY_CODE_CHILDREN, PROPERTY_CHILDREN, null,
+				children);
+	}
 
-    /**
-     * Add a collection of nodes to be children of this node. If these nodes
-     * already have parents they will first be removed from those parents.
-     * 
-     * @param nodes a collection of nodes to be added to this node
-     */
-    public void addChildren(final Collection nodes) {
-        final Iterator i = nodes.iterator();
-        while (i.hasNext()) {
-            final PNode each = (PNode) i.next();
-            addChild(each);
-        }
-    }
+	/**
+	 * Add a collection of nodes to be children of this node. If these nodes
+	 * already have parents they will first be removed from those parents.
+	 * 
+	 * @param nodes
+	 *            a collection of nodes to be added to this node
+	 */
+	public void addChildren(final Collection nodes) {
+		final Iterator i = nodes.iterator();
+		while (i.hasNext()) {
+			final PNode each = (PNode) i.next();
+			addChild(each);
+		}
+	}
 
-    /**
-     * Return true if this node is an ancestor of the parameter node.
-     * 
-     * @param node a possible descendant node
-     * @return true if this node is an ancestor of the given node
-     */
-    public boolean isAncestorOf(final PNode node) {
-        PNode p = node.parent;
-        while (p != null) {
-            if (p == this) {
-                return true;
-            }
-            p = p.parent;
-        }
-        return false;
-    }
+	/**
+	 * Return true if this node is an ancestor of the parameter node.
+	 * 
+	 * @param node
+	 *            a possible descendant node
+	 * @return true if this node is an ancestor of the given node
+	 */
+	public boolean isAncestorOf(final PNode node) {
+		PNode p = node.parent;
+		while (p != null) {
+			if (p == this) {
+				return true;
+			}
+			p = p.parent;
+		}
+		return false;
+	}
 
-    /**
-     * Return true if this node is a descendant of the parameter node.
-     * 
-     * @param node a possible ancestor node
-     * @return true if this nodes descends from the given node
-     */
-    public boolean isDescendentOf(final PNode node) {
-        PNode p = parent;
-        while (p != null) {
-            if (p == node) {
-                return true;
-            }
-            p = p.parent;
-        }
-        return false;
-    }
+	/**
+	 * Return true if this node is a descendant of the parameter node.
+	 * 
+	 * @param node
+	 *            a possible ancestor node
+	 * @return true if this nodes descends from the given node
+	 */
+	public boolean isDescendentOf(final PNode node) {
+		PNode p = parent;
+		while (p != null) {
+			if (p == node) {
+				return true;
+			}
+			p = p.parent;
+		}
+		return false;
+	}
 
-    /**
-     * Return true if this node descends from the root.
-     * 
-     * @return whether this node descends from root node
-     */
-    public boolean isDescendentOfRoot() {
-        return getRoot() != null;
-    }
+	/**
+	 * Return true if this node descends from the root.
+	 * 
+	 * @return whether this node descends from root node
+	 */
+	public boolean isDescendentOfRoot() {
+		return getRoot() != null;
+	}
 
-    /**
-     * Change the order of this node in its parent's children list so that it
-     * will draw in back of all of its other sibling nodes.
-     */
-    public void moveToBack() {
-        final PNode p = parent;
-        if (p != null) {
-            p.removeChild(this);
-            p.addChild(0, this);
-        }
-    }
+	/**
+	 * Change the order of this node in its parent's children list so that it
+	 * will draw in back of all of its other sibling nodes.
+	 */
+	public void moveToBack() {
+		final PNode p = parent;
+		if (p != null) {
+			p.removeChild(this);
+			p.addChild(0, this);
+		}
+	}
 
-    /**
-     * Change the order of this node in its parent's children list so that it
-     * will draw in front of all of its other sibling nodes.
-     * 
-     * @param sibling sibling in back of which this nodes should be moved.
-     */
-    public void moveInBackOf(final PNode sibling) {
-        final PNode p = parent;
-        if (p != null && p == sibling.getParent()) {
-            p.removeChild(this);
-            final int index = p.indexOfChild(sibling);
-            p.addChild(index, this);
-        }
-    }
+	/**
+	 * Change the order of this node in its parent's children list so that it
+	 * will draw in front of all of its other sibling nodes.
+	 * 
+	 * @param sibling
+	 *            sibling in back of which this nodes should be moved.
+	 */
+	public void moveInBackOf(final PNode sibling) {
+		final PNode p = parent;
+		if (p != null && p == sibling.getParent()) {
+			p.removeChild(this);
+			final int index = p.indexOfChild(sibling);
+			p.addChild(index, this);
+		}
+	}
 
-    /**
-     * Change the order of this node in its parent's children list so that it
-     * will draw after the given sibling node.
-     */
-    public void moveToFront() {
-        final PNode p = parent;
-        if (p != null) {
-            p.removeChild(this);
-            p.addChild(this);
-        }
-    }
+	/**
+	 * Change the order of this node in its parent's children list so that it
+	 * will draw after the given sibling node.
+	 */
+	public void moveToFront() {
+		final PNode p = parent;
+		if (p != null) {
+			p.removeChild(this);
+			p.addChild(this);
+		}
+	}
 
-    /**
-     * Change the order of this node in its parent's children list so that it
-     * will draw before the given sibling node.
-     * 
-     * @param sibling sibling in front of which this nodes should be moved.
-     */
-    public void moveInFrontOf(final PNode sibling) {
-        final PNode p = parent;
-        if (p != null && p == sibling.getParent()) {
-            p.removeChild(this);
-            final int index = p.indexOfChild(sibling);
-            p.addChild(index + 1, this);
-        }
-    }
+	/**
+	 * Change the order of this node in its parent's children list so that it
+	 * will draw before the given sibling node.
+	 * 
+	 * @param sibling
+	 *            sibling in front of which this nodes should be moved.
+	 */
+	public void moveInFrontOf(final PNode sibling) {
+		final PNode p = parent;
+		if (p != null && p == sibling.getParent()) {
+			p.removeChild(this);
+			final int index = p.indexOfChild(sibling);
+			p.addChild(index + 1, this);
+		}
+	}
 
-    /**
-     * Return the parent of this node. This will be null if this node has not
-     * been added to a parent yet.
-     * 
-     * @return this nodes parent or null
-     */
-    public PNode getParent() {
-        return parent;
-    }
+	/**
+	 * Return the parent of this node. This will be null if this node has not
+	 * been added to a parent yet.
+	 * 
+	 * @return this nodes parent or null
+	 */
+	public PNode getParent() {
+		return parent;
+	}
 
-    /**
-     * Set the parent of this node. Note this is set automatically when adding
-     * and removing children.
-     * 
-     * @param newParent the parent to which this node should be added
-     */
-    public void setParent(final PNode newParent) {
-        final PNode old = parent;
-        parent = newParent;
-        firePropertyChange(PROPERTY_CODE_PARENT, PROPERTY_PARENT, old, parent);
-    }
+	/**
+	 * Set the parent of this node. Note this is set automatically when adding
+	 * and removing children.
+	 * 
+	 * @param newParent
+	 *            the parent to which this node should be added
+	 */
+	public void setParent(final PNode newParent) {
+		final PNode old = parent;
+		parent = newParent;
+		firePropertyChange(PROPERTY_CODE_PARENT, PROPERTY_PARENT, old, parent);
+	}
 
-    /**
-     * Return the index where the given child is stored.
-     * 
-     * @param child child so search for
-     * @return index of child or -1 if not found
-     */
-    public int indexOfChild(final PNode child) {
-        if (children == null) {
-            return -1;
-        }
-        return children.indexOf(child);
-    }
+	/**
+	 * Return the index where the given child is stored.
+	 * 
+	 * @param child
+	 *            child so search for
+	 * @return index of child or -1 if not found
+	 */
+	public int indexOfChild(final PNode child) {
+		if (children == null) {
+			return -1;
+		}
+		return children.indexOf(child);
+	}
 
-    /**
-     * Remove the given child from this node's children list. Any subsequent
-     * children are shifted to the left (one is subtracted from their indices).
-     * The removed child's parent is set to null.
-     * 
-     * @param child the child to remove
-     * @return the removed child
-     */
-    public PNode removeChild(final PNode child) {
-        final int index = indexOfChild(child);
-        if (index == -1) {
-            return null;
-        }
-        return removeChild(index);
-    }
+	/**
+	 * Remove the given child from this node's children list. Any subsequent
+	 * children are shifted to the left (one is subtracted from their indices).
+	 * The removed child's parent is set to null.
+	 * 
+	 * @param child
+	 *            the child to remove
+	 * @return the removed child
+	 */
+	public PNode removeChild(final PNode child) {
+		final int index = indexOfChild(child);
+		if (index == -1) {
+			return null;
+		}
+		return removeChild(index);
+	}
 
-    /**
-     * Remove the child at the specified position of this group node's children.
-     * Any subsequent children are shifted to the left (one is subtracted from
-     * their indices). The removed child's parent is set to null.
-     * 
-     * @param index the index of the child to remove
-     * @return the removed child
-     */
-    public PNode removeChild(final int index) {
-        if (children == null) {
-            return null;
-        }
-        final PNode child = (PNode) children.remove(index);
+	/**
+	 * Remove the child at the specified position of this group node's children.
+	 * Any subsequent children are shifted to the left (one is subtracted from
+	 * their indices). The removed child's parent is set to null.
+	 * 
+	 * @param index
+	 *            the index of the child to remove
+	 * @return the removed child
+	 */
+	public PNode removeChild(final int index) {
+		if (children == null) {
+			return null;
+		}
+		final PNode child = (PNode) children.remove(index);
 
-        if (children.size() == 0) {
-            children = null;
-        }
+		if (children.size() == 0) {
+			children = null;
+		}
 
-        child.repaint();
-        child.setParent(null);
-        invalidateFullBounds();
+		child.repaint();
+		child.setParent(null);
+		invalidateFullBounds();
 
-        firePropertyChange(PROPERTY_CODE_CHILDREN, PROPERTY_CHILDREN, null, children);
+		firePropertyChange(PROPERTY_CODE_CHILDREN, PROPERTY_CHILDREN, null,
+				children);
 
-        return child;
-    }
+		return child;
+	}
 
-    /**
-     * Remove all the children in the given collection from this node's list of
-     * children. All removed nodes will have their parent set to null.
-     * 
-     * @param childrenNodes the collection of children to remove
-     */
-    public void removeChildren(final Collection childrenNodes) {
-        final Iterator i = childrenNodes.iterator();
-        while (i.hasNext()) {
-            final PNode each = (PNode) i.next();
-            removeChild(each);
-        }
-    }
+	/**
+	 * Remove all the children in the given collection from this node's list of
+	 * children. All removed nodes will have their parent set to null.
+	 * 
+	 * @param childrenNodes
+	 *            the collection of children to remove
+	 */
+	public void removeChildren(final Collection childrenNodes) {
+		final Iterator i = childrenNodes.iterator();
+		while (i.hasNext()) {
+			final PNode each = (PNode) i.next();
+			removeChild(each);
+		}
+	}
 
-    /**
-     * Remove all the children from this node. Node this method is more
-     * efficient then removing each child individually.
-     */
-    public void removeAllChildren() {
-        if (children != null) {
-            final int count = children.size();
-            for (int i = 0; i < count; i++) {
-                final PNode each = (PNode) children.get(i);
-                each.setParent(null);
-            }
-            children = null;
-            invalidatePaint();
-            invalidateFullBounds();
+	/**
+	 * Remove all the children from this node. Node this method is more
+	 * efficient then removing each child individually.
+	 */
+	public void removeAllChildren() {
+		if (children != null) {
+			final int count = children.size();
+			for (int i = 0; i < count; i++) {
+				final PNode each = (PNode) children.get(i);
+				each.setParent(null);
+			}
+			children = null;
+			invalidatePaint();
+			invalidateFullBounds();
 
-            firePropertyChange(PROPERTY_CODE_CHILDREN, PROPERTY_CHILDREN, null, children);
-        }
-    }
+			firePropertyChange(PROPERTY_CODE_CHILDREN, PROPERTY_CHILDREN, null,
+					children);
+		}
+	}
 
-    /**
-     * Delete this node by removing it from its parent's list of children.
-     */
-    public void removeFromParent() {
-        if (parent != null) {
-            parent.removeChild(this);
-        }
-    }
+	/**
+	 * Delete this node by removing it from its parent's list of children.
+	 */
+	public void removeFromParent() {
+		if (parent != null) {
+			parent.removeChild(this);
+		}
+	}
 
-    /**
-     * Set the parent of this node, and transform the node in such a way that it
-     * doesn't move in global coordinates.
-     * 
-     * @param newParent The new parent of this node.
-     */
-    public void reparent(final PNode newParent) {
-        final AffineTransform originalTransform = getLocalToGlobalTransform(null);
-        final AffineTransform newTransform = newParent.getGlobalToLocalTransform(null);
-        newTransform.concatenate(originalTransform);
+	/**
+	 * Set the parent of this node, and transform the node in such a way that it
+	 * doesn't move in global coordinates.
+	 * 
+	 * @param newParent
+	 *            The new parent of this node.
+	 */
+	public void reparent(final PNode newParent) {
+		final AffineTransform originalTransform = getLocalToGlobalTransform(null);
+		final AffineTransform newTransform = newParent
+				.getGlobalToLocalTransform(null);
+		newTransform.concatenate(originalTransform);
 
-        removeFromParent();
-        setTransform(newTransform);
-        newParent.addChild(this);
-        computeFullBounds(fullBoundsCache);
-    }
+		removeFromParent();
+		setTransform(newTransform);
+		newParent.addChild(this);
+		computeFullBounds(fullBoundsCache);
+	}
 
-    /**
-     * Swaps this node out of the scene graph tree, and replaces it with the
-     * specified replacement node. This node is left dangling, and it is up to
-     * the caller to manage it. The replacement node will be added to this
-     * node's parent in the same position as this was. That is, if this was the
-     * 3rd child of its parent, then after calling replaceWith(), the
-     * replacement node will also be the 3rd child of its parent. If this node
-     * has no parent when replace is called, then nothing will be done at all.
-     * 
-     * @param replacementNode the new node that replaces the current node in the
-     *            scene graph tree.
-     */
-    public void replaceWith(final PNode replacementNode) {
-        if (parent != null) {
-            final PNode p = parent;
-            final int index = p.getChildrenReference().indexOf(this);
-            p.removeChild(this);
-            p.addChild(index, replacementNode);
-        }
-    }
+	/**
+	 * Swaps this node out of the scene graph tree, and replaces it with the
+	 * specified replacement node. This node is left dangling, and it is up to
+	 * the caller to manage it. The replacement node will be added to this
+	 * node's parent in the same position as this was. That is, if this was the
+	 * 3rd child of its parent, then after calling replaceWith(), the
+	 * replacement node will also be the 3rd child of its parent. If this node
+	 * has no parent when replace is called, then nothing will be done at all.
+	 * 
+	 * @param replacementNode
+	 *            the new node that replaces the current node in the scene graph
+	 *            tree.
+	 */
+	public void replaceWith(final PNode replacementNode) {
+		if (parent != null) {
+			final PNode p = parent;
+			final int index = p.getChildrenReference().indexOf(this);
+			p.removeChild(this);
+			p.addChild(index, replacementNode);
+		}
+	}
 
-    /**
-     * Sets the name of this null, may be null.
-     * 
-     * @since 1.3
-     * @param name new name for this node
-     */
-    public void setName(final String name) {
-        this.name = name;
-    }
+	/**
+	 * Sets the name of this null, may be null.
+	 * 
+	 * @since 1.3
+	 * @param name
+	 *            new name for this node
+	 */
+	public void setName(final String name) {
+		this.name = name;
+	}
 
-    /**
-     * Returns the name given to this node.
-     * 
-     * @since 1.3
-     * @return name given to this node, may be null
-     */
-    public String getName() {
-        return name;
-    }
+	/**
+	 * Returns the name given to this node.
+	 * 
+	 * @since 1.3
+	 * @return name given to this node, may be null
+	 */
+	public String getName() {
+		return name;
+	}
 
-    /**
-     * Return the number of children that this node has.
-     * 
-     * @return the number of children
-     */
-    public int getChildrenCount() {
-        if (children == null) {
-            return 0;
-        }
-        return children.size();
-    }
+	/**
+	 * Return the number of children that this node has.
+	 * 
+	 * @return the number of children
+	 */
+	public int getChildrenCount() {
+		if (children == null) {
+			return 0;
+		}
+		return children.size();
+	}
 
-    /**
-     * Return the child node at the specified index.
-     * 
-     * @param index a child index
-     * @return the child node at the specified index
-     */
-    public PNode getChild(final int index) {
-        return (PNode) children.get(index);
-    }
+	/**
+	 * Return the child node at the specified index.
+	 * 
+	 * @param index
+	 *            a child index
+	 * @return the child node at the specified index
+	 */
+	public PNode getChild(final int index) {
+		return (PNode) children.get(index);
+	}
 
-    /**
-     * Return a reference to the list used to manage this node's children. This
-     * list should not be modified.
-     * 
-     * @return reference to the children list
-     */
-    public List getChildrenReference() {
-        if (children == null) {
-            children = new ArrayList();
-        }
-        return children;
-    }
+	/**
+	 * Return a reference to the list used to manage this node's children. This
+	 * list should not be modified.
+	 * 
+	 * @return reference to the children list
+	 */
+	public List getChildrenReference() {
+		if (children == null) {
+			children = new ArrayList();
+		}
+		return children;
+	}
 
-    /**
-     * Return an iterator over this node's direct descendant children.
-     * 
-     * @return iterator over this nodes children
-     */
-    public ListIterator getChildrenIterator() {
-        if (children == null) {
-            return Collections.EMPTY_LIST.listIterator();
-        }
-        return Collections.unmodifiableList(children).listIterator();
-    }
+	/**
+	 * Return an iterator over this node's direct descendant children.
+	 * 
+	 * @return iterator over this nodes children
+	 */
+	public ListIterator getChildrenIterator() {
+		if (children == null) {
+			return Collections.EMPTY_LIST.listIterator();
+		}
+		return Collections.unmodifiableList(children).listIterator();
+	}
 
-    /**
-     * Return the root node (instance of PRoot). If this node does not descend
-     * from a PRoot then null will be returned.
-     * 
-     * @return root element of this node, or null if this node does not descend
-     *         from a PRoot
-     */
-    public PRoot getRoot() {
-        if (parent != null) {
-            return parent.getRoot();
-        }
-        return null;
-    }
+	/**
+	 * Return the root node (instance of PRoot). If this node does not descend
+	 * from a PRoot then null will be returned.
+	 * 
+	 * @return root element of this node, or null if this node does not descend
+	 *         from a PRoot
+	 */
+	public PRoot getRoot() {
+		if (parent != null) {
+			return parent.getRoot();
+		}
+		return null;
+	}
 
-    /**
-     * Return a collection containing this node and all of its descendant nodes.
-     * 
-     * @return a new collection containing this node and all descendants
-     */
-    public Collection getAllNodes() {
-        return getAllNodes(null, null);
-    }
+	/**
+	 * Return a collection containing this node and all of its descendant nodes.
+	 * 
+	 * @return a new collection containing this node and all descendants
+	 */
+	public Collection getAllNodes() {
+		return getAllNodes(null, null);
+	}
 
-    /**
-     * Return a collection containing the subset of this node and all of its
-     * descendant nodes that are accepted by the given node filter. If the
-     * filter is null then all nodes will be accepted. If the results parameter
-     * is not null then it will be used to collect this subset instead of
-     * creating a new collection.
-     * 
-     * @param filter the filter used to determine the subset
-     * @param resultantNodes where matching nodes should be added
-     * @return a collection containing this node and all descendants
-     */
-    public Collection getAllNodes(final PNodeFilter filter, final Collection resultantNodes) {
-        Collection results;
-        if (resultantNodes == null) {
-            results = new ArrayList();
-        }
-        else {
-            results = resultantNodes;
-        }
+	/**
+	 * Return a collection containing the subset of this node and all of its
+	 * descendant nodes that are accepted by the given node filter. If the
+	 * filter is null then all nodes will be accepted. If the results parameter
+	 * is not null then it will be used to collect this subset instead of
+	 * creating a new collection.
+	 * 
+	 * @param filter
+	 *            the filter used to determine the subset
+	 * @param resultantNodes
+	 *            where matching nodes should be added
+	 * @return a collection containing this node and all descendants
+	 */
+	public Collection getAllNodes(final PNodeFilter filter,
+			final Collection resultantNodes) {
+		Collection results;
+		if (resultantNodes == null) {
+			results = new ArrayList();
+		} else {
+			results = resultantNodes;
+		}
 
-        if (filter == null || filter.accept(this)) {
-            results.add(this);
-        }
+		if (filter == null || filter.accept(this)) {
+			results.add(this);
+		}
 
-        if (filter == null || filter.acceptChildrenOf(this)) {
-            final int count = getChildrenCount();
-            for (int i = 0; i < count; i++) {
-                final PNode each = (PNode) children.get(i);
-                each.getAllNodes(filter, results);
-            }
-        }
+		if (filter == null || filter.acceptChildrenOf(this)) {
+			final int count = getChildrenCount();
+			for (int i = 0; i < count; i++) {
+				final PNode each = (PNode) children.get(i);
+				each.getAllNodes(filter, results);
+			}
+		}
 
-        return results;
-    }
+		return results;
+	}
 
-    // ****************************************************************
-    // Serialization - Nodes conditionally serialize their parent.
-    // This means that only the parents that were unconditionally
-    // (using writeObject) serialized by someone else will be restored
-    // when the node is unserialized.
-    // ****************************************************************
+	// ****************************************************************
+	// Serialization - Nodes conditionally serialize their parent.
+	// This means that only the parents that were unconditionally
+	// (using writeObject) serialized by someone else will be restored
+	// when the node is unserialized.
+	// ****************************************************************
 
-    /**
-     * Write this node and all of its descendant nodes to the given outputsteam.
-     * This stream must be an instance of PObjectOutputStream or serialization
-     * will fail. This nodes parent is written out conditionally, that is it
-     * will only be written out if someone else writes it out unconditionally.
-     * 
-     * @param out the output stream to write to, must be an instance of
-     *            PObjectOutputStream
-     * @throws IOException when an error occurs speaking to underlying
-     *             ObjectOutputStream
-     */
-    private void writeObject(final ObjectOutputStream out) throws IOException {
-        if (!(out instanceof PObjectOutputStream)) {
-            throw new IllegalArgumentException("PNode.writeObject may only be used with PObjectOutputStreams");
-        }
-        out.defaultWriteObject();
-        ((PObjectOutputStream) out).writeConditionalObject(parent);
-    }
+	/**
+	 * Write this node and all of its descendant nodes to the given outputsteam.
+	 * This stream must be an instance of PObjectOutputStream or serialization
+	 * will fail. This nodes parent is written out conditionally, that is it
+	 * will only be written out if someone else writes it out unconditionally.
+	 * 
+	 * @param out
+	 *            the output stream to write to, must be an instance of
+	 *            PObjectOutputStream
+	 * @throws IOException
+	 *             when an error occurs speaking to underlying
+	 *             ObjectOutputStream
+	 */
+	private void writeObject(final ObjectOutputStream out) throws IOException {
+		if (!(out instanceof PObjectOutputStream)) {
+			throw new IllegalArgumentException(
+					"PNode.writeObject may only be used with PObjectOutputStreams");
+		}
+		out.defaultWriteObject();
+		((PObjectOutputStream) out).writeConditionalObject(parent);
+	}
 
-    /**
-     * Read this node and all of its descendants in from the given input stream.
-     * 
-     * @param in the stream to read from
-     * 
-     * @throws IOException when an error occurs speaking to underlying
-     *             ObjectOutputStream
-     * @throws ClassNotFoundException when a class is deserialized that no
-     *             longer exists. This can happen if it's renamed or deleted.
-     */
-    private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
-        in.defaultReadObject();
-        parent = (PNode) in.readObject();
-    }
+	/**
+	 * Read this node and all of its descendants in from the given input stream.
+	 * 
+	 * @param in
+	 *            the stream to read from
+	 * 
+	 * @throws IOException
+	 *             when an error occurs speaking to underlying
+	 *             ObjectOutputStream
+	 * @throws ClassNotFoundException
+	 *             when a class is deserialized that no longer exists. This can
+	 *             happen if it's renamed or deleted.
+	 */
+	private void readObject(final ObjectInputStream in) throws IOException,
+			ClassNotFoundException {
+		in.defaultReadObject();
+		parent = (PNode) in.readObject();
+	}
 
-    /**
-     * @deprecated see http://code.google.com/p/piccolo2d/issues/detail?id=99
-     * 
-     * @return a string representation of this node's state
-     */
-    protected String paramString() {
-        return "";
-    }
+	/**
+	 * @deprecated see http://code.google.com/p/piccolo2d/issues/detail?id=99
+	 * 
+	 * @return a string representation of this node's state
+	 */
+	protected String paramString() {
+		return "";
+	}
 
-    /**
-     * Returns an array of input event listeners that are attached to this node.
-     * 
-     * @since 1.3
-     * @return event listeners attached to this node
-     */
-    public PInputEventListener[] getInputEventListeners() {
-        if (listenerList == null || listenerList.getListenerCount() == 0) {
-            return new PInputEventListener[] {};
-        }
+	/**
+	 * Returns an array of input event listeners that are attached to this node.
+	 * 
+	 * @since 1.3
+	 * @return event listeners attached to this node
+	 */
+	public PInputEventListener[] getInputEventListeners() {
+		if (listenerList == null || listenerList.getListenerCount() == 0) {
+			return new PInputEventListener[] {};
+		}
 
-        final EventListener[] listeners = listenerList.getListeners(PInputEventListener.class);
+		final EventListener[] listeners = listenerList
+				.getListeners(PInputEventListener.class);
 
-        final PInputEventListener[] result = new PInputEventListener[listeners.length];
-        for (int i = 0; i < listeners.length; i++) {
-            result[i] = (PInputEventListener) listeners[i];
-        }
-        return result;
-    }
+		final PInputEventListener[] result = new PInputEventListener[listeners.length];
+		for (int i = 0; i < listeners.length; i++) {
+			result[i] = (PInputEventListener) listeners[i];
+		}
+		return result;
+	}
 
-    private static final class ClientPropertyKeyIterator implements Iterator {
-        private final Enumeration enumeration;
+	private static final class ClientPropertyKeyIterator implements Iterator {
+		private final Enumeration enumeration;
 
-        private ClientPropertyKeyIterator(final Enumeration enumeration) {
-            this.enumeration = enumeration;
-        }
+		private ClientPropertyKeyIterator(final Enumeration enumeration) {
+			this.enumeration = enumeration;
+		}
 
-        public boolean hasNext() {
-            return enumeration.hasMoreElements();
-        }
+		public boolean hasNext() {
+			return enumeration.hasMoreElements();
+		}
 
-        public Object next() {
-            return enumeration.nextElement();
-        }
+		public Object next() {
+			return enumeration.nextElement();
+		}
 
-        public void remove() {
-            throw new UnsupportedOperationException();
-        }
-    }
+		public void remove() {
+			throw new UnsupportedOperationException();
+		}
+	}
 
-    /**
-     * PSceneGraphDelegate is an interface to receive low level node
-     * events. It together with PNode.SCENE_GRAPH_DELEGATE gives Piccolo2d users
-     * an efficient way to learn about low level changes in Piccolo's scene
-     * graph. Most users will not need to use this.
-     */
-    public interface PSceneGraphDelegate {
-        /**
-         * Called to notify delegate that the node needs repainting.
-         * 
-         * @param node node needing repaint
-         */
-        void nodePaintInvalidated(PNode node);
+	/**
+	 * PSceneGraphDelegate is an interface to receive low level node
+	 * events. It together with PNode.SCENE_GRAPH_DELEGATE gives Piccolo2d users
+	 * an efficient way to learn about low level changes in Piccolo's scene
+	 * graph. Most users will not need to use this.
+	 */
+	public interface PSceneGraphDelegate {
+		/**
+		 * Called to notify delegate that the node needs repainting.
+		 * 
+		 * @param node
+		 *            node needing repaint
+		 */
+		void nodePaintInvalidated(PNode node);
 
-        /**
-         * Called to notify delegate that the node and all it's children need
-         * repainting.
-         * 
-         * @param node node needing repaint
-         */
-        void nodeFullBoundsInvalidated(PNode node);
-    }
+		/**
+		 * Called to notify delegate that the node and all it's children need
+		 * repainting.
+		 * 
+		 * @param node
+		 *            node needing repaint
+		 */
+		void nodeFullBoundsInvalidated(PNode node);
+	}
 }