You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pivot.apache.org by tv...@apache.org on 2009/03/16 17:36:28 UTC

svn commit: r754936 [24/38] - in /incubator/pivot/tags/v1.0.1: ./ charts-test/ charts-test/src/ charts-test/src/pivot/ charts-test/src/pivot/charts/ charts-test/src/pivot/charts/test/ charts/ charts/lib/ charts/src/ charts/src/pivot/ charts/src/pivot/c...

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/ReflectionDecorator.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/ReflectionDecorator.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/ReflectionDecorator.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/ReflectionDecorator.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,83 @@
+package pivot.wtk.effects;
+
+import java.awt.AlphaComposite;
+import java.awt.Color;
+import java.awt.GradientPaint;
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+
+import pivot.wtk.Component;
+import pivot.wtk.Decorator;
+import pivot.wtk.Bounds;
+
+/**
+ * Decorator that paints a reflection of a component.
+ * <p>
+ * TODO Make gradient properties configurable.
+ *
+ * @author gbrown
+ */
+public class ReflectionDecorator implements Decorator {
+    private Graphics2D graphics = null;
+
+    private BufferedImage bufferedImage = null;
+    private Graphics2D bufferedImageGraphics = null;
+
+    public Graphics2D prepare(Component component, Graphics2D graphics) {
+        this.graphics = graphics;
+
+        int width = component.getWidth();
+        int height = component.getHeight();
+
+        if (bufferedImage == null
+            || bufferedImage.getWidth() < width
+            || bufferedImage.getHeight() < height) {
+            bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
+        }
+
+        bufferedImageGraphics = bufferedImage.createGraphics();
+        bufferedImageGraphics.setClip(graphics.getClip());
+
+        // Clear the image background
+        bufferedImageGraphics.setComposite(AlphaComposite.Clear);
+        bufferedImageGraphics.fillRect(0, 0, bufferedImage.getWidth(), bufferedImage.getHeight());
+
+        bufferedImageGraphics.setComposite(AlphaComposite.SrcOver);
+
+        return bufferedImageGraphics;
+    }
+
+    public void update() {
+        // Draw the component
+        graphics.drawImage(bufferedImage, 0, 0, null);
+
+        // Draw the reflection
+        int width = bufferedImage.getWidth();
+        int height = bufferedImage.getHeight();
+
+        GradientPaint mask = new GradientPaint(0, height / 4, new Color(1.0f, 1.0f, 1.0f, 0.0f),
+            0, height, new Color(1.0f, 1.0f, 1.0f, 0.5f));
+        bufferedImageGraphics.setPaint(mask);
+
+        bufferedImageGraphics.setComposite(AlphaComposite.DstIn);
+        bufferedImageGraphics.fillRect(0, 0, width, height);
+
+        bufferedImageGraphics.dispose();
+        bufferedImage.flush();
+
+        Graphics2D reflectionGraphics = (Graphics2D)graphics.create();
+        reflectionGraphics.scale(1.0, -1.0);
+        reflectionGraphics.translate(0, -(height * 2));
+
+        reflectionGraphics.setClip(null);
+        reflectionGraphics.drawImage(bufferedImage, 0, 0, null);
+
+        // Dispose of the graphics
+        reflectionGraphics.dispose();
+    }
+
+    public Bounds getAffectedArea(Component component, int x, int y, int width, int height) {
+        return new Bounds(x, (component.getHeight() * 2) - (y + height),
+            width, height);
+    }
+}

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/SaturationDecorator.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/SaturationDecorator.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/SaturationDecorator.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/SaturationDecorator.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Contains code and concepts from ShadowRenderer.java v1.6,
+ * copyright 2006 Sun Microsystems, Inc., 4150 Network Circle,
+ * Santa Clara, California 95054, U.S.A. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk.effects;
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+import java.awt.image.WritableRaster;
+import pivot.wtk.Component;
+import pivot.wtk.Decorator;
+import pivot.wtk.Bounds;
+
+/**
+ * Decorator that modifies the color saturation of a component.
+ *
+ * @author tvolkert
+ */
+public class SaturationDecorator implements Decorator {
+    private float multiplier;
+
+    private Graphics2D graphics = null;
+
+    private BufferedImage componentImage = null;
+    private Graphics2D componentGraphics = null;
+
+    public SaturationDecorator() {
+        this(1.0f);
+    }
+
+    public SaturationDecorator(float multiplier) {
+        this.multiplier = multiplier;
+    }
+
+    public float getMultiplier() {
+        return multiplier;
+    }
+
+    public void setMultiplier(float multiplier) {
+        this.multiplier = multiplier;
+    }
+
+    public void setMultiplier(Number multiplier) {
+        if (multiplier == null) {
+            throw new IllegalArgumentException("Multiplier is null.");
+        }
+
+        setMultiplier(multiplier.floatValue());
+    }
+
+    public Graphics2D prepare(Component component, Graphics2D graphics) {
+        int x = 0;
+        int y = 0;
+        int width = component.getWidth();
+        int height = component.getHeight();
+
+        java.awt.Rectangle clipBounds = graphics.getClipBounds();
+        if (clipBounds != null) {
+            x = clipBounds.x;
+            y = clipBounds.y;
+            width = clipBounds.width;
+            height = clipBounds.height;
+        }
+
+        componentImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
+
+        this.graphics = graphics;
+
+        componentGraphics = componentImage.createGraphics();
+        componentGraphics.translate(-x, -y);
+        componentGraphics.setClip(graphics.getClip());
+
+        return componentGraphics;
+    }
+
+    /**
+     * Adjusts the saturation of the component image and draws the resulting
+     * image using the component's graphics.
+     */
+    public void update() {
+        int width = componentImage.getWidth();
+        int height = componentImage.getHeight();
+
+        int[] buffer = new int[width * height];
+
+        WritableRaster raster = componentImage.getRaster();
+        raster.getDataElements(0, 0, width, height, buffer);
+
+        float[] hsb = new float[3];
+
+        for (int i = 0; i < height; i++) {
+            for (int j = 0; j < width; j++) {
+                int srcRGB = buffer[i * width + j];
+
+                // Adjust color saturation
+                Color.RGBtoHSB((srcRGB >> 16) & 0xff,
+                    (srcRGB >> 8) & 0xff, srcRGB & 0xff, hsb);
+                int dstRGB = Color.HSBtoRGB(hsb[0],
+                    Math.min(Math.max(hsb[1] * multiplier, 0f), 1f), hsb[2]);
+
+                // Preserve the source alpha channel
+                dstRGB = (srcRGB & 0xff000000) | (dstRGB & 0xffffff);
+
+                buffer[i * width + j] = dstRGB;
+            }
+        }
+
+        raster.setDataElements(0, 0, width, height, buffer);
+
+        int x = 0;
+        int y = 0;
+
+        java.awt.Rectangle clipBounds = componentGraphics.getClipBounds();
+        if (clipBounds != null) {
+            x = clipBounds.x;
+            y = clipBounds.y;
+        }
+
+        componentGraphics.dispose();
+        graphics.drawImage(componentImage, x, y, null);
+    }
+
+    public Bounds getAffectedArea(Component component, int x, int y, int width, int height) {
+        return new Bounds(x, y, width, height);
+    }
+}

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/ScaleDecorator.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/ScaleDecorator.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/ScaleDecorator.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/ScaleDecorator.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,373 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk.effects;
+
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+
+import pivot.wtk.Bounds;
+import pivot.wtk.Component;
+import pivot.wtk.Container;
+import pivot.wtk.Decorator;
+import pivot.wtk.HorizontalAlignment;
+import pivot.wtk.VerticalAlignment;
+
+/**
+ * Decorator that scales the painting of a component along the X and/or Y axes.
+ *
+ * @author tvolkert
+ */
+public class ScaleDecorator implements Decorator {
+    private float scaleX;
+    private float scaleY;
+    private HorizontalAlignment horizontalAlignment = HorizontalAlignment.CENTER;
+    private VerticalAlignment verticalAlignment = VerticalAlignment.CENTER;
+
+    /**
+     * Creates a new <tt>ScaleDecorator</tt> with the default <tt>scaleX</tt>
+     * <tt>scaleY</tt> values of <tt>1</tt>.
+     */
+    public ScaleDecorator() {
+        this(1f, 1f);
+    }
+
+    /**
+     * Creates a new <tt>ScaleDecorator</tt> with the specified <tt>scaleX</tt>
+     * and <tt>scaleY</tt> values.
+     *
+     * @param scaleX
+     * The amount to scale the component's x-axis
+     *
+     * @param scaleY
+     * The amount to scale the component's y-axis
+     */
+    public ScaleDecorator(float scaleX, float scaleY) {
+        if (scaleX <= 0
+            || scaleY <= 0) {
+            throw new IllegalArgumentException("Scale values must be positive.");
+        }
+
+        this.scaleX = scaleX;
+        this.scaleY = scaleY;
+    }
+
+    /**
+     * Gets the amount by which drawing operations will be scaled along the
+     * x-axis.
+     *
+     * @return
+     * The amount to scale the component's x-axis
+     */
+    public float getScaleX() {
+        return scaleX;
+    }
+
+    /**
+     * Sets the amount by which drawing operations will be scaled along the
+     * x-axis.
+     *
+     * @param scaleX
+     * The amount to scale the component's x-axis
+     */
+    public void setScaleX(float scaleX) {
+        if (scaleX <= 0) {
+            throw new IllegalArgumentException("scaleX must be positive.");
+        }
+
+        this.scaleX = scaleX;
+    }
+
+    /**
+     * Sets the amount by which drawing operations will be scaled along the
+     * x-axis.
+     *
+     * @param scaleX
+     * The amount to scale the component's x-axis
+     */
+    public void setScaleX(Number scaleX) {
+        if (scaleX == null) {
+            throw new IllegalArgumentException("scaleX is null.");
+        }
+
+        setScaleX(scaleX.floatValue());
+    }
+
+    /**
+     * Gets the amount by which drawing operations will be scaled along the
+     * y-axis.
+     *
+     * @return
+     * The amount to scale the component's y-axis
+     */
+    public float getScaleY() {
+        return scaleY;
+    }
+
+    /**
+     * Sets the amount by which drawing operations will be scaled along the
+     * y-axis.
+     *
+     * @param scaleY
+     * The amount to scale the component's y-axis
+     */
+    public void setScaleY(float scaleY) {
+        if (scaleY <= 0) {
+            throw new IllegalArgumentException("scaleY must be positive.");
+        }
+
+        this.scaleY = scaleY;
+    }
+
+    /**
+     * Sets the amount by which drawing operations will be scaled along the
+     * y-axis.
+     *
+     * @param scaleY
+     * The amount to scale the component's y-axis
+     */
+    public void setScaleY(Number scaleY) {
+        if (scaleY == null) {
+            throw new IllegalArgumentException("scaleY is null.");
+        }
+
+        setScaleY(scaleY.floatValue());
+    }
+
+    /**
+     * Gets the horizontal alignment of the decorator. A left alignment will
+     * paint the component's left edge at the component's x-coordinate. A right
+     * alignment will paint the component's right edge along the right side
+     * of the component's bounding box. A center or justified alignment will
+     * paint the scaled component centered with respect to the component's
+     * bounding box.
+     *
+     * @return
+     * The horizontal alignment
+     */
+    public HorizontalAlignment getHorizontalAlignment() {
+        return horizontalAlignment;
+    }
+
+    /**
+     * Sets the horizontal alignment of the decorator. A left alignment will
+     * paint the component's left edge at the component's x-coordinate. A right
+     * alignment will paint the component's right edge along the right side
+     * of the component's bounding box. A center or justified alignment will
+     * paint the scaled component centered with respect to the component's
+     * bounding box.
+     *
+     * @param horizontalAlignment
+     * The horizontal alignment
+     */
+    public void setHorizontalAlignment(HorizontalAlignment horizontalAlignment) {
+        if (horizontalAlignment == null) {
+            throw new IllegalArgumentException("horizontalAlignment is null.");
+        }
+
+        this.horizontalAlignment = horizontalAlignment;
+    }
+
+    /**
+     * Sets the horizontal alignment of the decorator. A left alignment will
+     * paint the component's left edge at the component's x-coordinate. A right
+     * alignment will paint the component's right edge along the right side
+     * of the component's bounding box. A center or justified alignment will
+     * paint the scaled component centered with respect to the component's
+     * bounding box.
+     *
+     * @param horizontalAlignment
+     * The horizontal alignment
+     */
+    public final void setHorizontalAlignment(String horizontalAlignment) {
+        if (horizontalAlignment == null) {
+            throw new IllegalArgumentException("horizontalAlignment is null.");
+        }
+
+        setHorizontalAlignment(HorizontalAlignment.decode(horizontalAlignment));
+    }
+
+    /**
+     * Gets the vertical alignment of the decorator. A top alignment will
+     * paint the component's top edge at the component's y-coordinate. A bottom
+     * alignment will paint the component's bottom edge along the bottom side
+     * of the component's bounding box. A center or justified alignment will
+     * paint the scaled component centered with respect to the component's
+     * bounding box.
+     *
+     * @return
+     * The vertical alignment
+     */
+    public VerticalAlignment getVerticalAlignment() {
+        return verticalAlignment;
+    }
+
+    /**
+     * Sets the vertical alignment of the decorator. A top alignment will
+     * paint the component's top edge at the component's y-coordinate. A bottom
+     * alignment will paint the component's bottom edge along the bottom side
+     * of the component's bounding box. A center or justified alignment will
+     * paint the scaled component centered with respect to the component's
+     * bounding box.
+     *
+     * @param verticalAlignment
+     * The vertical alignment
+     */
+    public void setVerticalAlignment(VerticalAlignment verticalAlignment) {
+        if (verticalAlignment == null) {
+            throw new IllegalArgumentException("verticalAlignment is null.");
+        }
+
+        this.verticalAlignment = verticalAlignment;
+    }
+
+    /**
+     * Sets the vertical alignment of the decorator. A top alignment will
+     * paint the component's top edge at the component's y-coordinate. A bottom
+     * alignment will paint the component's bottom edge along the bottom side
+     * of the component's bounding box. A center or justified alignment will
+     * paint the scaled component centered with respect to the component's
+     * bounding box.
+     *
+     * @param verticalAlignment
+     * The vertical alignment
+     */
+    public final void setVerticalAlignment(String verticalAlignment) {
+        if (verticalAlignment == null) {
+            throw new IllegalArgumentException("verticalAlignment is null.");
+        }
+
+        setVerticalAlignment(VerticalAlignment.decode(verticalAlignment));
+    }
+
+    /**
+     * Gets the x translation that will be applied with respect to the
+     * specified component, given this decorator's <tt>scaleX</tt> and
+     * <tt>horizontalAlignment</tt> properties.
+     *
+     * @param component
+     * The component being decorated
+     *
+     * @return
+     * The amount to translate x-coordinate actions when decorating this
+     * component
+     */
+    private int getTranslatedX(Component component) {
+        int width = component.getWidth();
+        int translatedWidth = (int)Math.ceil(width * scaleX);
+
+        int tx;
+
+        switch (horizontalAlignment) {
+        case LEFT:
+            tx = 0;
+            break;
+        case RIGHT:
+            tx = width - translatedWidth;
+            break;
+        default:
+            tx = (width - translatedWidth) / 2;
+            break;
+        }
+
+        return tx;
+    }
+
+    /**
+     * Gets the y translation that will be applied with respect to the
+     * specified component, given this decorator's <tt>scaleY</tt> and
+     * <tt>verticalAlignment</tt> properties.
+     *
+     * @param component
+     * The component being decorated
+     *
+     * @return
+     * The amount to translate y-coordinate actions when decorating this
+     * component
+     */
+    private int getTranslatedY(Component component) {
+        int height = component.getHeight();
+        int translatedHeight = (int)Math.ceil(height * scaleY);
+
+        int ty;
+
+        switch (verticalAlignment) {
+        case TOP:
+            ty = 0;
+            break;
+        case BOTTOM:
+            ty = height - translatedHeight;
+            break;
+        default:
+            ty = (height - translatedHeight) / 2;
+            break;
+        }
+
+        return ty;
+    }
+
+    public Graphics2D prepare(Component component, Graphics2D graphics) {
+        graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+            RenderingHints.VALUE_ANTIALIAS_ON);
+        graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
+            RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
+
+        int tx = getTranslatedX(component);
+        int ty = getTranslatedY(component);
+
+        if (tx != 0 || ty != 0) {
+            graphics.translate(tx, ty);
+        }
+
+        graphics.scale(scaleX, scaleY);
+
+        return graphics;
+    }
+
+    public void update() {
+        // No-op
+    }
+
+    public Bounds getBounds(Component component) {
+        int width = (int)Math.ceil(component.getWidth() * scaleX);
+        int height = (int)Math.ceil(component.getHeight() * scaleY);
+
+        int tx = getTranslatedX(component);
+        int ty = getTranslatedY(component);
+
+        return new Bounds(tx, ty, width, height);
+    }
+
+    public void repaint(Component component, int x, int y, int width, int height) {
+        Container parent = component.getParent();
+
+        if (parent != null) {
+            int tx = getTranslatedX(component);
+            int ty = getTranslatedY(component);
+
+            x = (int)((x * scaleX) + component.getX() + tx);
+            y = (int)((y * scaleY) + component.getY() + ty);
+            width = (int)Math.ceil(width * scaleX);
+            height = (int)Math.ceil(height * scaleY);
+
+            parent.repaint(x, y, width, height);
+        }
+    }
+
+    public Bounds getAffectedArea(Component component, int x, int y, int width, int height) {
+        // TODO
+        return new Bounds(x, y, width, height);
+    }
+}

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/ShadeDecorator.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/ShadeDecorator.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/ShadeDecorator.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/ShadeDecorator.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk.effects;
+
+import java.awt.AlphaComposite;
+import java.awt.Color;
+import java.awt.Graphics2D;
+
+import pivot.wtk.Component;
+import pivot.wtk.Decorator;
+import pivot.wtk.Bounds;
+
+/**
+ * Decorator that applies a "shade" to a component. The shade is a rectangle
+ * of the same size as the component that is painted over the component using a
+ * given color and opacity value.
+ *
+ * @author tvolkert
+ */
+public class ShadeDecorator implements Decorator {
+    private float opacity;
+    private Color color;
+
+    private Graphics2D graphics;
+    private Component component;
+
+    /**
+     * Creates a new <tt>ShadeDecorator</tt> with the default opacity and
+     * shade color.
+     */
+    public ShadeDecorator() {
+        this(0.33f, Color.BLACK);
+    }
+
+    /**
+     * Creates a new <tt>ShadeDecorator</tt> with the specified opacity and
+     * shade color.
+     *
+     * @param opacity
+     * The opacity of the shade, between 0 and 1, exclusive.
+     *
+     * @param color
+     * The color of the shade.
+     */
+    public ShadeDecorator(float opacity, Color color) {
+        if (opacity <= 0 || opacity >= 1) {
+            throw new IllegalArgumentException("opacity must be between 0 and 1, exclusive.");
+        }
+
+        if (color == null) {
+            throw new IllegalArgumentException("color is null.");
+        }
+
+        this.opacity = opacity;
+        this.color = color;
+    }
+
+    /**
+     *
+     */
+    public float getOpacity() {
+        return opacity;
+    }
+
+    /**
+     *
+     */
+    public void setOpacity(float opacity) {
+        this.opacity = opacity;
+    }
+
+    /**
+     *
+     */
+    public void setOpacity(Number opacity) {
+        if (opacity == null) {
+            throw new IllegalArgumentException("opacity is null.");
+        }
+
+        setOpacity(opacity.floatValue());
+    }
+
+    /**
+     *
+     */
+    public Color getColor() {
+        return color;
+    }
+
+    /**
+     *
+     */
+    public void setColor(Color color) {
+        if (color == null) {
+            throw new IllegalArgumentException("color is null.");
+        }
+
+        this.color = color;
+    }
+
+    /**
+     *
+     */
+    public final void setColor(String color) {
+        if (color == null) {
+            throw new IllegalArgumentException("color is null.");
+        }
+
+        setColor(Color.decode(color));
+    }
+
+    public Graphics2D prepare(Component component, Graphics2D graphics) {
+        this.graphics = graphics;
+        this.component = component;
+
+        return graphics;
+    }
+
+    public void update() {
+        graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, opacity));
+        graphics.setColor(color);
+        graphics.fillRect(0, 0, component.getWidth(), component.getHeight());
+    }
+
+    public Bounds getAffectedArea(Component component, int x, int y, int width, int height) {
+        return new Bounds(x, y, width, height);
+    }
+}

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/Transition.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/Transition.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/Transition.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/Transition.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,272 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk.effects;
+
+import pivot.wtk.ApplicationContext;
+
+/**
+ * Abstract base class for "transitions", which are animated application
+ * effects.
+ *
+ * @author gbrown
+ * @author tvolkert
+ */
+public abstract class Transition {
+    private int duration;
+    private int rate;
+    private boolean repeat;
+
+    private TransitionListener transitionListener;
+
+    private long startTime = 0;
+    private long currentTime = 0;
+    private int intervalID = -1;
+
+    public static final int DEFAULT_DURATION = 0;
+    public static final int DEFAULT_RATE = 15;
+
+    private final Runnable updateCallback = new Runnable() {
+        public void run() {
+            if (intervalID == -1) {
+                // TODO Figure out why this is happening
+                System.out.println("Interval task executed after it was cancelled.");
+                return;
+            }
+
+            currentTime = System.currentTimeMillis();
+
+            long endTime = startTime + duration;
+            if (currentTime >= endTime) {
+                if (repeat) {
+                    startTime = endTime;
+                } else {
+                    currentTime = endTime;
+                    stop();
+
+                    if (transitionListener != null) {
+                        transitionListener.transitionCompleted(Transition.this);
+                    }
+                }
+            }
+
+            update();
+        }
+    };
+
+    /**
+     * Creates a new, non-repeating transition with the default duration
+     * and rate.
+     */
+    public Transition() {
+        this(DEFAULT_DURATION, DEFAULT_RATE, false);
+    }
+
+    /**
+     * Creates a new transition with the given duration, rate, and repeat.
+     *
+     * @param duration
+     * Transition duration, in milliseconds.
+     *
+     * @param rate
+     * Transition rate, in frames per second.
+     */
+    public Transition(int duration, int rate, boolean repeat) {
+        if (duration <= 0) {
+            throw new IllegalArgumentException("duration must be positive.");
+        }
+
+        this.duration = duration;
+        this.rate = rate;
+        this.repeat = repeat;
+    }
+
+    /**
+     * Returns the transition duration.
+     *
+     * @return
+     * The duration of the transition, in milliseconds.
+     *
+     * @see #setDuration(int)
+     */
+    public int getDuration() {
+        return duration;
+    }
+
+    /**
+     * Sets the transition duration, the length of time the transition is
+     * scheduled to run.
+     *
+     * @param duration
+     * The duration of the transition, in milliseconds.
+     */
+    public void setDuration(int duration) {
+        if (duration < 0) {
+            throw new IllegalArgumentException("duration is negative.");
+        }
+
+        if (intervalID != -1) {
+            throw new IllegalStateException("Transition is currently running.");
+        }
+
+        this.duration = duration;
+    }
+
+    /**
+     * Returns the transition rate.
+     *
+     * @return
+     * The rate of the transition, in frames per second.
+     *
+     * @see #setRate(int)
+     */
+    public int getRate() {
+        return rate;
+    }
+
+    /**
+     * Sets the transition rate, the number of times the transition will be
+     * updated within the span of one second.
+     *
+     * @param rate
+     * The transition rate, in frames per second.
+     */
+    public void setRate(int rate) {
+        if (rate < 0) {
+            throw new IllegalArgumentException("rate is negative.");
+        }
+
+        if (intervalID != -1) {
+            throw new IllegalStateException("Transition is currently running.");
+        }
+
+        this.rate = rate;
+    }
+
+    /**
+     * Returns the transition interval, the number of milliseconds between
+     * updates.
+     *
+     * @return
+     * The transition interval, in milliseconds.
+     */
+    public int getInterval() {
+        return (int)((1f / (float)rate) * 1000);
+    }
+
+    /**
+     * Returns the time at which the transition was started.
+     *
+     * @return
+     * The transition's start time.
+     */
+    public long getStartTime() {
+        return startTime;
+    }
+
+    /**
+     * Returns the last time the transition was updated.
+     *
+     * @return
+     * The most recent update time.
+     */
+    public long getCurrentTime() {
+        return currentTime;
+    }
+
+    /**
+     * Returns the elapsed time since the transition started.
+     *
+     * @return
+     * Returns the amount of time that has passed since the transition
+     * was started.
+     */
+    public int getElapsedTime() {
+        return (int)(currentTime - startTime);
+    }
+
+    /**
+     * Returns the percentage of the transition that has completed.
+     *
+     * @return
+     * A value between 0 and 1, inclusive, representing the transition's
+     * percent complete.
+     */
+    public float getPercentComplete() {
+        return (float)(currentTime - startTime) / (float)(duration);
+    }
+
+    /**
+     * Tells whether or not the transition is currently running.
+     *
+     * @return
+     * <tt>true</tt> if the transition is currently running; <tt>false</tt> if
+     * it is not
+     */
+    public boolean isRunning() {
+        return (intervalID != -1);
+    }
+
+    /**
+     * Starts the transition. Calls {@link #update()} to establish the
+     * initial state and starts a timer that will repeatedly call
+     * {@link #update()} at the current rate.
+     */
+    public final void start() {
+        start(null);
+    }
+
+    /**
+     * Starts the transition. Calls {@link #update()} to establish the
+     * initial state and starts a timer that will repeatedly call
+     * {@link #update()} at the current rate. The specified
+     * <tt>TransitionListener</tt> will be notified when the transition
+     * completes.
+     *
+     * @param transitionListener
+     * The listener to get notified when the transition completes, or
+     * <tt>null</tt> if no notification is necessary
+     */
+    public void start(TransitionListener transitionListener) {
+        if (intervalID != -1) {
+            throw new IllegalStateException("Transition is currently running.");
+        }
+
+        this.transitionListener = transitionListener;
+
+        startTime = System.currentTimeMillis();
+        currentTime = startTime;
+
+        intervalID = ApplicationContext.setInterval(updateCallback, getInterval());
+
+        update();
+    }
+
+    /**
+     * Stops the transition.
+     */
+    public void stop() {
+        if (intervalID != -1) {
+            ApplicationContext.clearInterval(intervalID);
+            intervalID = -1;
+        }
+    }
+
+    /**
+     * Called repeatedly while the transition is running to update the
+     * transition's state.
+     */
+    protected abstract void update();
+}

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/TransitionListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/TransitionListener.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/TransitionListener.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/TransitionListener.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk.effects;
+
+/**
+ * Transition listener interface.
+ *
+ * @author tvolkert
+ */
+public interface TransitionListener {
+    /**
+     * Called when a transition has completed.
+     *
+     * @param transition
+     */
+    public void transitionCompleted(Transition transition);
+}

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/TranslationDecorator.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/TranslationDecorator.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/TranslationDecorator.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/TranslationDecorator.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk.effects;
+
+import java.awt.Graphics2D;
+
+import pivot.wtk.Bounds;
+import pivot.wtk.Component;
+import pivot.wtk.Decorator;
+import pivot.wtk.Point;
+
+/**
+ * Decorator that translates the paint origin of its component.
+ *
+ * @author gbrown
+ */
+public class TranslationDecorator implements Decorator {
+    private int x = 0;
+    private int y = 0;
+    private boolean clip = false;
+
+    public TranslationDecorator() {
+    }
+
+    public TranslationDecorator(boolean clip) {
+        setClip(clip);
+    }
+
+    public TranslationDecorator(int x, int y, boolean clip) {
+        setOffset(x, y);
+        setClip(clip);
+    }
+
+    public int getX() {
+        return x;
+    }
+
+    public void setX(int x) {
+        this.x = x;
+    }
+
+    public int getY() {
+        return y;
+    }
+
+    public void setY(int y) {
+        this.y = y;
+    }
+
+    public Point getOffset() {
+        return new Point(x, y);
+    }
+
+    public void setOffset(Point offset) {
+        if (offset == null) {
+            throw new IllegalArgumentException("offset is null.");
+        }
+
+        setOffset(offset.x, offset.y);
+    }
+
+    public void setOffset(int x, int y) {
+        this.x = x;
+        this.y = y;
+    }
+
+    public boolean getClip() {
+        return clip;
+    }
+
+    public void setClip(boolean clip) {
+        this.clip = clip;
+    }
+
+    public Graphics2D prepare(Component component, Graphics2D graphics) {
+        graphics.translate(x, y);
+        return graphics;
+    }
+
+    public void update() {
+    }
+
+    public Bounds getAffectedArea(Component component, int x, int y, int width, int height) {
+        Bounds affectedArea = new Bounds(x + this.x, y + this.y, width, height);
+        if (clip) {
+            affectedArea.intersect(component.getBounds());
+        }
+
+        return affectedArea;
+    }
+}

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/WatermarkDecorator.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/WatermarkDecorator.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/WatermarkDecorator.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/WatermarkDecorator.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,309 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk.effects;
+
+import java.awt.AlphaComposite;
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.net.URL;
+
+import pivot.wtk.Component;
+import pivot.wtk.Decorator;
+import pivot.wtk.FlowPane;
+import pivot.wtk.ImageView;
+import pivot.wtk.Label;
+import pivot.wtk.Orientation;
+import pivot.wtk.Bounds;
+import pivot.wtk.VerticalAlignment;
+import pivot.wtk.media.Image;
+
+/**
+ * Decorator that paints a watermark effect over a component.
+ *
+ * @author tvolkert
+ */
+public class WatermarkDecorator implements Decorator {
+    private float opacity = 0.075f;
+    private double theta = Math.PI / 4;
+
+    private FlowPane flowPane = new FlowPane(Orientation.HORIZONTAL);
+    private ImageView imageView = new ImageView();
+    private Label label = new Label();
+
+    private Component component = null;
+    private Graphics2D graphics = null;
+
+    /**
+     * Cretes a new <tt>WatermarkDecorator</tt> with no text or image.
+     */
+    public WatermarkDecorator() {
+        this(null, null);
+    }
+
+    /**
+     * Cretes a new <tt>WatermarkDecorator</tt> with the specified string as
+     * its text and no image.
+     *
+     * @param text
+     * The text to paint over the decorated component
+     */
+    public WatermarkDecorator(String text) {
+        this(text, null);
+    }
+
+    /**
+     * Cretes a new <tt>WatermarkDecorator</tt> with no text and the specified
+     * image.
+     *
+     * @param image
+     * The image to paint over the decorated component
+     */
+    public WatermarkDecorator(Image image) {
+        this(null, image);
+    }
+
+    /**
+     * Cretes a new <tt>WatermarkDecorator</tt> with the specified text and
+     * image.
+     *
+     * @param text
+     * The text to paint over the decorated component
+     *
+     * @param image
+     * The image to paint over the decorated component
+     */
+    public WatermarkDecorator(String text, Image image) {
+        flowPane.add(imageView);
+        flowPane.add(label);
+
+        flowPane.getStyles().put("verticalAlignment", VerticalAlignment.CENTER);
+        imageView.getStyles().put("opacity", opacity);
+
+        Font font = (Font)label.getStyles().get("font");
+        label.getStyles().put("font", font.deriveFont(Font.BOLD, 60));
+
+        label.setText(text);
+        imageView.setImage(image);
+
+        validate();
+    }
+
+    /**
+     * Gets the text that will be painted over this decorator's component.
+     *
+     * @return
+     * This decorator's text
+     */
+    public String getText() {
+        return label.getText();
+    }
+
+    /**
+     * Sets the text that will be painted over this decorator's component.
+     *
+     * @param text
+     * This decorator's text
+     */
+    public void setText(String text) {
+        label.setText(text);
+        validate();
+    }
+
+    /**
+     * Gets the font that will be used when painting this decorator's text.
+     *
+     * @return
+     * This decorator's font
+     */
+    public Font getFont() {
+        return (Font)label.getStyles().get("font");
+    }
+
+    /**
+     * Sets the font that will be used when painting this decorator's text.
+     *
+     * @param font
+     * This decorator's font
+     */
+    public void setFont(Font font) {
+        label.getStyles().put("font", font);
+        validate();
+    }
+
+    /**
+     * Sets the font that will be used when painting this decorator's text.
+     *
+     * @param font
+     * This decorator's font
+     */
+    public final void setFont(String font) {
+        setFont(Font.decode(font));
+    }
+
+    /**
+     * Gets the image that will be painted over this decorator's component.
+     *
+     * @return
+     * This decorator's image
+     */
+    public Image getImage() {
+        return imageView.getImage();
+    }
+
+    /**
+     * Sets the image that will be painted over this decorator's component.
+     *
+     * @param image
+     * This decorator's image
+     */
+    public void setImage(Image image) {
+        imageView.setImage(image);
+        validate();
+    }
+
+    /**
+     * Sets the image that will be painted over this decorator's component.
+     *
+     * @param image
+     * This decorator's image
+     */
+    public void setImage(URL image) {
+        if (image == null) {
+            throw new IllegalArgumentException("image is null.");
+        }
+
+        setImage(Image.load(image));
+    }
+
+    /**
+     * Sets the image that will be painted over this decorator's component.
+     *
+     * @param image
+     * This decorator's image
+     */
+    public void setImage(String image) {
+        if (image == null) {
+            throw new IllegalArgumentException("image is null.");
+        }
+
+        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+        setImage(classLoader.getResource(image));
+    }
+
+    /**
+     * Gets the opacity of the watermark.
+     *
+     * @return
+     * This decorator's opacity
+     */
+    public float getOpacity() {
+        return opacity;
+    }
+
+    /**
+     * Sets the opacity of the watermark.
+     *
+     * @param opacity
+     * This decorator's opacity
+     */
+    public void setOpacity(float opacity) {
+        this.opacity = opacity;
+        imageView.getStyles().put("opacity", opacity);
+    }
+
+    /**
+     * Gets the angle at the watermark will be painted, in radians.
+     *
+     * @return
+     * This decorator's watermark angle
+     */
+    public double getTheta() {
+        return theta;
+    }
+
+    /**
+     * Sets the angle at the watermark will be painted, in radians. This value
+     * must lie between <tt>0</tt> and <tt>PI / 2</tt> (inclusive).
+     *
+     * @param theta
+     * This decorator's watermark angle
+     */
+    public void setTheta(double theta) {
+        if (theta < 0
+            || theta > Math.PI / 2) {
+            throw new IllegalArgumentException("Theta must be between 0 nd PI / 2.");
+        }
+
+        this.theta = theta;
+    }
+
+    /**
+     * Sets this decorator's flow pane to its preferred size and validates it.
+     */
+    private void validate() {
+        flowPane.setSize(flowPane.getPreferredSize());
+        flowPane.validate();
+    }
+
+    public Graphics2D prepare(Component component, Graphics2D graphics) {
+        this.component = component;
+        this.graphics = graphics;
+
+        return graphics;
+    }
+
+    public void update() {
+        int width = component.getWidth();
+        int height = component.getHeight();
+
+        double sinTheta = Math.sin(theta);
+        double cosTheta = Math.cos(theta);
+
+        Graphics2D watermarkGraphics = (Graphics2D)graphics.create();
+        watermarkGraphics.setComposite(AlphaComposite.getInstance
+            (AlphaComposite.SRC_OVER, opacity));
+        watermarkGraphics.rotate(theta);
+
+        // Calculate the separation in between each repetition of the watermark
+        int dX = (int)(1.5 * flowPane.getWidth());
+        int dY = 2 * flowPane.getHeight();
+
+        // Prepare the origin of our graphics context
+        int x = 0;
+        int y = (int)(-width * sinTheta);
+        watermarkGraphics.translate(x, y);
+
+        for (int yStop = (int)(height * cosTheta), p = 0; y < yStop; y += dY, p = 1 - p) {
+            for (int xStop = (int)(height * sinTheta + width * cosTheta); x < xStop; x += dX) {
+                flowPane.paint(watermarkGraphics);
+                watermarkGraphics.translate(dX, 0);
+            }
+
+            // Move X origin back to its starting position & Y origin down
+            watermarkGraphics.translate(-x, dY);
+            x = 0;
+
+            // Shift the x back and forth to add randomness feel to pattern
+            watermarkGraphics.translate((int)((0.5f - p) * flowPane.getWidth()), 0);
+        }
+
+        watermarkGraphics.dispose();
+    }
+
+    public Bounds getAffectedArea(Component component, int x, int y, int width, int height) {
+        return new Bounds(x, y, width, height);
+    }
+}

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/easing/Circular.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/easing/Circular.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/easing/Circular.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/easing/Circular.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2003 Robert Penner, all rights reserved.
+ *
+ * This work is subject to the terms in
+ * http://www.robertpenner.com/easing_terms_of_use.html.
+ *
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk.effects.easing;
+
+/**
+ * Circular easing operation.
+ *
+ * @author Robert Penner
+ * @author gbrown
+ */
+public class Circular implements Easing {
+    public float easeIn(float time, float begin, float change, float duration) {
+        return -change * ((float)Math.sqrt(1f - (time /= duration) * time) - 1f) + begin;
+    }
+
+    public float easeOut(float time, float begin, float change, float duration) {
+        return change * (float)Math.sqrt(1f - (time = time / duration - 1f) * time) + begin;
+    }
+
+    public float easeInOut(float time, float begin, float change, float duration) {
+        if ((time /= duration / 2f) < 1f) {
+            return -change / 2f * ((float)Math.sqrt(1f - time * time) - 1f) + begin;
+        } else {
+            return change / 2f * ((float)Math.sqrt(1f - (time -= 2f) * time) + 1f) + begin;
+        }
+    }
+}

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/easing/Cubic.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/easing/Cubic.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/easing/Cubic.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/easing/Cubic.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2003 Robert Penner, all rights reserved.
+ *
+ * This work is subject to the terms in
+ * http://www.robertpenner.com/easing_terms_of_use.html.
+ *
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk.effects.easing;
+
+/**
+ * Cubic easing operation.
+ *
+ * @author Robert Penner
+ * @author gbrown
+ */
+public class Cubic implements Easing {
+    public float easeIn(float time, float begin, float change, float duration) {
+        return change * (time /= duration) * time * time + begin;
+    }
+
+    public float easeOut(float time, float begin, float change, float duration) {
+        return change * ((time = time / duration - 1f) * time * time + 1f) + begin;
+    }
+
+    public float easeInOut(float time, float begin, float change, float duration) {
+        if ((time /= duration / 2f) < 1f) {
+            return change / 2f * time * time * time + begin;
+        } else {
+            return change / 2f * ((time -= 2f) * time * time + 2f) + begin;
+        }
+    }
+}

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/easing/Easing.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/easing/Easing.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/easing/Easing.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/easing/Easing.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2003 Robert Penner, all rights reserved.
+ *
+ * This work is subject to the terms in
+ * http://www.robertpenner.com/easing_terms_of_use.html.
+ *
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk.effects.easing;
+
+/**
+ * Base interface for easing operations.
+ *
+ * @author Robert Penner
+ * @author gbrown
+ */
+public interface Easing {
+    public float easeIn(float time, float begin, float change, float duration);
+    public float easeOut(float time, float begin, float change, float duration);
+    public float easeInOut(float time, float begin, float change, float duration);
+}

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/easing/Exponential.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/easing/Exponential.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/easing/Exponential.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/easing/Exponential.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2003 Robert Penner, all rights reserved.
+ *
+ * This work is subject to the terms in
+ * http://www.robertpenner.com/easing_terms_of_use.html.
+ *
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk.effects.easing;
+
+/**
+ * Exponential easing operation.
+ *
+ * @author Robert Penner
+ * @author gbrown
+ */
+public class Exponential implements Easing {
+    public float easeIn(float time, float begin, float change, float duration) {
+        return (time == 0) ? begin
+            : change * (float)Math.pow(2, 10 * (time / duration - 1f)) + begin;
+    }
+
+    public float easeOut(float time, float begin, float change, float duration) {
+        return (time == duration) ? begin + change
+            : change * ((float)-Math.pow(2, -10 * time / duration) + 1f) + begin;
+    }
+
+    public float easeInOut(float time, float begin, float change, float duration) {
+        if (time == 0) {
+            return begin;
+        }
+
+        if (time == duration) {
+            return begin + change;
+        }
+
+        if ((time /= duration / 2f) < 1) {
+            return change / 2f * (float)Math.pow(2, 10 * (time - 1)) + begin;
+        }
+
+        return change / 2f * ((float)-Math.pow(2, -10 * --time) + 2) + begin;
+    }
+}

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/easing/Linear.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/easing/Linear.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/easing/Linear.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/easing/Linear.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2003 Robert Penner, all rights reserved.
+ *
+ * This work is subject to the terms in
+ * http://www.robertpenner.com/easing_terms_of_use.html.
+ *
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk.effects.easing;
+
+/**
+ * Linear easing operation.
+ *
+ * @author Robert Penner
+ * @author gbrown
+ */
+public class Linear implements Easing {
+    public float easeIn(float time, float begin, float change, float duration) {
+        return change * time / duration + begin;
+    }
+
+    public float easeOut(float time, float begin, float change, float duration) {
+        return change * time / duration + begin;
+    }
+
+    public float easeInOut(float time, float begin, float change, float duration) {
+        return change * time / duration + begin;
+    }
+}

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/easing/Quadratic.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/easing/Quadratic.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/easing/Quadratic.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/easing/Quadratic.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2003 Robert Penner, all rights reserved.
+ *
+ * This work is subject to the terms in
+ * http://www.robertpenner.com/easing_terms_of_use.html.
+ *
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk.effects.easing;
+
+/**
+ * Quadratic easing operation.
+ *
+ * @author Robert Penner
+ * @author gbrown
+ */
+public class Quadratic implements Easing {
+    public float easeIn(float time, float begin, float change, float duration) {
+        return change * (time /= duration) * time + begin;
+    }
+
+    public float easeOut(float time, float begin, float change, float duration) {
+        return -change * (time /= duration) * (time - 2) + begin;
+    }
+
+    public float easeInOut(float time, float begin, float change, float duration) {
+        if ((time /= duration / 2) < 1) {
+            return change / 2 * time * time + begin;
+        } else {
+            return -change / 2 * ((--time) * (time - 2) - 1) + begin;
+        }
+    }
+}

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/easing/Quartic.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/easing/Quartic.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/easing/Quartic.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/easing/Quartic.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2003 Robert Penner, all rights reserved.
+ *
+ * This work is subject to the terms in
+ * http://www.robertpenner.com/easing_terms_of_use.html.
+ *
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk.effects.easing;
+
+/**
+ * Quartic easing operation.
+ *
+ * @author Robert Penner
+ * @author gbrown
+ */
+public class Quartic implements Easing {
+    public float easeIn(float time, float begin, float change, float duration) {
+        return change * (time /= duration) * time * time * time + begin;
+    }
+
+    public float easeOut(float time, float begin, float change, float duration) {
+        return -change * ((time = time / duration - 1) * time * time * time - 1) + begin;
+    }
+
+    public float easeInOut(float time, float begin, float change, float duration) {
+        if ((time /= duration / 2f) < 1) {
+            return change / 2f * time * time * time * time + begin;
+        } else {
+            return -change / 2f * ((time -= 2) * time * time * time - 2) + begin;
+        }
+    }
+}

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/easing/Quintic.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/easing/Quintic.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/easing/Quintic.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/easing/Quintic.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2003 Robert Penner, all rights reserved.
+ *
+ * This work is subject to the terms in
+ * http://www.robertpenner.com/easing_terms_of_use.html.
+ *
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk.effects.easing;
+
+/**
+ * Quintic easing operation.
+ *
+ * @author Robert Penner
+ * @author gbrown
+ */
+public class Quintic implements Easing {
+    public float easeIn(float time, float begin, float change, float duration) {
+        return change * (time /= duration) * time * time * time * time + begin;
+    }
+
+    public float easeOut(float time, float begin, float change, float duration) {
+        return change * ((time = time / duration - 1) * time * time * time * time + 1) + begin;
+    }
+
+    public float easeInOut(float time, float begin, float change, float duration) {
+        if ((time /= duration / 2f) < 1) {
+            return change / 2f * time * time * time * time * time + begin;
+        } else {
+            return change / 2f * ((time -= 2) * time * time * time * time + 2) + begin;
+        }
+    }
+}

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/easing/Sine.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/easing/Sine.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/easing/Sine.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/easing/Sine.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2003 Robert Penner, all rights reserved.
+ *
+ * This work is subject to the terms in
+ * http://www.robertpenner.com/easing_terms_of_use.html.
+ *
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk.effects.easing;
+
+/**
+ * Easing operation based on a sine curve.
+ *
+ * @author Robert Penner
+ * @author gbrown
+ */
+public class Sine {
+    public float easeIn(float time, float begin, float change, float duration) {
+        return -change * (float)Math.cos(time / duration * (Math.PI/2)) + change + begin;
+    }
+
+    public float easeOut(float time, float begin, float change, float duration) {
+        return change * (float)Math.sin(time / duration * (Math.PI/2)) + begin;
+    }
+
+    public float easeInOut(float time, float begin, float change, float duration) {
+        return -change / 2f * (float)(Math.cos(Math.PI * time / duration) - 1) + begin;
+    }
+}

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/easing/package.html
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/easing/package.html?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/easing/package.html (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/easing/package.html Mon Mar 16 16:36:10 2009
@@ -0,0 +1,6 @@
+<html>
+<head></head>
+<body>
+<p>Contains "easing" operations for producing natural-looking transitions. Based on easing equations developed by <a href="http://robertpenner.com/">Robert Penner</a>.</p>
+</body>
+</html>

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/package.html
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/package.html?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/package.html (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/effects/package.html Mon Mar 16 16:36:10 2009
@@ -0,0 +1,6 @@
+<html>
+<head></head>
+<body>
+<p>Contains classes supporting visual effects such as blurs, reflections, and drop shadows.</p>
+</body>
+</html>

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/media/BufferedImageSerializer.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/media/BufferedImageSerializer.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/media/BufferedImageSerializer.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/media/BufferedImageSerializer.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk.media;
+
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import javax.imageio.ImageIO;
+
+import pivot.serialization.SerializationException;
+import pivot.serialization.Serializer;
+
+/**
+ * Implementation of the {@link Serializer} interface that reads and writes
+ * instances of {@link java.awt.image.BufferedImage}.
+ *
+ * @author tvolkert
+ */
+public class BufferedImageSerializer implements Serializer {
+    /**
+     * Supported image formats.
+     *
+     * @author tvolkert
+     */
+    public static enum Format {
+        PNG("png", "image/png"),
+        JPEG("jpeg", "image/jpeg"),
+        BMP("bmp", "image/bmp"),
+        WBMP("wbmp", "image/vnd.wap.wbmp"),
+        GIF("gif", "image/gif");
+
+        private String name;
+        private String mimeType;
+
+        private Format(String name, String mimeType) {
+            this.name = name;
+            this.mimeType = mimeType;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public String getMimeType() {
+            return mimeType;
+        }
+    }
+
+    private Format outputFormat;
+
+    public BufferedImageSerializer() {
+        this(Format.PNG);
+    }
+
+    public BufferedImageSerializer(Format outputFormat) {
+        setOutputFormat(outputFormat);
+    }
+
+    /**
+     * Gets the image format that this serializer is using for output.
+     */
+    public Format getOutputFormat() {
+        return outputFormat;
+    }
+
+    /**
+     * Sets the image format that this serializer should use for output.
+     */
+    public void setOutputFormat(Format outputFormat) {
+        if (outputFormat == null) {
+            throw new IllegalArgumentException("Output format is null.");
+        }
+
+        this.outputFormat = outputFormat;
+    }
+
+    /**
+     * Reads a serialized image from an input stream.
+     *
+     * @return
+     * A <tt>BufferedImage</tt> object
+     */
+    public Object readObject(InputStream inputStream) throws IOException,
+        SerializationException {
+        if (inputStream == null) {
+            throw new IllegalArgumentException("inputStream is null.");
+        }
+
+        BufferedImage bufferedImage = ImageIO.read(inputStream);
+        return bufferedImage;
+    }
+
+
+    /**
+     * Writes a buffered image to an output stream.
+     */
+    public void writeObject(Object object, OutputStream outputStream)
+        throws IOException, SerializationException {
+        if (object == null) {
+            throw new IllegalArgumentException("object is null.");
+        }
+
+        if (outputStream == null) {
+            throw new IllegalArgumentException("outputStream is null.");
+        }
+
+        BufferedImage bufferedImage = (BufferedImage)object;
+        ImageIO.write(bufferedImage, outputFormat.getName(), outputStream);
+    }
+
+    public String getMIMEType() {
+        return outputFormat.getMimeType();
+    }
+}

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/media/Drawing.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/media/Drawing.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/media/Drawing.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/media/Drawing.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk.media;
+
+import java.awt.Graphics2D;
+import pivot.wtk.Bounds;
+import pivot.wtk.media.drawing.Group;
+
+/**
+ * Image representing a vector drawing.
+ *
+ * @author gbrown
+ */
+public class Drawing extends Image {
+    private Group shapes = new Group();
+
+    public int getWidth() {
+        Bounds bounds = shapes.getBounds();
+        return bounds.width + bounds.x;
+    }
+
+    public int getHeight() {
+        Bounds bounds = shapes.getBounds();
+        return bounds.height + bounds.y;
+    }
+
+    public void paint(Graphics2D graphics) {
+        graphics.clipRect(0, 0, getWidth(), getHeight());
+        shapes.paint(graphics);
+    }
+
+    public Group getShapes() {
+        return shapes;
+    }
+}

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/media/Image.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/media/Image.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/media/Image.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/media/Image.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk.media;
+
+import java.awt.image.BufferedImage;
+import java.io.BufferedInputStream;
+import java.io.InputStream;
+import java.net.URL;
+import pivot.util.concurrent.Dispatcher;
+import pivot.util.concurrent.Task;
+import pivot.util.concurrent.TaskListener;
+import pivot.util.concurrent.TaskExecutionException;
+import pivot.wtk.Dimensions;
+import pivot.wtk.Visual;
+
+/**
+ * Abstract base class for images. An image is either a bitmapped "picture"
+ * or a vector "drawing".
+ *
+ * @author gbrown
+ */
+public abstract class Image implements Visual {
+    /**
+     * Task that executes an image load operation.
+     *
+     * @author gbrown
+     */
+    public static class LoadTask extends Task<Image> {
+        private URL url = null;
+
+        public LoadTask(URL url) {
+            super();
+            this.url = url;
+        }
+
+        public LoadTask(URL url, Dispatcher dispatcher) {
+            super(dispatcher);
+            this.url = url;
+        }
+
+        @Override
+        public Image execute() throws TaskExecutionException {
+            Image image = null;
+
+            try {
+                InputStream inputStream = null;
+
+                try {
+                    // NOTE We don't open the stream until the callback
+                    // executes because this is a potentially time-consuming
+                    // operation
+                    inputStream = new BufferedInputStream(url.openStream());
+
+                    // TODO Need a way to identify the type of image to load
+                    // (picture or drawing) - an argument/property may be
+                    // appropriate. If the attribute is optional, we can try to
+                    // determine the type from the file extension in the URL, or
+                    // by looking at the first few bytes of the input stream.
+
+                    // TODO Use a monitored input stream here, similar to
+                    // the one used in web queries. This will allow us to abort
+                    // and time out image load operations.
+                    BufferedImageSerializer serializer = new BufferedImageSerializer();
+                    BufferedImage bufferedImage = (BufferedImage)serializer.readObject(inputStream);
+                    image = new Picture(bufferedImage);
+                } finally {
+                    if (inputStream != null) {
+                        inputStream.close();
+                    }
+                }
+            } catch(Exception exception) {
+                throw new TaskExecutionException(exception);
+            }
+
+            return image;
+        }
+    }
+
+    public Dimensions getSize() {
+        return new Dimensions(getWidth(), getHeight());
+    }
+
+    public static Image load(URL url) {
+        LoadTask loadTask = new LoadTask(url);
+
+        Image image = null;
+        try {
+            image = loadTask.execute();
+        } catch(TaskExecutionException exception) {
+            throw new RuntimeException(exception);
+        }
+
+        return image;
+    }
+
+    public static Image.LoadTask load(URL url, TaskListener<Image> loadListener) {
+        LoadTask loadTask = new LoadTask(url);
+        loadTask.execute(loadListener);
+        return loadTask;
+    }
+}

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/media/Picture.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/media/Picture.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/media/Picture.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/media/Picture.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk.media;
+
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+
+/**
+ * Image representing a bitmapped picture.
+ *
+ * @author gbrown
+ */
+public class Picture extends Image {
+    private BufferedImage bufferedImage = null;
+
+    public Picture(BufferedImage bufferedImage) {
+        if (bufferedImage == null) {
+            throw new IllegalArgumentException("bufferedImage is null.");
+        }
+
+        this.bufferedImage = bufferedImage;
+    }
+
+    public int getWidth() {
+        return bufferedImage.getWidth();
+    }
+
+    public int getHeight() {
+        return bufferedImage.getHeight();
+    }
+
+    public void paint(Graphics2D graphics) {
+        graphics.drawImage(bufferedImage, 0, 0, null);
+    }
+
+    public BufferedImage getBufferedImage() {
+        return bufferedImage;
+    }
+}

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/media/drawing/Clone.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/media/drawing/Clone.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/media/drawing/Clone.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/media/drawing/Clone.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk.media.drawing;
+
+import java.awt.Graphics2D;
+
+import pivot.wtk.Bounds;
+
+/**
+ * Shape representing a copy of another shape.
+ * <p>
+ * TODO Throw in setStroke() and setFill()?
+ */
+public class Clone extends Shape {
+    private Shape source = null;
+
+    public Shape getSource() {
+        return source;
+    }
+
+    public void setSource(Shape source) {
+        this.source = source;
+    }
+
+    @Override
+    public Bounds getUntransformedBounds() {
+        return (source == null) ? new Bounds(0, 0, 0, 0) : source.getUntransformedBounds();
+    }
+
+    @Override
+    public void fill(Graphics2D graphics) {
+        if (source != null) {
+            source.fill(graphics);
+        }
+    }
+
+    @Override
+    public void stroke(Graphics2D graphics) {
+        if (source != null) {
+            source.stroke(graphics);
+        }
+    }
+
+    @Override
+    public boolean contains(int x, int y) {
+        return (source == null) ? false : source.contains(x, y);
+    }
+}

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/media/drawing/Group.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/media/drawing/Group.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/media/drawing/Group.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/media/drawing/Group.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk.media.drawing;
+
+import java.awt.Graphics2D;
+import java.util.Iterator;
+
+import pivot.collections.ArrayList;
+import pivot.collections.Sequence;
+import pivot.util.ImmutableIterator;
+import pivot.wtk.Bounds;
+
+/**
+ * Shape representing a collection of other shapes.
+ * <p>
+ * TODO Throw in setStroke() and setFill()?
+ */
+public class Group extends Shape implements Sequence<Shape>, Iterable<Shape> {
+    private ArrayList<Shape> shapes = new ArrayList<Shape>();
+
+    public Bounds getUntransformedBounds() {
+        // TODO
+        return null;
+    }
+
+    public void paint(Graphics2D graphics) {
+        for (Shape shape : this) {
+            Graphics2D shapeGraphics = (Graphics2D)graphics.create();
+
+            // TODO Translate to origin, then apply transform to graphics
+
+            // TODO Only paint if shape bounds intersects clip bounds
+
+            shape.paint(shapeGraphics);
+            shapeGraphics.dispose();
+        }
+    }
+
+    public void fill(Graphics2D graphics) {
+        // No-op
+    }
+
+    public void stroke(Graphics2D graphics) {
+        // No-op
+    }
+
+    public int add(Shape shape) {
+        int index = shapes.getLength();
+        insert(shape, index);
+
+        return index;
+    }
+
+    public void insert(Shape shape, int index) {
+        shapes.insert(shape, index);
+
+        // TODO Set parent
+        // TODO Update bounds
+    }
+
+    public Shape update(int index, Shape shape) {
+        Shape previousShape = shapes.update(index, shape);
+
+        // TODO Set parent
+        // TODO Update bounds
+
+        return previousShape;
+    }
+
+    public int remove(Shape shape) {
+        int index = shapes.indexOf(shape);
+
+        if (index != -1) {
+            remove(index, 1);
+        }
+
+        return index;
+    }
+
+    public Sequence<Shape> remove(int index, int count) {
+        Sequence<Shape> removed = shapes.remove(index, count);
+
+        // TODO Clear parent
+        // TODO Update bounds
+
+        return removed;
+    }
+
+    public Shape get(int index) {
+        return shapes.get(index);
+    }
+
+    public int indexOf(Shape shape) {
+        return shapes.indexOf(shape);
+    }
+
+    public int getLength() {
+        return shapes.getLength();
+    }
+
+    @Override
+    public boolean contains(int x, int y) {
+        // TODO
+        return false;
+    }
+
+    public Shape getShapeAt(int x, int y) {
+        // TODO Walk shape list from top to bottom; if shape bounds contains
+        // x, y, call contains() on the shape
+        return null;
+    }
+
+    public Shape getDescendantAt(int x, int y) {
+        // TODO Mirror behavior of Container#getDescendantAt()
+        return null;
+    }
+
+    public Iterator<Shape> iterator() {
+        return new ImmutableIterator<Shape>(shapes.iterator());
+    }
+}

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/media/drawing/Rectangle.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/media/drawing/Rectangle.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/media/drawing/Rectangle.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/media/drawing/Rectangle.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk.media.drawing;
+
+import java.awt.Graphics2D;
+
+import pivot.wtk.Bounds;
+import pivot.wtk.Dimensions;
+
+/**
+ * Shape representing a rectangle.
+ *
+ * @author gbrown
+ */
+public class Rectangle extends Shape {
+    private int width = 0;
+    private int height = 0;
+
+    public int getWidth() {
+        return width;
+    }
+
+    public void setWidth(int width) {
+        if (width < 0) {
+            throw new IllegalArgumentException("width is null.");
+        }
+
+        this.width = width;
+    }
+
+    public int getHeight() {
+        return height;
+    }
+
+    public void setHeight(int height) {
+        if (height < 0) {
+            throw new IllegalArgumentException("height is null.");
+        }
+
+        this.height = height;
+    }
+
+    public Dimensions getSize() {
+        return new Dimensions(getWidth(), getHeight());
+    }
+
+    public void setSize(int width, int height) {
+        setWidth(width);
+        setHeight(height);
+    }
+
+    public void setSize(Dimensions size) {
+        if (size == null) {
+            throw new IllegalArgumentException("size is null.");
+        }
+
+        setSize(size.width, size.height);
+    }
+
+    @Override
+    public Bounds getUntransformedBounds() {
+        return new Bounds(getX(), getY(), width, height);
+    }
+
+    @Override
+    public void fill(Graphics2D graphics) {
+        graphics.fillRect(getX(), getY(), width, height);
+    }
+
+    @Override
+    public void stroke(Graphics2D graphics) {
+        graphics.drawRect(getX(), getY(), width, height);
+    }
+
+    @Override
+    public boolean contains(int x, int y) {
+        // TODO
+        return false;
+    }
+}

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/media/drawing/Rotation.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/media/drawing/Rotation.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/media/drawing/Rotation.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/media/drawing/Rotation.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk.media.drawing;
+
+/**
+ * Transform representing a rotation.
+ * <p>
+ * TODO Allow caller to specify angle in degrees or radians.
+ */
+public class Rotation extends Transform {
+    private float angle = 0f;
+
+    public float getAngle() {
+        return angle;
+    }
+
+    public void setAngle(float angle) {
+        this.angle = angle;
+    }
+
+    public float[][] getMatrix() {
+        // TODO
+        return null;
+    }
+}