Revision: 963
Author: allain.lalonde
Date: Mon Feb  1 11:30:02 2010
Log: Fixing error with rounding error bug when calculating inverseTransform repeatedly during globalToLocal.

Fixes Issue 159
http://code.google.com/p/piccolo2d/source/detail?r=963

Modified:
 /piccolo2d.java/trunk/core/src/main/java/edu/umd/cs/piccolo/PNode.java

=======================================
--- /piccolo2d.java/trunk/core/src/main/java/edu/umd/cs/piccolo/PNode.java Mon Jan 18 16:07:38 2010 +++ /piccolo2d.java/trunk/core/src/main/java/edu/umd/cs/piccolo/PNode.java Mon Feb 1 11:30:02 2010
@@ -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;
-
-    /**
-     * 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 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 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 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 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 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 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 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 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 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 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;
-
-    /** 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;
-
-    /** Tracks the parent of this node, may be null. */
-    private transient PNode parent;
-
-    /** Tracks all immediate child nodes. */
-    private List children;
-
-    /** Bounds of the PNode. */
-    private final PBounds bounds;
-
-    /** 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;
-
-    /**
-     * How Opaque this node should be 1f = fully opaque, 0f = completely
-     * transparent.
-     */
-    private float transparency;
-
-    /** 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;
-
-    /**
- * 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;
-
-    /** List of event listeners. */
-    private transient EventListenerList listenerList;
-
-    /** 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 this node will be rendered. */
-    private boolean visible;
-
-    private boolean childBoundsVolatile;
-
-    /** Whether this node needs to be repainted. */
-    private boolean paintInvalid;
-
-    /** 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 full bounds need to be recomputed. */
-    private boolean fullBoundsInvalid;
-
-    /** Whether this node's child bounds need to be recomputed. */
-    private boolean childBoundsInvalid;
-
-    private boolean occluded;
-
-    /** 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 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;
-
-    /**
-     * 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.
-     * <P>
- * 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.
-    // ****************************************************************
-
-    /**
- * 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 PInterpolatingActivity interpolatingActivity = new PInterpolatingActivity(duration,
-                PUtil.DEFAULT_ACTIVITY_STEP_RATE) {
-            private PBounds src;
-
-            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));
-            }
-
-            protected void activityFinished() {
-                super.activityFinished();
-                endResizeBounds();
-            }
-        };
-
-        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'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);
-                }
-
-                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;
-        }
-    }
-
-    /**
-     * 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);
-                }
-            };
-
- 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;
-
- final PInterpolatingActivity ta = new PInterpolatingActivity(duration, PUtil.DEFAULT_ACTIVITY_STEP_RATE) {
-                private float source;
-
-                protected void activityStarted() {
-                    source = getTransparency();
-                    super.activityStarted();
-                }
-
-                public void setRelativeTargetValue(final float zeroToOne) {
- PNode.this.setTransparency(source + zeroToOne * (dest - source));
-                }
-            };
-
-            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;
-    }
-
-    // ****************************************************************
-    // 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;
-    }
-
-    /**
- * Returns the value of the client attribute with the specified key. Only - * attributes added with <code>addAttribute</code> 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.
-     * <p>
-     * The <code>get/add attribute</code> 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.
-     * <p>
-     * 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);
-
-        if (value != oldValue) {
-            if (clientProperties == null) {
-                clientProperties = new SimpleAttributeSet();
-            }
-
-            if (value == null) {
-                clientProperties.removeAttribute(key);
-            }
-            else {
-                clientProperties.addAttribute(key, value);
-            }
-
- 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);
-        }
-    }
-
-    /**
-     * 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
-
-    /**
- * 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;
-    }
-
-    /**
-     * 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();
-    }
-
-    /**
-     * 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();
-    }
-
-    /**
-     * 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();
-    }
-
-    /**
-     * @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 getClientPropertyKeysEnumerator() instead.
-     *
-     * @return iterator for client property keys
-     */
-    public Iterator getClientPropertyKeysIterator() {
-        final Enumeration enumeration = getClientPropertyKeysEnumeration();
-
-        return new ClientPropertyKeyIterator(enumeration);
-    }
-
-    // ****************************************************************
-    // 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;
-        }
-    }
-
-    // ****************************************************************
-    // 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 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 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);
-    }
-
-    /**
- * 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 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 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) {
-        if (parent != null) {
-            parent.globalToLocal(globalPoint);
-        }
-        return parentToLocal(globalPoint);
-    }
-
-    /**
-     * Transform the given dimension from global coordinates to this node's
-     * local coordinate system. Note that this will modify the dimension
-     * parameter.
-     *
***The diff for this file has been truncated for email.***

--
Piccolo2D Developers Group: http://groups.google.com/group/piccolo2d-dev?hl=en

Reply via email to