/*
 * @(#)Paintable.java    2.6.0   7 June 2007
 *
 * Copyright 2007
 * College of Computer and Information Science
 * Northeastern University
 * Boston, MA  02115
 *
 * The Java Power Tools software may be used for educational
 * purposes as long as this copyright notice is retained intact
 * at the top of all source files.
 *
 * To discuss possible commercial use of this software, 
 * contact Richard Rasala at Northeastern University, 
 * College of Computer and Information Science,
 * 617-373-2462 or rasala@ccs.neu.edu.
 *
 * The Java Power Tools software has been designed and built
 * in collaboration with Viera Proulx and Jeff Raab.
 *
 * Should this software be modified, the words "Modified from 
 * Original" must be included as a comment below this notice.
 *
 * All ation rights are retained.  This software or its 
 * documentation may not be published in any media either
 * in whole or in part without explicit permission.
 *
 * This software was created with support from Northeastern 
 * University and from NSF grant DUE-9950829.
 */

package edu.neu.ccs.gui;

import edu.neu.ccs.*;
import edu.neu.ccs.util.*;

import java.awt.*;
import java.awt.geom.*;
import java.awt.image.BufferedImage;

/**
 * <p><code>Paintable</code> describes an object that can paint onto a
 * graphics context.</p>
 *
 * <p>As of 2.4.0, the former interface <code>MutatablePaintable</code> has
 * been merged into <code>Paintable</code>.  Furthermore, the interface
 * <code>MutatablePaintable</code> has been removed from the Java Power
 * Tools as has the class <CODE>AbstractMutatablePaintable</CODE>.</p>
 *
 * <p>Much programming experience proved that splitting the design into two
 * interfaces and two abstract classes was more hassle than it was worth.
 * Although splittling the design into two classes was conceptually simple,
 * it made programming much more difficult since the necessary facilities
 * were not all available everywhere.</p>
 *
 * <p>The new <code>Paintable</code> interface also includes methods that
 * have proven to be useful but which required explicit coding in earlier
 * versions of JPT.  These methods are now available automatically in the
 * base class <code>AbstractPaintable</code>.</p>
 *
 * <p>In fact, all but three of the methods specified in this interface have
 * default definitions in <code>AbstractPaintable</code>.  The three abstract
 * methods in that class are:</p>
 *
 * <ul>
 *   <li><code>public void originalPaint(Graphics g)</code></li>
 *   <li><code>public XRect getActualBounds2D()</code></li>
 *   <li><code>public boolean originalContains(double x, double y)</code></li>
 * </ul>
 *
 * <p>Therefore, it is relatively easy to create a <code>Paintable</code> in
 * a direct manner by extending <code>AbstractPaintable</code>.  However, it
 * is even easier to use the existing JPT <code>Paintable</code> classes to
 * handle shapes, images, and text directly, and to create composites of
 * simpler paintables via <code>PaintableSequence</code>.</p>
 *
 * <p>As of 2.4.0, the interface <code>Paintable</code> extends the interface
 * <code>SupportsPropertyChange</code>.  This makes explicit a relationship
 * that was true <i>de facto</i> in earlier releases of JPT since the class
 * <code>AbstractPaintable</code> has always implemented
 * <code>SupportsPropertyChange</code>.</p>
 *
 * <p>In 2.6.0, the notion of a <i>background paint</i> was refactored from
 * <code>Tile</code> into required &ldquo;set&rdquo; and &ldquo;get&rdquo;
 * methods in this interface and corresponding implementation in the base
 * class <code>AbstractPaintable</code>.</p>
 *
 * <p>Also, in 2.6.0, support was added to use a paintable as
 * a tile for a rectangle.  Once this facility was in place, we added the
 * option for one paintable to use another paintable as a
 * <i>background tile</i> that will paint the bounding box of the primary
 * paintable before that paintable itself paints.</p>
 * 
 * <p>The order of painting should now be:</p>
 * 
 * <ul>
 *   <li>Paint the <i>background paint</i> if any.</li>
 *   <li>Tile with the <i>background tile</i> if any.</li>
 *   <li>Paint the primary content of this paintable.</li>
 * </ul>
 * 
 * <p>Of course, no painting takes place if the paintable is set to be
 * invisible.</p>
 *
 * <p>Finally, in 2.6.0, as a convenience, <code>Paintable</code> also extends
 * the interface of constants <code>JPTConstants</code>.</p>
 * 
 * <p>In 2.6.0c, added the method <code>makeSnapshot</code>.</p>
 * 
 * @author  Richard Rasala
 * @version 2.6.0c
 * @since   2.3
 * @see     AbstractPaintable
 * @see     SupportsPropertyChange
 * @see     JPTConstants
 */
 public interface Paintable
     extends SupportsPropertyChange, JPTConstants
 {

    /** Bound property name for set default bounds2D. */
    public static final String SET_DEFAULT_BOUNDS2D = "set.default.bounds2d";
    
    /** Bound property name for set default center. */
    public static final String SET_DEFAULT_CENTER = "set.default.center";
    
    /** Bound property name for set default original bounds2D. */
    public static final String SET_DEFAULT_ORIGINAL_BOUNDS2D =
        "set.default.original.bounds2d";
    
    /** Bound property name for set default originalcenter. */
    public static final String SET_DEFAULT_ORIGINAL_CENTER =
        "set.default.original.center";
    
    
    /** Bound property name for set visible. */
    public static final String SET_VISIBLE = "set.visible";
    
    /** Bound property name for set opacity. */
    public static final String SET_OPACITY = "set.opacity";
    
    /** Bound property name for set mutator. */
    public static final String SET_MUTATOR = "set.mutator";
    
    /** Bound property name for set paintables. */
    public static final String SET_PAINTABLE = "set.paintable";
    
    /** Bound property name to remove paintables. */
    public static final String REMOVE_PAINTABLE = "remove.paintable";
    
    /** Bound property name to shift paintables within a sequence. */
    public static final String SHIFT_PAINTABLE = "shift.paintable";
    
    /** Bound property name for set clipping shape. */
    public static final String SET_CLIPPING_SHAPE = "set.clipping.shape";
    
    
    
    /**
     * <P>Paints onto a <CODE>Graphics</CODE> context using information
     * from this object.</P>
     *
     * <p>A recommended implementation should adopt the following
     * policy:</p>
     *
     * <ul>
     *   <li>Do nothing if the graphics context is <code>null</code>
     *       or the paintable is set to be invisible.</li>
     *   <li>Use a copy of the graphics context so the original
     *       context will not be changed.</li>
     *   <li>Clip the paint area to the bounds region that is
     *       returned by the method <code>getBounds2D</code>.</li>
     *   <li>Turn anti-aliasing on.</li>
     *   <li>Apply the current opacity setting.</li>
     *   <li>Paint the <i>background paint</i> if any.</li>
     *   <li>Tile with the <i>background tile</i> if any.</li>
     *   <li>Apply the current mutator to the graphics context.</li>
     *   <li>Call the method <code>originalPaint</code> to
     *       complete the actual paint operations.</li>
     * </ul>
     *
     * <P>Whatever the implementation, when this method call is complete,
     * the internal state of g should be unchanged.</P>
     * 
     * @param g the graphics context on which to paint
     */
    void paint(Graphics g);
    
    
    /**
     * <p>Without changing the paintable or the graphics context, paint
     * the paintable in a translated position specified by the point in
     * coordinates.</p>
     *
     * <p>In particular, <code>paintAt(g,0,0)</code> should be equivalent
     * to <code>paint(g)</code>.</p>
     *
     * <p><i>Recommendation:</i> The <code>paintAt</code> methods are
     * intended to be used if a designer wants to define a paintable at
     * or near the origin of coordinates and then independently compute
     * or retrieve the position at which the paintable will be painted.
     * If the <code>paintAt</code> methods are used, it is recommended
     * that the programmer avoid mutating the paintable directly since
     * that will almost certainly lead to confusion and bugs.  Either
     * use mutation or use <code>paintAt</code> but not both.</p>
     *
     * @param g the graphics context on which to paint
     * @param x the x-translation
     * @param y the y-translation
     */
    void paintAt(Graphics g, double x, double y);
    
    
    /**
     * <p>Without changing the paintable or the graphics context, paint
     * the paintable in a translated position specified by the point.</p>
     *
     * <p><i>Recommendation:</i> The <code>paintAt</code> methods are
     * intended to be used if a designer wants to define a paintable at
     * or near the origin of coordinates and then independently compute
     * or retrieve the position at which the paintable will be painted.
     * If the <code>paintAt</code> methods are used, it is recommended
     * that the programmer avoid mutating the paintable directly since
     * that will almost certainly lead to confusion and bugs.  Either
     * use mutation or use <code>paintAt</code> but not both.</p>
     *
     * @param g the graphics context on which to paint
     * @param p the translation vector
     */
    void paintAt(Graphics g, Point2D p);
    
    
    /**
     * <p>Without changing the paintable or the graphics context, paint
     * the paintable in a translated position specified by the point in
     * coordinates and the affine transform T; before painting the
     * transform T should be applied to the point.</p>
     *
     * <p>The application of this facility is to apply a transform to
     * the position of painting that should be applied to the position
     * alone and NOT to the paintable or to the graphics context.</p>
     *
     * <p>For example, if T is a reflection through a horizontal axis
     * that places the origin (0,0) at the lower left of a panel, then
     * it would probably be a very bad idea to apply the reflection
     * to the graphics context (which turns every object upside down)
     * or to the paintable (which turns the paintable upside down).
     * The transform should be applied to the position alone.</p>
     *
     * <p><i>Recommendation:</i> The <code>paintAt</code> methods are
     * intended to be used if a designer wants to define a paintable at
     * or near the origin of coordinates and then independently compute
     * or retrieve the position at which the paintable will be painted.
     * If the <code>paintAt</code> methods are used, it is recommended
     * that the programmer avoid mutating the paintable directly since
     * that will almost certainly lead to confusion and bugs.  Either
     * use mutation or use <code>paintAt</code> but not both.</p>
     *
     * @param g the graphics context on which to paint
     * @param T the affine transform to apply to the translation point
     * @param x the original x-translation before transformation
     * @param y the original y-translation before transformation
     */
    void paintAt(Graphics g, AffineTransform T, double x, double y);
    
    
    /**
     * <p>Without changing the paintable or the graphics context, paint
     * the paintable in a translated position specified by the point in
     * coordinates and the affine transform T; before painting the
     * transform T should be applied to the point.</p>
     *
     * <p>The application of this facility is to apply a transform to
     * the position of painting that should be applied to the position
     * alone and NOT to the paintable or to the graphics context.</p>
     *
     * <p>For example, if T is a reflection through a horizontal axis
     * that places the origin (0,0) at the lower left of a panel, then
     * it would probably be a very bad idea to apply the reflection
     * to the graphics context (which turns every object upside down)
     * or to the paintable (which turns the paintable upside down).
     * The transform should be applied to the position alone.</p>
     *
     * <p><i>Recommendation:</i> The <code>paintAt</code> methods are
     * intended to be used if a designer wants to define a paintable at
     * or near the origin of coordinates and then independently compute
     * or retrieve the position at which the paintable will be painted.
     * If the <code>paintAt</code> methods are used, it is recommended
     * that the programmer avoid mutating the paintable directly since
     * that will almost certainly lead to confusion and bugs.  Either
     * use mutation or use <code>paintAt</code> but not both.</p>
     *
     * @param g the graphics context on which to paint
     * @param T the affine transform to apply to the translation point
     * @param p the original translation point before transformation
     */
    void paintAt(Graphics g, AffineTransform T, Point2D p);
    
    
    /**
     * <p>Repeatedly paints this object as a tile that covers the
     * rectangle <code>(x,y,w,h)</code> in the graphics context
     * <code>g</code>.  The painting is clipped to this rectangle.
     * The graphics context is unchanged when this method is done.</p>
     * 
     * <p>This method should work appropriately if the width or height
     * is negative.</p>
     * 
     * <p>The method should do nothing if:</p>
     * 
     * <ul>
     *   <li>The given graphics context is <code>null</code>.</li>
     *   <li>The given width or height is zero.</li>
     *   <li>This paintable has zero width or height.</li>
     *   <li>This paintable is set to be invisible.</li>
     * </ul>
     * 
     * @param g the graphics context
     * @param x the x-corner of the rectangle to tile
     * @param y the y-corner of the rectangle to tile
     * @param w the width  of the rectangle to tile
     * @param h the height of the rectangle to tile
     */
    void paintAsTiles(Graphics g, double x, double y, double w, double h);
    
    
    /**
     * <p>Repeatedly paints this object as a tile that covers the
     * rectangle <code>(0,0,w,h)</code> in the graphics context
     * <code>g</code>.  The painting is clipped to this rectangle.
     * The graphics context is unchanged when this method is done.</p>
     * 
     * <p>This method should work appropriately if the width or height
     * is negative.</p>
     * 
     * <p>The method should do nothing if:</p>
     * 
     * <ul>
     *   <li>The given graphics context is <code>null</code>.</li>
     *   <li>The given width or height is zero.</li>
     *   <li>This paintable has zero width or height.</li>
     *   <li>This paintable is set to be invisible.</li>
     * </ul>
     * 
     * @param g the graphics context
     * @param w the width  of the rectangle to tile
     * @param h the height of the rectangle to tile
     */
    void paintAsTiles(Graphics g, double w, double h);
    
    
    /**
     * <p>Repeatedly paints this object as a tile that covers the
     * given rectangle in the graphics context <code>g</code>.
     * The painting is clipped to this rectangle.
     * The graphics context is unchanged when this method is done.</p>
     * 
     * <p>The method should do nothing if:</p>
     * 
     * <ul>
     *   <li>The given graphics context is <code>null</code>.</li>
     *   <li>The given rectangle is <code>null</code>.</li>
     *   <li>The width or height of the given rectangle is zero.</li>
     *   <li>This paintable has zero width or height.</li>
     *   <li>This paintable is set to be invisible.</li>
     * </ul>
     * 
     * @param g    the graphics context
     * @param rect the rectangle to tile
     */
    void paintAsTiles(Graphics g, Rectangle2D rect);
    
    
    /**
     * <P>Returns a copy of the given graphics context after modifying the copy
     * to clip to within the bounds region, to set anti-aliasing on, and to
     * apply the opacity of this paintable if needed.</P>
     *
     * <P>For convenience, the graphics context should be returned as a
     * <CODE>Graphics2D</CODE> object.</P>
     *
     * <P>It is recommended that this method be used in the implementation of
     * the <code>paint</code> method.</p>
     *
     * @param  g the given graphics context to copy
     * @return a suitably prepared copy of the given graphics context
     */
    Graphics2D getPreparedGraphics2D(Graphics g);
    
    
    /**
     * <p>Constructs a <code>BufferedImage</code> object that is
     * the same size as the bounding box of this paintable and
     * then paints this paintable onto the buffered image with a
     * suitable translation back to the origin.</p>
     * 
     * <p>This method creates a snapshot of the current visual
     * state of this paintable.</p>
     * 
     * <p>The <code>BufferedImage</code> returned will have size at
     * least 1-by-1 even if this paintable has 0 width or height.</p>
     */
    BufferedImage makeSnapshot();
    
    
    /**
     * <P>Returns a copy of the 2-dimensional bounds of the paintable.</P>
     *
     * <p>A recommended implementation should adopt the following
     * policy:</p>
     *
     * <P>If the value of <CODE>getDefaultBounds2D</CODE> is
     * non-<code>null</code>, then return this value.</p>
     *
     * <P>Otherwise, return a reasonable estimate of the bounds
     * within computational constraints.</p>
     *
     * <P>This method must not return <CODE>null</CODE>.</P>
     *
     * @return a copy of the 2-dimensional bounds of the paintable
     */
    XRect getBounds2D();
    
    
    /**
     * <P>Returns a copy of the center of the paintable.</P>
     *
     * <p>A recommended implementation should adopt the following
     * policy:</p>
     *
     * <p>If the value of <code>getDefaultCenter</code> is
     * non-<code>null</code>, then return this value.</p>
     *
     * <P>Otherwise, return a computed value of the center.</P>
     *
     * <P>This method must not return <CODE>null</CODE>.</P>
     *
     * @return a copy the center of the paintable
     */
    XPoint2D getCenter();
    
    
    /**
     * <P>Returns a copy of the corner of the paintable.</P>
     *
     * <p>The corner should be the top-left corner of the bounds
     * rectangle returned by <code>getBounds2D</code>.</P>
     *
     * @return a copy the corner of the paintable
     */
    XPoint2D getCorner();
    
    
    /**
     * <p>Tests if a point specified by coordinates is inside the paintable.</p>
     *
     * @param  x the x-coordinate of the point
     * @param  y the y-coordinate of the point
     * @return whether or not a specified point is inside the paintable
     */
    boolean contains(double x, double y);
    
    
    /**
     * <P>Tests if a specified point is inside the paintable.</P>
     *
     * @param  p a specified point
     * @return whether or not a specified point is inside the paintable
     */
    boolean contains(Point2D p);
    
    
    /**
     * <P>Sets the visibility property of this paintable.</P>
     *
     * <P>The default for the visibility property should be <CODE>true</CODE></P>.
     *
     * <P>Fires property change: SET_VISIBLE.</P>
     * 
     * @param visible the visibility setting
     */
    void setVisible(boolean visible);
    
    
    /**
     * Returns the current visibility property of this paintable.
     */
    boolean isVisible();
    
    
    /**
     * <P>Sets the opacity of this paintable to a value between 0 and 1.</P>
     *
     * <P>Note that an opacity of 0 will make the paintable invisible.  This
     * is not recommended.  Instead use <CODE>setVisible(false)</CODE>.</P>
     *
     * <P>Fires property change: SET_OPACITY.</P>
     * 
     * @param opacity the opacity of this paintable
     */
    void setOpacity(float opacity);
    
    
    /**
     * Returns the opacity value of this paintable between 0 and 1.
     */
    float getOpacity();
    
    
    /**
     * <p>Sets the background paint.</p>
     *
     * <p>The paint may be set to <code>null</code> to
     * eliminate background painting.</p>
     *
     * @param background the background paint
     */
    void setBackgroundPaint(Paint background);
    
    
    /**
     * Returns the background paint.
     *
     * @return the background paint.
     */
    Paint getBackgroundPaint();
    
    
    /**
     * Clear the background paint.
     */
    void clearBackgroundPaint();
    
    
    /**
     * <p>Sets the background tile paintable.  The object passed
     * should be a paintable or be convertible to a paintable
     * via the method <code>ComponentFactory.makePaintable</code>.</p>
     *
     * <p>The object may be set to <code>null</code> to
     * eliminate background tiling.</p>
     *
     * @param object the background tile object
     */
    void setBackgroundTile(Object object);
    
    
    /**
     * Returns the background tile.
     *
     * @return the background tile.
     */
    Paintable getBackgroundTile();
    
    
    /**
     * Clear the background tile.
     */
    void clearBackgroundTile();
    
    
    /**
     * Clear the background paint and the background tile.
     */
    void clearBothBackgrounds();
    
    
    /**
     * <P>Sets the mutator transform to the given transform provided that
     * the given transform is invertible
     * and the paintable object supports this operation.</P>
     *
     * <P>If the given transform is not invertible, the method does nothing.</P>
     *
     * <P>Fires property change: SET_MUTATOR.</P>
     * 
     * <p><i>Remarks:</i></p>
     *
     * <p>If the paintable object maintains a mutator object that transforms
     * the paintable, then this method should set that mutator.  Moreover,
     * in this case, the method <code>getMutator</code> should return a copy
     * of that mutator.</p>
     *
     * <p>If the paintable object distributes mutation to internal data then
     * this method may or may not make sense.  The documentation of the
     * implementation should state what, if anything, is done by this method.
     * In particular, it is valid for the method <code>getMutator</code> to
     * return an identity transform if no mutator is maintained explicitly.</p>
     *
     * @param M the invertible affine transform to set as the mutator
     */
    void setMutator(AffineTransform M);
    
    
    /**
     * <P>Composes the current mutator on the right with the given transform
     * provided that
     * the given transform is invertible
     * and the paintable object supports this operation.</P>
     *
     * <P>If the given transform is not invertible, the method does nothing.</P>
     *
     * <P>Fires property change: SET_MUTATOR.</P>
     * 
     * <p><i>Remarks:</i></p>
     *
     * <P>Normally, the action of the new mutator will be to apply
     * the given transform and then to apply the old mutator.</P>
     *
     * <p>If the paintable object distributes mutation to internal data then
     * this method may or may not make sense.  The documentation of the
     * implementation should state what, if anything, is done by this method.</p>
     *
     * @param M the invertible affine transform to compose
     */
    void addPreMutation(AffineTransform M);
    
    
    
    /**
     * <P>Composes the current mutator on the left with the given transform
     * provided that the given transform is invertible.</P>
     *
     * <P>If the given transform is not invertible, the method does nothing.</P>
     *
     * <P>Fires property change: SET_MUTATOR.</P>
     * 
     * <p><i>Remarks:</i></p>
     *
     * <P>Normally, the action of the new mutator will be to apply
     * the old mutator and then to apply the given transform.</P>
     *
     * <p>This method should always have a meaningful interpretation for a
     * paintable, that is, it should always be possible to apply a mutation
     * that follows earlier mutations.  If this method is implemented in a
     * non-standard fashion, the documentation should state what is done.</p>
     *
     * @param M the invertible affine transform to compose
     */
    void addPostMutation(AffineTransform M);
    
    
    /**
     * <P>Applies a <CODE>Mutator.Strategy</CODE> object to the paintable
     * by constructing an affine transform using the <i>original</i> center
     * of the paintable
     * and then calling <code>setMutation</code> with this transform as the
     * argument.</p>
     *
     * <P>Fires property change: SET_MUTATOR.</P>
     *
     * <p>This method may be implemented in a more sophisticated fashion if
     * that is appropriate for a particular paintable.</p>
     * 
     * @param strategy the mutator strategy to apply
     */
    void setMutator(Mutator.Strategy strategy);
    
    
    /**
     * <P>Applies a <CODE>Mutator.Strategy</CODE> object to the paintable
     * by constructing an affine transform using the <i>original</i> center
     * of the paintable
     * and then calling <code>addPreMutation</code> with this transform as the
     * argument.</p>
     *
     * <P>Fires property change: SET_MUTATOR.</P>
     * 
     * <p>This method may be implemented in a more sophisticated fashion if
     * that is appropriate for a particular paintable.</p>
     * 
     * @param strategy the mutator strategy to apply
     */
    void addPreMutation(Mutator.Strategy strategy);
    
    
    /**
     * <P>Applies a <CODE>Mutator.Strategy</CODE> object to the paintable
     * by constructing an affine transform using the <i>mutated</i> center
     * of the paintable
     * and then calling <code>addPostMutation</code> with this transform as the
     * argument.</p>
     *
     * <P>Fires property change: SET_MUTATOR.</P>
     * 
     * <p>This method may be implemented in a more sophisticated fashion if
     * that is appropriate for a particular paintable.</p>
     * 
     * @param strategy the mutator strategy to apply
     */
    void addPostMutation(Mutator.Strategy strategy);
    
    
    /**
     * <p>Returns a copy of the existing mutator transform.</p>
     *
     * <p>If the implementation chooses to distribute transforms to
     * sub-objects, then this method may validly always return the
     * identity transform.</p>
     *
     * @return a copy of the existing mutator transform
     */
     AffineTransform getMutator();
    
    
    /**
     * <p>Returns a copy of the existing mutator inverse transform.</p>
     *
     * <p>If the implementation chooses to distribute transforms to
     * sub-objects, then this method may validly always return the
     * identity transform.</p>
     *
     * @return a copy of the existing mutator inverse transform
     */
    AffineTransform getMutatorInverse();
    
    
    /**
     * <p>This method should always be implemented to do exactly the same
     * operation as the corresponding method <code>addPostMutation</code>.
     * In other words, this should simply be a convenience method with a
     * short name.</p>
     *
     * @param M the invertible affine transform to compose
     * @see #addPostMutation(AffineTransform)
     */
    void mutate(AffineTransform M);
    
    
    /**
     * <p>This method should always be implemented to do exactly the same
     * operation as the corresponding method <code>addPostMutation</code>.
     * In other words, this should simply be a convenience method with a
     * short name.</p>
     *
     * @param strategy the mutator strategy to apply
     * @see #addPostMutation(Mutator.Strategy)
     */
    void mutate(Mutator.Strategy strategy);
    
    
    /**
     * <P>Moves the paintable by a translation using the data in the point
     * specified by coordinates.</P>
     *
     * @param dx the x-coordinate of the translation
     * @param dy the y-coordinate of the translation
     */
    void move(double dx, double dy);
    
    
    /**
     * <P>Moves the paintable by a translation using the data in the point.</p>
     *
     * @param p the translation vector
     */
    void move(Point2D p);
    
    
    /**
     * <P>Moves the paintable by a translation in such a way that the
     * paintable center specified by <code>getCenter</code>
     * will move to the given point specified in coordinates.</P>
     *
     * @param x the x-coordinate of the desired center
     * @param y the y-coordinate of the desired center
     */
    void moveCenterTo(double x, double y);
    
    
    /**
     * <P>Moves the paintable by a translation in such a way that the
     * paintable center specified by <code>getCenter</code>
     * will move to the given point.</P>
     *
     * @param p the desired center
     */
    void moveCenterTo(Point2D p);
    
    
    /**
     * <P>Moves the paintable by a translation in such a way that the
     * paintable corner specified by <code>getCorner</code>
     * will move to the given point specified in coordinates.</P>
     *
     * @param x the x-coordinate of the desired corner
     * @param y the y-coordinate of the desired corner
     */
    void moveCornerTo(double x, double y);
    
    
    /**
     * <P>Moves the paintable by a translation in such a way that the
     * paintable corner specified by <code>getCorner</code>
     * will move to the given point.</P>
     *
     * @param p the desired corner
     */
    void moveCornerTo(Point2D p);
    
    
    /**
     * <p>Rotates the paintable about its center by the given angle
     * in degrees.</p>
     *
     * @param degrees the rotation angle in degrees
     */
    void rotate(double degrees);
    
    
    /**
     * Reflects the paintable along the line through its center at
     * the given angle in degrees.
     *
     * @param degrees the angle in degrees of the line of reflection
     */
    void reflect(double degrees);
    
    
    /**
     * Reflects the paintable along a horizontal axis through its center.
     */
    void hreflect();
    
    
    /**
     * Reflects the paintable along a vertical axis through its center.
     */
    void vreflect();
    
    
    /**
     * <p>Scales the paintable about its center by the given factor
     * s uniformly in all directions.</p>
     *
     * @param s the scale in all directions
     */
    void scale(double s);
    
    
    /**
     * <p>Scales the paintable about its center by the given factor
     * s along the main axis at the given angle in degrees and the
     * given factor t along the perpendicular axis.</p>
     *
     * @param degrees the angle in degrees of the main scaling axis
     * @param s the scale factor along the axis at angle degrees
     * @param t the scale factor along the axis at angle degrees+90
     */
    void scale(double degrees, double s, double t);
    
    
    /**
     * <P>Shears the paintable about its center and with shear
     * factor s along the line at the given angle in degrees.</P>
     *
     * <P>In the special case when the center is at (0,0) and the
     * angle in degrees is 0, this corresponds to the transform:
     * (u,v) maps to (u+s*v,v), which fixes the x-axis and shears
     * parallel to that axis.</P>
     *
     * <P>In the general case, the fixed axis for the shear is the
     * line at the given angle degrees through the center.</P>
     *
     * @param degrees the angle in degrees of the fixed axis for shear
     * @param s determines the amount of shear along lines parallel to
     *        the fixed axis for shear
     */
    void shear(double degrees, double s);
    
    
    /**
     * <p>Glides (translates) the paintable along a glide line
     * at the given angle in degrees and the given glide distance.</p>
     *
     * <p>Equivalent to specifing a translation via polar coordinates
     * with the angle in degrees specified first and the distance
     * specified second. The reason for specifying degrees first here
     * is to be consistent with the usage of all other methods that
     * have degrees as a parameter.</p>
     *
     * @param degrees the angle in degrees of the line of glide
     * @param distance the translation distance along the line of glide
     */
    void glide(double degrees, double distance);
    
    
    /**
     * Glide-reflects the paintable along the line through its center
     * at the given angle in degrees and the given glide distance.
     *
     * @param degrees the angle in degrees of the line of glide reflection
     * @param distance the translation distance along the line of glide reflection
     */
    void glidereflect(double degrees, double distance);
    
    
    /**
     * <p>Apply the linear transform given by the matrix coefficients
     * m00, m10, m01, m11 as if the transform were centered at the
     * center of the paintable.  In other words, before applying the
     * given transform, adjust it so that the center of the paintable
     * remains fixed.</p>
     *
     * <p>Note that the two coefficients of column 0 are given first
     * and the two coefficients of column 1 are given next.</p>
     *
     * @param m00 the matrix coefficient in row 0 column 0
     * @param m10 the matrix coefficient in row 1 column 0
     * @param m01 the matrix coefficient in row 0 column 1
     * @param m11 the matrix coefficient in row 1 column 1
     */ 
    void lineartransform(double m00, double m10, double m01, double m11);
    
    
    /**
     * <p>Apply the affine transform given by the matrix coefficients
     * m00, m10, m01, m11, m02, m12 as if the transform were centered
     * at the center of the paintable.</p>
     *
     * <p>Note that the two coefficients of column 0 are given first,
     * the two coefficients of column 1 are given next, and
     * the two coefficients of column 2 are given last.</p>
     *
     * @param m00 the matrix coefficient in row 0 column 0
     * @param m10 the matrix coefficient in row 1 column 0
     * @param m01 the matrix coefficient in row 0 column 1
     * @param m11 the matrix coefficient in row 1 column 1
     * @param m02 the matrix coefficient in row 0 column 2
     * @param m12 the matrix coefficient in row 1 column 2
     */ 
    void affinetransform
        (double m00, double m10, double m01, double m11, double m02, double m12);
    
    
    /**
     * <P>Paints onto a <CODE>Graphics</CODE> context using information
     * from this object but without the use of the mutator transform.</P>
     *
     * <p>This method should be the foundation for the <code>paint</code>
     * methods that use the mutator.</p>
     *
     * <p>The designer of this method should assume that issues such as
     * visibility, opacity, clipping, antialiasing, and mutation will
     * be taken care of by the <code>paint</code> methods.  Therefore,
     * this method need only paint what must be painted with no
     * adjustments.</p>
     *
     * <P>Whatever the implementation, when this method call is complete,
     * the internal state of g should be unchanged.</P>
     * 
     * @param g the graphics context on which to paint
     */
    void originalPaint(Graphics g);
    
    
    /**
     * <P>Returns a copy of the 2-dimensional bounds of the original
     * paintable prior to any mutation.</P>
     *
     * <p>A recommended implementation should adopt the following
     * policy:</p>
     *
     * <p>If the value of <code>getDefaultOriginalBounds2D</code>
     * is non-<code>null</code>, then return this value.</p>
     *
     * <p>If the value of  <code>getActualBounds2D</code>
     * is non-<code>null</code>, then return this value.</p>
     *
     * <p>Otherwise, return <code>new XRect()</code>.</p>
     *
     * <P>This method must not return <CODE>null</CODE>.</P>
     *
     * @return a copy of the 2-dimensional bounds of the original paintable
     */
    XRect getOriginalBounds2D();
    
    
    /**
     * <p>Returns the actual bounds of the original paintable or
     * <code>null</code> if the paintable is effectively empty.</p>
     */
    XRect getActualBounds2D();
    
    
    /**
     * <P>Returns a copy of the original center of the paint region.</P>
     *
     * <p>A recommended implementation should adopt the following
     * policy:</p>
     *
     * <p>If the value of <code>getDefaultOriginalCenter</code>
     * is non-<code>null</code>, then return this value.</p>
     *
     * <P>Otherwise, return a computed value of the center.</P>
     *
     * <P>This method must not return <CODE>null</CODE>.</P>
     *
     * @return a copy of the center of the paint region
     */
    XPoint2D getOriginalCenter();
    
    
    /**
     * <p>Tests if a point specified by coordinates is inside the
     * original paintable without mutation.</p>
     *
     * @param  x the x-coordinate of the point
     * @param  y the y-coordinate of the point
     * @return whether or not a specified point is inside the
     *         original paintable
     */
    boolean originalContains(double x, double y);
    
    
    /**
     * <P>Tests if a specified point is inside the
     * original paintable without mutation.</P>
     *
     * @param  p a specified <CODE>Point2D</CODE>
     * @return whether or not a specified point is inside the
     *         original paintable
     */
    boolean originalContains(Point2D p);
    
    
    /**
     * <P>Apply the current opacity to calculate and set a net opacity for the
     * given graphics context.</P>
     *
     * <P>The following conditions must hold:</P>
     *
     * <UL>
     *   <LI>The current opacity of this paintable must be less than 1.</LI>
     *   <LI>The given graphics context either has no <CODE>Composite</CODE> set
     *       or has a <CODE>Composite</CODE> of type <CODE>AlphaComposite</CODE>
     *       whose rule is <CODE>SRC_OVER</CODE>.
     * </UL>
     *
     * <P>In the case that the graphics context has a <CODE>Composite</CODE> set
     * of type <CODE>AlphaComposite</CODE> with rule <CODE>SRC_OVER</CODE>, then
     * the net opacity is the product of the current opacity of this object and
     * the alpha value of the context's <CODE>AlphaComposite</CODE>.</P>
     *
     * <P>Otherwise the net opacity equals the current opacity of this object.</P>
     *
     * <P>It is recommended that this method be used in the implementation of
     * the <code>getPreparedGraphics2D</code> method.</p>
     *
     * @param h the graphics context whose opacity will be changed
     */
    void applyOpacity(Graphics2D h);
    
    
    /**
     * <P>Sets the default Bounds2D rectangle, that is,
     * the default for computation of <code>getBounds2D</code>.</P>
     *
     * <P>It is valid to set the default Bounds2D rectangle to
     * <CODE>null</CODE> to force a computation of the bounds.
     * Setting the default Bounds2D rectangle to a rectangle
     * with zero width or height should be equivalent to
     * setting it to <CODE>null</CODE>.</P>
     *
     * <P>Fires property change: SET_DEFAULT_BOUNDS2D.</P>
     * 
     * @param rectangle the default Bounds2D rectangle
     */
    void setDefaultBounds2D(Rectangle2D rectangle);
    
    
    /**
     * <p>Returns a copy of the default Bounds2D rectangle, that is,
     * the default for computation of <code>getBounds2D</code>.</P>
     *
     * <p>Returns <code>null</code> to signal no setting.</p>
     *
     * @return a copy of the default Bounds2D rectangle
     */
    XRect getDefaultBounds2D();
    
    
    /**
     * <P>Sets the default center, that is,
     * the default for computation of <code>getCenter</code>.</P>
     *
     * <P>It is valid to set the default center to
     * <CODE>null</CODE> to force a computation of the center.</P>
     *
     * <P>Fires property change: SET_DEFAULT_CENTER.</P>
     * 
     * @param center the default center
     */
    void setDefaultCenter(Point2D center);
    
    
    /**
     * <p>Returns a copy of the default center, that is,
     * the default for computation of <code>getCenter</code>.</P>
     *
     * <p>Returns <code>null</code> to signal no setting.</p>
     *
     * @return a copy of the default center
     */
    XPoint2D getDefaultCenter();
    
    
    /**
     * <P>Sets the default original Bounds2D rectangle, that is,
     * the default for computation of <code>getOriginalBounds2D</code>.</P>
     *
     * <P>It is valid to set the default original Bounds2D rectangle
     * to <CODE>null</CODE> to force a computation of the bounds.
     * Setting the default original Bounds2D rectangle to a rectangle
     * with zero width or height should be equivalent to setting it
     * to <CODE>null</CODE>.</P>
     *
     * <P>Fires property change: SET_DEFAULT_ORIGINAL_BOUNDS2D.</P>
     * 
     * @param rectangle the default original Bounds2D rectangle
     */
    void setDefaultOriginalBounds2D(Rectangle2D rectangle);
    
    
    /**
     * <p>Returns a copy of the default original Bounds2D rectangle, that is,
     * the default for computation of <code>getOriginalBounds2D</code>.</P>
     *
     * <p>Returns <code>null</code> to signal no setting.</p>
     *
     * @return a copy of the default original Bounds2D rectangle
     */
    XRect getDefaultOriginalBounds2D();
    
    
    /**
     * <P>Sets the default original center, that is,
     * the default for computation of <code>getOriginalCenter</code>.</P>
     *
     * <P>It is valid to set the default original center to
     * <CODE>null</CODE> to force a computation of the center.</P>
     *
     * <P>Fires property change: SET_DEFAULT_ORIGINAL_CENTER.</P>
     * 
     * @param center the default original center
     */
    void setDefaultOriginalCenter(Point2D center);
    
    
    /**
     * <p>Returns a copy of the default original center, that is,
     * the default for computation of <code>getOriginalCenter</code>.</P>
     *
     * <p>Returns <code>null</code> to signal no setting.</p>
     *
     * @return a copy of the default original center
     */
    XPoint2D getDefaultOriginalCenter();
    
    
}
