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 [15/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/ComponentLayoutListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/ComponentLayoutListener.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/ComponentLayoutListener.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/ComponentLayoutListener.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,40 @@
+/*
+ * 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;
+
+/**
+ * Component layout listener interface.
+ *
+ * @author gbrown
+ */
+public interface ComponentLayoutListener {
+    /**
+     * Called when a component's preferred size has changed.
+     *
+     * @param component
+     * @param previousPreferredWidth
+     * @param previousPreferredHeight
+     */
+    public void preferredSizeChanged(Component component,
+        int previousPreferredWidth, int previousPreferredHeight);
+
+    /**
+     * Called when a component's displayable flag has changed.
+     *
+     * @param component
+     */
+    public void displayableChanged(Component component);
+}

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/ComponentListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/ComponentListener.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/ComponentListener.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/ComponentListener.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,82 @@
+/*
+ * 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;
+
+/**
+ * Component listener interface.
+ *
+ * @author gbrown
+ */
+public interface ComponentListener {
+    /**
+     * Called when a component's parent has changed (when the component is
+     * either added to or removed from a container).
+     *
+     * @param component
+     * @param previousParent
+     */
+    public void parentChanged(Component component, Container previousParent);
+
+    /**
+     * Called when a component's size has changed.
+     *
+     * @param component
+     * @param previousWidth
+     * @param previousHeight
+     */
+    public void sizeChanged(Component component, int previousWidth, int previousHeight);
+
+    /**
+     * Called when a component's location has changed.
+     *
+     * @param component
+     * @param previousX
+     * @param previousY
+     */
+    public void locationChanged(Component component, int previousX, int previousY);
+
+    /**
+     * Called when a component's visible flag has changed.
+     *
+     * @param component
+     */
+    public void visibleChanged(Component component);
+
+    /**
+     * Called when a component style has been updated.
+     *
+     * @param component
+     * @param styleKey
+     * @param previousValue
+     */
+    public void styleUpdated(Component component, String styleKey, Object previousValue);
+
+    /**
+     * Called when a component's cursor has changed.
+     *
+     * @param component
+     * @param previousCursor
+     */
+    public void cursorChanged(Component component, Cursor previousCursor);
+
+    /**
+     * Called when a component's tooltip text has changed.
+     *
+     * @param component
+     * @param previousTooltipText
+     */
+    public void tooltipTextChanged(Component component, String previousTooltipText);
+}

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/ComponentMouseButtonListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/ComponentMouseButtonListener.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/ComponentMouseButtonListener.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/ComponentMouseButtonListener.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,62 @@
+/*
+ * 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;
+
+/**
+ * Component mouse button listener interface.
+ *
+ * @author gbrown
+ */
+public interface ComponentMouseButtonListener {
+    /**
+     * Called when a mouse button is pressed over a component.
+     *
+     * @param component
+     * @param button
+     * @param x
+     * @param y
+     *
+     * @return
+     * <tt>true</tt> to consume the event; <tt>false</tt> to allow it to
+     * propagate.
+     */
+    public boolean mouseDown(Component component, Mouse.Button button, int x, int y);
+
+    /**
+     * Called when a mouse button is released over a component.
+     *
+     * @param component
+     * @param button
+     * @param x
+     * @param y
+     *
+     * @return
+     * <tt>true</tt> to consume the event; <tt>false</tt> to allow it to
+     * propagate.
+     */
+    public boolean mouseUp(Component component, Mouse.Button button, int x, int y);
+
+    /**
+     * Called when a mouse button is clicked over a component.
+     *
+     * @param component
+     * @param button
+     * @param x
+     * @param y
+     * @param count
+     */
+    public void mouseClick(Component component, Mouse.Button button, int x, int y, int count);
+}

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/ComponentMouseListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/ComponentMouseListener.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/ComponentMouseListener.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/ComponentMouseListener.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;
+
+/**
+ * Component mouse listener interface. Component mouse events are "bubbling"
+ * and are fired as the event propagates up the component hierarchy.
+ *
+ * @author gbrown
+ */
+public interface ComponentMouseListener {
+    /**
+     * Called when the mouse is moved over a component.
+     *
+     * @param component
+     * @param x
+     * @param y
+     *
+     * @return
+     * <tt>true</tt> to consume the event; <tt>false</tt> to allow it to
+     * propagate.
+     */
+    public boolean mouseMove(Component component, int x, int y);
+
+    /**
+     * Called when the mouse enters a component.
+     *
+     * @param component
+     */
+    public void mouseOver(Component component);
+
+    /**
+     * Called when the mouse exits a component.
+     *
+     * @param component
+     */
+    public void mouseOut(Component component);
+}
+

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/ComponentMouseWheelListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/ComponentMouseWheelListener.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/ComponentMouseWheelListener.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/ComponentMouseWheelListener.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,40 @@
+/*
+ * 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;
+
+/**
+ * Component mouse wheel listener interface.
+ *
+ * @author gbrown
+ */
+public interface ComponentMouseWheelListener {
+    /**
+     * Called when the mouse wheel is scrolled over a component.
+     *
+     * @param component
+     * @param scrollType
+     * @param scrollAmount
+     * @param wheelRotation
+     * @param x
+     * @param y
+     *
+     * @return
+     * <tt>true</tt> to consume the event; <tt>false</tt> to allow it to
+     * propagate.
+     */
+    public boolean mouseWheel(Component component, Mouse.ScrollType scrollType,
+        int scrollAmount, int wheelRotation, int x, int y);
+}

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/ComponentStateListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/ComponentStateListener.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/ComponentStateListener.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/ComponentStateListener.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,72 @@
+/*
+ * 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;
+
+import pivot.util.Vote;
+
+/**
+ * Component state listener interface.
+ *
+ * @author gbrown
+ * @author tvolkert
+ */
+public interface ComponentStateListener {
+    /**
+     * Called to preview an enabled change event.
+     *
+     * @param component
+     */
+    public Vote previewEnabledChange(Component component);
+
+    /**
+     * Called when a enabled change event has been vetoed.
+     *
+     * @param component
+     * @param reason
+     */
+    public void enabledChangeVetoed(Component component, Vote reason);
+
+    /**
+     * Called when a component's enabled state has changed.
+     *
+     * @param component
+     */
+    public void enabledChanged(Component component);
+
+    /**
+     * Called to preview a focused change event.
+     *
+     * @param component
+     * @param temporary
+     */
+    public Vote previewFocusedChange(Component component, boolean temporary);
+
+    /**
+     * Called when a focused change event has been vetoed.
+     *
+     * @param component
+     * @param reason
+     */
+    public void focusedChangeVetoed(Component component, Vote reason);
+
+    /**
+     * Called when a component's focused state has changed.
+     *
+     * @param component
+     * @param temporary
+     */
+    public void focusedChanged(Component component, boolean temporary);
+}

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/Component_Red.png
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/Component_Red.png?rev=754936&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/Component_Red.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/ConstrainedVisual.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/ConstrainedVisual.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/ConstrainedVisual.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/ConstrainedVisual.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,41 @@
+package pivot.wtk;
+
+/**
+ * Interface representing a visual that is used in layout.
+ *
+ * @author gbrown
+ */
+public interface ConstrainedVisual extends Visual {
+    /**
+     * Sets the visual's render size.
+     *
+     * @param width
+     * @param height
+     */
+    public void setSize(int width, int height);
+
+    /**
+     * Returns the visual's preferred width given the provided height
+     * constraint.
+     *
+     * @param height
+     * The height by which to constrain the preferred width, or <tt>-1</tt>
+     * for no constraint.
+     */
+    public int getPreferredWidth(int height);
+
+    /**
+     * Returns the visual's preferred height given the provided width
+     * constraint.
+     *
+     * @param width
+     * The width by which to constrain the preferred height, or <tt>-1</tt>
+     * for no constraint.
+     */
+    public int getPreferredHeight(int width);
+
+    /**
+     * Returns the visual's unconstrained preferred size.
+     */
+    public Dimensions getPreferredSize();
+}

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/Container.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/Container.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/Container.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/Container.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,690 @@
+/*
+ * 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;
+
+import java.awt.Graphics2D;
+import java.util.Iterator;
+
+import pivot.collections.ArrayList;
+import pivot.collections.Dictionary;
+import pivot.collections.Map;
+import pivot.collections.Sequence;
+import pivot.util.ImmutableIterator;
+import pivot.util.ListenerList;
+
+/**
+ * Abstract base class for containers.
+ * <p>
+ * NOTES:
+ * <ul>
+ * <li>Child components that have special meaning to a container should be
+ * installed via a dedicated method (for example,
+ * {@link pivot.wtk.Window#setContent(Component)}); additional components may
+ * be added by the skin when installed. Other components may still be added but
+ * may not be rendered properly by the installed skin.</li>
+ * <li>Callers should not rely on component position within container to mean
+ * anything other than paint order.</li>
+ * </ul>
+ *
+ * @author gbrown
+ */
+@ComponentInfo(icon="Container.png")
+public abstract class Container extends Component
+    implements Sequence<Component>, Iterable<Component> {
+    private static class ContainerListenerList extends ListenerList<ContainerListener>
+        implements ContainerListener {
+        public void componentInserted(Container container, int index) {
+            for (ContainerListener listener : this) {
+                listener.componentInserted(container, index);
+            }
+        }
+
+        public void componentsRemoved(Container container, int index, Sequence<Component> components) {
+            for (ContainerListener listener : this) {
+                listener.componentsRemoved(container, index, components);
+            }
+        }
+
+        public void contextKeyChanged(Container container, String previousContextKey) {
+            for (ContainerListener listener : this) {
+                listener.contextKeyChanged(container, previousContextKey);
+            }
+        }
+
+        public void focusTraversalPolicyChanged(Container container,
+            FocusTraversalPolicy previousFocusTraversalPolicy) {
+            for (ContainerListener listener : this) {
+                listener.focusTraversalPolicyChanged(container, previousFocusTraversalPolicy);
+            }
+        }
+    }
+
+    private static class ContainerMouseListenerList extends ListenerList<ContainerMouseListener>
+        implements ContainerMouseListener {
+        public void mouseMove(Container container, int x, int y) {
+            for (ContainerMouseListener listener : this) {
+                listener.mouseMove(container, x, y);
+            }
+        }
+
+        public void mouseDown(Container container, Mouse.Button button, int x, int y) {
+            for (ContainerMouseListener listener : this) {
+                listener.mouseDown(container, button, x, y);
+            }
+        }
+
+        public void mouseUp(Container container, Mouse.Button button, int x, int y) {
+            for (ContainerMouseListener listener : this) {
+                listener.mouseUp(container, button, x, y);
+            }
+        }
+
+        public void mouseWheel(Container container, Mouse.ScrollType scrollType,
+            int scrollAmount, int wheelRotation, int x, int y) {
+            for (ContainerMouseListener listener : this) {
+                listener.mouseWheel(container, scrollType, scrollAmount, wheelRotation, x, y);
+            }
+        }
+    }
+
+    // TODO A linked list may be more efficient than an array list; it would
+    // certainly optimize moveToTop() and moveToBottom() in Window, since
+    // an array list will need to perform a lot of copying as owned windows
+    // are removed from the list and appended to the end
+    private ArrayList<Component> components = new ArrayList<Component>();
+
+    private boolean valid = true;
+
+    private FocusTraversalPolicy focusTraversalPolicy = null;
+    private String contextKey = null;
+
+    private Component mouseOverComponent = null;
+
+    private Component mouseDownComponent = null;
+    private long mouseDownTime = 0;
+    private int mouseClickCount = 0;
+
+    private ContainerListenerList containerListeners = new ContainerListenerList();
+    private ContainerMouseListenerList containerMouseListeners = new ContainerMouseListenerList();
+
+    public final int add(Component component) {
+        int i = getLength();
+        insert(component, i);
+
+        return i;
+    }
+
+    public void insert(Component component, int index) {
+        if (component == null) {
+            throw new IllegalArgumentException("component is null.");
+        }
+
+        if (component == this) {
+            throw new IllegalArgumentException("Cannot add a container to itself.");
+        }
+
+        if (component.getParent() != null) {
+            throw new IllegalArgumentException("Component already has a parent.");
+        }
+
+        component.setParent(Container.this);
+        components.insert(component, index);
+
+        // Repaint the area occupied by the new component
+        component.repaint();
+
+        invalidate();
+
+        containerListeners.componentInserted(Container.this, index);
+    }
+
+    public Component update(int index, Component component) {
+        throw new UnsupportedOperationException();
+    }
+
+    public final int remove(Component component) {
+        int index = indexOf(component);
+        if (index != -1) {
+            remove(index, 1);
+        }
+
+        return index;
+    }
+
+    public Sequence<Component> remove(int index, int count) {
+        Sequence<Component> removed = components.remove(index, count);
+
+        if (count > 0) {
+            // Set the removed components' parent to null and repaint the area
+            // formerly occupied by the components
+            for (int i = 0, n = removed.getLength(); i < n; i++) {
+                Component component = removed.get(i);
+                component.repaint();
+                component.setParent(null);
+            }
+
+            invalidate();
+
+            containerListeners.componentsRemoved(Container.this, index, removed);
+        }
+
+        return removed;
+    }
+
+    public final Sequence<Component> removeAll() {
+        return remove(0, getLength());
+    }
+
+    public Component get(int index) {
+        return components.get(index);
+    }
+
+    public int indexOf(Component component) {
+        return components.indexOf(component);
+    }
+
+    public int getLength() {
+        return components.getLength();
+    }
+
+    public Iterator<Component> iterator() {
+        return new ImmutableIterator<Component>(components.iterator());
+    }
+
+    @Override
+    protected void setParent(Container parent) {
+        // If this container is being removed from the component hierarchy
+        // and contains the focused component, clear the focus
+        if (parent == null
+            && isAncestor(getFocusedComponent())) {
+            clearFocus(true);
+        }
+
+        super.setParent(parent);
+    }
+
+    public Component getComponentAt(int x, int y) {
+        Component component = null;
+
+        int i = components.getLength() - 1;
+        while (i >= 0) {
+            component = components.get(i);
+            if (component.isVisible()) {
+                Bounds bounds = component.getBounds();
+                if (bounds.contains(x, y)) {
+                    break;
+                }
+            }
+
+            i--;
+        }
+
+        if (i < 0) {
+            component = null;
+        }
+
+        return component;
+    }
+
+    public Component getDescendantAt(int x, int y) {
+        Component component = getComponentAt(x, y);
+
+        if (component instanceof Container) {
+            Container parent = (Container)component;
+            component = parent.getDescendantAt(x - component.getX(),
+                y - component.getY());
+
+            if (component == null) {
+                component = parent;
+            }
+        }
+
+        return component;
+    }
+
+    @Override
+    public void setVisible(boolean visible) {
+        if (!visible
+            && containsFocus()) {
+            clearFocus(true);
+        }
+
+        super.setVisible(visible);
+    }
+
+    @Override
+    public boolean isValid() {
+        return valid;
+    }
+
+    @Override
+    public void invalidate() {
+        if (valid) {
+            valid = false;
+            super.invalidate();
+        }
+    }
+
+    @Override
+    public void validate() {
+        if (!valid) {
+            try {
+                super.validate();
+
+                for (int i = 0, n = components.getLength(); i < n; i++) {
+                    Component component = components.get(i);
+                    component.validate();
+                }
+            } finally {
+                valid = true;
+            }
+        }
+    }
+
+    @Override
+    public void paint(Graphics2D graphics) {
+        // Give the base method a copy of the graphics context; otherwise,
+        // container skins can change the graphics state before it is passed
+        // to subcomponents
+        Graphics2D containerGraphics = (Graphics2D)graphics.create();
+        super.paint(containerGraphics);
+        containerGraphics.dispose();
+
+        java.awt.Rectangle clipBounds = graphics.getClipBounds();
+        Bounds paintBounds = (clipBounds == null) ?
+            new Bounds(0, 0, getWidth(), getHeight()) : new Bounds(clipBounds);
+
+        for (Component component : this) {
+            Bounds componentBounds = component.getBounds();
+
+            // Calculate the decorated bounds
+            Bounds affectedArea = new Bounds(0, 0, componentBounds.width, componentBounds.height);
+            for (Decorator decorator : component.getDecorators()) {
+                affectedArea.union(decorator.getAffectedArea(component, 0, 0,
+                    componentBounds.width, componentBounds.height));
+            }
+
+            affectedArea.x += componentBounds.x;
+            affectedArea.y += componentBounds.y;
+
+            // Only paint components that are visible and intersect the
+            // current clip rectangle
+            if (component.isVisible()
+                && affectedArea.intersects(paintBounds)) {
+                // Create a copy of the current graphics context and
+                // translate to the component's coordinate system
+                Graphics2D componentGraphics = (Graphics2D)graphics.create();
+                componentGraphics.translate(componentBounds.x, componentBounds.y);
+                componentGraphics.clipRect(0, 0, componentBounds.width, componentBounds.height);
+
+                // Prepare the decorators
+                Graphics2D decoratedGraphics = componentGraphics;
+
+                DecoratorSequence decorators = component.getDecorators();
+                int n = decorators.getLength();
+                for (int i = n - 1; i >= 0; i--) {
+                    Decorator decorator = decorators.get(i);
+                    decoratedGraphics = decorator.prepare(component, decoratedGraphics);
+                }
+
+                // Paint the component
+                component.paint(decoratedGraphics);
+
+                // Update the decorators
+                for (int i = 0; i < n; i++) {
+                    Decorator decorator = decorators.get(i);
+                    decorator.update();
+                }
+
+                // Dispose of the component's graphics
+                componentGraphics.dispose();
+            }
+        }
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+        if (isEnabled() != enabled) {
+            super.setEnabled(enabled);
+
+            if (isEnabled() == enabled) {
+                if (!enabled
+                    && containsFocus()) {
+                    clearFocus(true);
+                }
+            }
+        }
+    }
+
+    /**
+     * Unsupported for containers. Only leaf components can have tooltips.
+     */
+    public void setTooltip(String tooltip) {
+        throw new UnsupportedOperationException("A container cannot have a toolip.");
+    }
+
+    /**
+     * Tests if this container is an ancestor of a given component.
+     *
+     * @param component
+     * The component to test.
+     *
+     * @return
+     * <tt>true</tt> if this container is an ancestor of <tt>component</tt>;
+     * <tt>false</tt>, otherwise.
+     */
+    public boolean isAncestor(Component component) {
+        boolean ancestor = false;
+
+        Component parent = component;
+        while (parent != null) {
+           if (parent == this) {
+              ancestor = true;
+              break;
+           }
+
+           parent = parent.getParent();
+        }
+
+        return ancestor;
+     }
+
+    /**
+     * @return
+     * <tt>false</tt>; containers are not focusable.
+     */
+    @Override
+    public final boolean isFocusable() {
+        return false;
+    }
+
+    @Override
+    /**
+     * Requests that focus be set to the first focusable component in this
+     * container.
+     */
+    public void requestFocus() {
+        if (getLength() > 0) {
+            get(0).requestFocus();
+        }
+    }
+
+    /**
+     * Returns this container's focus traversal policy.
+     */
+    public FocusTraversalPolicy getFocusTraversalPolicy() {
+        return this.focusTraversalPolicy;
+    }
+
+    /**
+     * Sets this container's focus traversal policy.
+     *
+     * @param focusTraversalPolicy
+     * The focus traversal policy to use with this container.
+     */
+    public void setFocusTraversalPolicy(FocusTraversalPolicy focusTraversalPolicy) {
+        FocusTraversalPolicy previousFocusTraversalPolicy = this.focusTraversalPolicy;
+
+        if (previousFocusTraversalPolicy != focusTraversalPolicy) {
+            this.focusTraversalPolicy = focusTraversalPolicy;
+            containerListeners.focusTraversalPolicyChanged(this, previousFocusTraversalPolicy);
+        }
+    }
+
+    /**
+     * Tests whether this container is an ancestor of the currently focused
+     * component.
+     *
+     * @return
+     * <tt>true</tt> if a component is focused and this container is an
+     * ancestor of the component; <tt>false</tt>, otherwise.
+     */
+    public boolean containsFocus() {
+        Component focusedComponent = getFocusedComponent();
+        return (focusedComponent != null && isAncestor(focusedComponent));
+    }
+
+    /**
+     * Returns the container's context key.
+     *
+     * @return
+     * The context key, or <tt>null</tt> if no context key is set.
+     */
+    public String getContextKey() {
+        return contextKey;
+    }
+
+    /**
+     * Sets the component's context key.
+     *
+     * @param contextKey
+     * The context key, or <tt>null</tt> to clear the context.
+     */
+    public void setContextKey(String contextKey) {
+        String previousContextKey = this.contextKey;
+
+        if ((previousContextKey != null
+            && contextKey != null
+            && !previousContextKey.equals(contextKey))
+            || previousContextKey != contextKey) {
+            this.contextKey = contextKey;
+            containerListeners.contextKeyChanged(this, previousContextKey);
+        }
+    }
+
+    /**
+     * Propagates binding to subcomponents. If this container has a binding
+     * set, propagates the bound value as a nested context.
+     *
+     * @param context
+     */
+    @SuppressWarnings("unchecked")
+    public void load(Dictionary<String, Object> context) {
+        if (contextKey != null
+            && context.containsKey(contextKey)) {
+            context = (Map<String, Object>)context.get(contextKey);
+        }
+
+        for (Component component : components) {
+            component.load(context);
+        }
+    }
+
+    /**
+     * Propagates binding to subcomponents. If this container has a binding
+     * set, propagates the bound value as a nested context.
+     *
+     * @param context
+     */
+    @SuppressWarnings("unchecked")
+    public void store(Dictionary<String, Object> context) {
+        if (contextKey != null) {
+            // Bound value is expected to be a sub-context
+            context = (Map<String, Object>)context.get(contextKey);
+        }
+
+        for (Component component : components) {
+            component.store(context);
+        }
+    }
+
+    @Override
+    protected boolean mouseMove(int x, int y) {
+        boolean consumed = false;
+
+        if (isEnabled()) {
+            // Notify container listeners
+            containerMouseListeners.mouseMove(this, x, y);
+
+            // Clear the mouse over component if its visibility or enabled
+            // state has changed
+            if (mouseOverComponent != null
+                && !(mouseOverComponent.isEnabled() && mouseOverComponent.isVisible())) {
+                mouseOverComponent = null;
+            }
+
+            // Synthesize mouse over/out events
+            Component component = getComponentAt(x, y);
+
+            if (mouseOverComponent != component) {
+                if (mouseOverComponent != null) {
+                    mouseOverComponent.mouseOut();
+                }
+
+                mouseOverComponent = component;
+
+                if (mouseOverComponent != null) {
+                    mouseOverComponent.mouseOver();
+                }
+            }
+
+            // Propagate event to subcomponents
+            if (component != null) {
+                consumed = component.mouseMove(x - component.getX(),
+                    y - component.getY());
+            }
+
+            // Notify the base class
+            if (!consumed) {
+                consumed = super.mouseMove(x, y);
+            }
+        }
+
+        return consumed;
+    }
+
+    @Override
+    protected void mouseOut() {
+        // Ensure that mouse out is called on descendant components
+        if (mouseOverComponent != null) {
+            mouseOverComponent.mouseOut();
+            mouseOverComponent = null;
+        }
+
+        super.mouseOut();
+    }
+
+    @Override
+    protected boolean mouseDown(Mouse.Button button, int x, int y) {
+        boolean consumed = false;
+
+        if (isEnabled()) {
+            // Notify container listeners
+            containerMouseListeners.mouseDown(this, button, x, y);
+
+            // Synthesize mouse click event
+            Component component = getComponentAt(x, y);
+            mouseDownComponent = component;
+
+            long currentTime = System.currentTimeMillis();
+            int multiClickInterval = ApplicationContext.getMultiClickInterval();
+
+            if (currentTime - mouseDownTime > multiClickInterval) {
+                mouseDownTime = System.currentTimeMillis();
+                mouseClickCount = 1;
+            } else {
+                mouseClickCount++;
+            }
+
+            // Propagate event to subcomponents
+            if (component != null) {
+                consumed = component.mouseDown(button, x - component.getX(),
+                    y - component.getY());
+            }
+
+            // Notify the base class
+            if (!consumed) {
+                consumed = super.mouseDown(button, x, y);
+            }
+        }
+
+        return consumed;
+    }
+
+    @Override
+    protected boolean mouseUp(Mouse.Button button, int x, int y) {
+        boolean consumed = false;
+
+        if (isEnabled()) {
+            // Notify container listeners
+            containerMouseListeners.mouseUp(this, button, x, y);
+
+            // Clear the mouse down component if its visibility or enabled
+            // state has changed
+            if (mouseDownComponent != null
+                && !(mouseDownComponent.isEnabled() && mouseDownComponent.isVisible())) {
+                mouseDownComponent = null;
+            }
+
+            // Propagate event to subcomponents
+            Component component = getComponentAt(x, y);
+
+            if (component != null) {
+                consumed = component.mouseUp(button, x - component.getX(),
+                    y - component.getY());
+
+                // Synthesize mouse click event
+                if (component == mouseDownComponent) {
+                    component.mouseClick(button, x - component.getX(), y - component.getY(),
+                        mouseClickCount);
+                    mouseDownComponent = null;
+                }
+            }
+
+            // Notify the base class
+            if (!consumed) {
+                consumed = super.mouseUp(button, x, y);
+            }
+        }
+
+        return consumed;
+    }
+
+    @Override
+    protected boolean mouseWheel(Mouse.ScrollType scrollType, int scrollAmount,
+        int wheelRotation, int x, int y) {
+        boolean consumed = false;
+
+        if (isEnabled()) {
+            // Notify container listeners
+            containerMouseListeners.mouseWheel(this, scrollType, scrollAmount,
+                wheelRotation, x, y);
+
+            // Propagate event to subcomponents
+            Component component = getComponentAt(x, y);
+
+            if (component != null) {
+                consumed = component.mouseWheel(scrollType, scrollAmount, wheelRotation,
+                    x - component.getX(), y - component.getY());
+            }
+
+            // Notify the base class
+            if (!consumed) {
+                consumed = super.mouseWheel(scrollType, scrollAmount, wheelRotation, x, y);
+            }
+        }
+
+        return consumed;
+    }
+
+    public ListenerList<ContainerListener> getContainerListeners() {
+        return containerListeners;
+    }
+
+    public ListenerList<ContainerMouseListener> getContainerMouseListeners() {
+        return containerMouseListeners;
+    }
+}

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/Container.png
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/Container.png?rev=754936&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/Container.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/ContainerListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/ContainerListener.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/ContainerListener.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/ContainerListener.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;
+
+import pivot.collections.Sequence;
+
+/**
+ * Container listener interface.
+ *
+ * @author gbrown
+ */
+public interface ContainerListener  {
+    /**
+     * Called when a component has been inserted into a container's component
+     * sequence.
+     *
+     * @param container
+     * @param index
+     */
+    public void componentInserted(Container container, int index);
+
+    /**
+     * Called when components have been removed from a container's component
+     * sequence.
+     *
+     * @param container
+     * @param index
+     * @param removed
+     */
+    public void componentsRemoved(Container container, int index, Sequence<Component> removed);
+
+    /**
+     * Called when a container's context key has changed.
+     *
+     * @param container
+     * @param previousContextKey
+     */
+    public void contextKeyChanged(Container container, String previousContextKey);
+
+    /**
+     * Called when a container's focus traversal policy has changed.
+     *
+     * @param container
+     * @param previousFocusTraversalPolicy
+     */
+    public void focusTraversalPolicyChanged(Container container,
+        FocusTraversalPolicy previousFocusTraversalPolicy);
+}

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/ContainerMouseListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/ContainerMouseListener.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/ContainerMouseListener.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/ContainerMouseListener.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,66 @@
+/*
+ * 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;
+
+/**
+ * Container mouse listener interface. Container mouse events are "tunneling"
+ * events that are fired as the event propagates down the component hierarchy.
+ *
+ * @author gbrown
+ */
+public interface ContainerMouseListener {
+    /**
+     * Called when the mouse is moved over a container.
+     *
+     * @param container
+     * @param x
+     * @param y
+     */
+    public void mouseMove(Container container, int x, int y);
+
+    /**
+     * Called when the mouse is pressed over a container.
+     *
+     * @param container
+     * @param button
+     * @param x
+     * @param y
+     */
+    public void mouseDown(Container container, Mouse.Button button, int x, int y);
+
+    /**
+     * Called when the mouse is released over a container.
+     *
+     * @param container
+     * @param button
+     * @param x
+     * @param y
+     */
+    public void mouseUp(Container container, Mouse.Button button, int x, int y);
+
+    /**
+     * Called when the mouse wheel is scrolled over a container.
+     *
+     * @param container
+     * @param scrollType
+     * @param scrollAmount
+     * @param wheelRotation
+     * @param x
+     * @param y
+     */
+    public void mouseWheel(Container container, Mouse.ScrollType scrollType,
+        int scrollAmount, int wheelRotation, int x, int y);
+}

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/CornerRadii.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/CornerRadii.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/CornerRadii.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/CornerRadii.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,101 @@
+/*
+ * 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;
+
+import pivot.collections.Dictionary;
+
+/**
+ * Class representing the corner radii of a rectangular object.
+ *
+ * @author gbrown
+ */
+public class CornerRadii {
+    public int topLeft = 0;
+    public int topRight = 0;
+    public int bottomLeft = 0;
+    public int bottomRight = 0;
+
+    public static final String TOP_LEFT_KEY = "topLeft";
+    public static final String TOP_RIGHT_KEY = "topRight";
+    public static final String BOTTOM_LEFT_KEY = "bottomLeft";
+    public static final String BOTTOM_RIGHT_KEY = "bottomRight";
+
+    public CornerRadii() {
+    }
+
+    public CornerRadii(int radius) {
+        this(radius, radius, radius, radius);
+    }
+
+    public CornerRadii(Dictionary<String, ?> cornerRadii) {
+        if (cornerRadii == null) {
+            throw new IllegalArgumentException("cornerRadii is null.");
+        }
+
+        if (cornerRadii.containsKey(TOP_LEFT_KEY)) {
+            topLeft = (Integer)cornerRadii.get(TOP_LEFT_KEY);
+        }
+
+        if (cornerRadii.containsKey(TOP_RIGHT_KEY)) {
+            topRight = (Integer)cornerRadii.get(TOP_RIGHT_KEY);
+        }
+
+        if (cornerRadii.containsKey(BOTTOM_LEFT_KEY)) {
+            bottomLeft = (Integer)cornerRadii.get(BOTTOM_LEFT_KEY);
+        }
+
+        if (cornerRadii.containsKey(BOTTOM_RIGHT_KEY)) {
+            bottomRight = (Integer)cornerRadii.get(BOTTOM_RIGHT_KEY);
+        }
+    }
+
+    public CornerRadii(CornerRadii cornerRadii) {
+        if (cornerRadii == null) {
+            throw new IllegalArgumentException("cornerRadii is null.");
+        }
+
+        this.topLeft = cornerRadii.topLeft;
+        this.topRight = cornerRadii.topRight;
+        this.bottomLeft = cornerRadii.bottomLeft;
+        this.bottomRight = cornerRadii.bottomRight;
+    }
+
+    public CornerRadii(int topLeft, int topRight, int bottomLeft, int bottomRight) {
+        this.topLeft = topLeft;
+        this.topRight = topRight;
+        this.bottomLeft = bottomLeft;
+        this.bottomRight = bottomRight;
+    }
+
+    public boolean equals(Object object) {
+        boolean equals = false;
+
+        if (object instanceof CornerRadii) {
+            CornerRadii cornerRadii = (CornerRadii)object;
+            equals = (topLeft == cornerRadii.topLeft
+                && topRight == cornerRadii.topRight
+                && bottomLeft == cornerRadii.bottomLeft
+                && bottomRight == cornerRadii.bottomRight);
+        }
+
+        return equals;
+    }
+
+    public String toString() {
+        return getClass().getName() + " [" + topLeft + ", " + topRight
+            + bottomLeft + ", " + bottomRight + "]";
+    }
+}

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/Cursor.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/Cursor.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/Cursor.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/Cursor.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,81 @@
+/*
+ * 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;
+
+/**
+ * Enumeration defining the supported mouse cursor types.
+ *
+ * @author gbrown
+ */
+public enum Cursor {
+    DEFAULT,
+    HAND,
+    TEXT,
+    WAIT,
+    CROSSHAIR,
+    MOVE,
+    RESIZE_NORTH,
+    RESIZE_SOUTH,
+    RESIZE_EAST,
+    RESIZE_WEST,
+    RESIZE_NORTH_EAST,
+    RESIZE_NORTH_WEST,
+    RESIZE_SOUTH_EAST,
+    RESIZE_SOUTH_WEST;
+
+    public static Cursor decode(String value) {
+        if (value == null) {
+            throw new IllegalArgumentException("value is null.");
+        }
+
+        Cursor cursor = null;
+
+        if (value.equalsIgnoreCase("default")) {
+            cursor = Cursor.DEFAULT;
+        } else if (value.equalsIgnoreCase("hand")) {
+            cursor = Cursor.HAND;
+        } else if (value.equalsIgnoreCase("text")) {
+            cursor = Cursor.TEXT;
+        } else if (value.equalsIgnoreCase("wait")) {
+            cursor = Cursor.WAIT;
+        } else if (value.equalsIgnoreCase("crosshair")) {
+            cursor = Cursor.CROSSHAIR;
+        } else if (value.equalsIgnoreCase("move")) {
+            cursor = Cursor.MOVE;
+        } else if (value.equalsIgnoreCase("resizeNorth")) {
+            cursor = Cursor.RESIZE_NORTH;
+        } else if (value.equalsIgnoreCase("resizeSouth")) {
+            cursor = Cursor.RESIZE_SOUTH;
+        } else if (value.equalsIgnoreCase("resizeEast")) {
+            cursor = Cursor.RESIZE_EAST;
+        } else if (value.equalsIgnoreCase("resizeWest")) {
+            cursor = Cursor.RESIZE_WEST;
+        } else if (value.equalsIgnoreCase("resizeNorthEast")) {
+            cursor = Cursor.RESIZE_NORTH_EAST;
+        } else if (value.equalsIgnoreCase("resizeNorthWest")) {
+            cursor = Cursor.RESIZE_NORTH_WEST;
+        } else if (value.equalsIgnoreCase("resizeSouthEast")) {
+            cursor = Cursor.RESIZE_SOUTH_EAST;
+        } else if (value.equalsIgnoreCase("resizeSouthWest")) {
+            cursor = Cursor.RESIZE_SOUTH_WEST;
+        } else {
+            throw new IllegalArgumentException("\"" + value
+                + "\" is not a valid cursor.");
+        }
+
+        return cursor;
+    }
+}

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/Decorator.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/Decorator.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/Decorator.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/Decorator.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,65 @@
+/*
+ * 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;
+
+import java.awt.Graphics2D;
+
+/**
+ * Interface defining a component "decorator". Decorators allow a caller to
+ * attach additional visual effects to a component.
+ *
+ * @author gbrown
+ */
+public interface Decorator {
+    /**
+     * Prepares the graphics context into which the component or prior
+     * decorator will paint. This method is called immediately prior to
+     * {@link Component#paint(Graphics2D)}; decorators are called in
+     * descending order.
+     *
+     * @param component
+     * @param graphics
+     *
+     * @return
+     * The graphics context that should be used by the component or prior
+     * decorators.
+     */
+    public Graphics2D prepare(Component component, Graphics2D graphics);
+
+    /**
+     * Updates the graphics context into which the component or prior
+     * decorator was painted. This method is called immediately after
+     * {@link Component#paint(Graphics2D)}; decorators are called in
+     * ascending order.
+     */
+    public void update();
+
+    /**
+     * Returns the bounds of the area affected by a change to a given region
+     * within a component.
+     *
+     * @param component
+     * @param x
+     * @param y
+     * @param width
+     * @param height
+     *
+     * @return
+     * The bounds of the affected area, relative to the component's
+     * origin. The bounds may exceed the actual bounds of the component.
+     */
+    public Bounds getAffectedArea(Component component, int x, int y, int width, int height);
+}

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/DesktopApplicationContext.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/DesktopApplicationContext.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/DesktopApplicationContext.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/DesktopApplicationContext.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,248 @@
+/*
+ * 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;
+
+import java.awt.AWTEvent;
+import java.awt.Graphics;
+import java.awt.event.WindowEvent;
+
+import pivot.collections.HashMap;
+import pivot.collections.immutable.ImmutableMap;
+import pivot.wtk.media.Image;
+import pivot.wtk.media.Picture;
+
+/**
+ * Application context used to execute applications in a native frame
+ * window.
+ *
+ * @author gbrown
+ */
+public final class DesktopApplicationContext extends ApplicationContext {
+    private static class HostFrame extends java.awt.Frame {
+        public static final long serialVersionUID = 0;
+
+        private HostFrame() {
+            enableEvents(AWTEvent.WINDOW_EVENT_MASK
+                | AWTEvent.WINDOW_STATE_EVENT_MASK);
+
+            // Add the display host
+            add(applicationContext.getDisplayHost());
+
+            // Disable focus traversal keys
+            setFocusTraversalKeysEnabled(false);
+
+            // Clear the background
+            setBackground(null);
+        }
+
+        @Override
+        public void update(Graphics graphics) {
+            paint(graphics);
+        }
+
+        @Override
+        public void processWindowEvent(WindowEvent event) {
+            super.processWindowEvent(event);
+
+            switch(event.getID()) {
+                case WindowEvent.WINDOW_OPENED: {
+                    applicationContext.getDisplayHost().requestFocus();
+
+                    try {
+                        application.startup(applicationContext.getDisplay(),
+                            new ImmutableMap<String, String>(properties));
+                    } catch(Exception exception) {
+                        exception.printStackTrace();
+                        String message = exception.getMessage();
+                        if (message == null) {
+                            message = exception.getClass().getName();
+                        }
+
+                        Alert.alert(MessageType.ERROR, message, applicationContext.getDisplay());
+                    }
+
+                    break;
+                }
+
+                case WindowEvent.WINDOW_CLOSING: {
+                    boolean shutdown = true;
+
+                    try {
+                        shutdown = application.shutdown(true);
+                    } catch(Exception exception) {
+                        exception.printStackTrace();
+                        Alert.alert(MessageType.ERROR, exception.getMessage(),
+                            applicationContext.getDisplay());
+                    }
+
+                    if (shutdown) {
+                        java.awt.Window window = event.getWindow();
+                        window.setVisible(false);
+                        window.dispose();
+                    }
+
+                    break;
+                }
+
+                case WindowEvent.WINDOW_CLOSED: {
+                    exit();
+                    break;
+                }
+            }
+        }
+
+        @Override
+        protected void processWindowStateEvent(WindowEvent event) {
+            super.processWindowStateEvent(event);
+
+            switch(event.getID()) {
+                case WindowEvent.WINDOW_ICONIFIED: {
+                    try {
+                        application.suspend();
+                    } catch(Exception exception) {
+                        exception.printStackTrace();
+                        Alert.alert(MessageType.ERROR, exception.getMessage(),
+                            applicationContext.getDisplay());
+                    }
+
+                    break;
+                }
+
+                case WindowEvent.WINDOW_DEICONIFIED: {
+                    try {
+                        application.resume();
+                    } catch(Exception exception) {
+                        exception.printStackTrace();
+                        Alert.alert(MessageType.ERROR, exception.getMessage(),
+                            applicationContext.getDisplay());
+                    }
+
+                    break;
+                }
+            }
+        }
+    }
+
+    private static DesktopApplicationContext applicationContext = null;
+    private static HashMap<String, String> properties = null;
+    private static Application application = null;
+
+    private static int x = 0;
+    private static int y = 0;
+    private static int width = 800;
+    private static int height = 600;
+    private static boolean center = false;
+    private static boolean resizable = true;
+
+    private static final String DEFAULT_HOST_FRAME_TITLE = "Pivot"; // TODO i18n
+
+    private static final String X_ARGUMENT = "x";
+    private static final String Y_ARGUMENT = "y";
+    private static final String WIDTH_ARGUMENT = "width";
+    private static final String HEIGHT_ARGUMENT = "height";
+    private static final String CENTER_ARGUMENT = "center";
+    private static final String RESIZABLE_ARGUMENT = "resizable";
+
+    public static void main(String[] args) throws Exception {
+        // Get the application class name and startup properties
+        String applicationClassName = null;
+        properties = new HashMap<String, String>();
+
+        for (int i = 0, n = args.length; i < n; i++) {
+            String arg = args[i];
+
+            if (i == 0) {
+                applicationClassName = arg;
+            } else {
+                String[] property = arg.split(":");
+
+                if (property.length == 2) {
+                    String key = property[0];
+                    String value = property[1];
+
+                    if (key.equals(X_ARGUMENT)) {
+                        x = Integer.parseInt(value);
+                    } else if (key.equals(Y_ARGUMENT)) {
+                        y = Integer.parseInt(value);
+                    } else if (key.equals(WIDTH_ARGUMENT)) {
+                        width = Integer.parseInt(value);
+                    } else if (key.equals(HEIGHT_ARGUMENT)) {
+                        height = Integer.parseInt(value);
+                    } else if (key.equals(CENTER_ARGUMENT)) {
+                        center = Boolean.parseBoolean(value);
+                    } else if (key.equals(RESIZABLE_ARGUMENT)) {
+                        resizable = Boolean.parseBoolean(value);
+                    } else {
+                        properties.put(key, value);
+                    }
+                } else {
+                    System.out.println(arg + " is not a valid startup property.");
+                }
+            }
+        }
+
+        // Create the application context
+        applicationContext = new DesktopApplicationContext();
+
+        // Load the application
+        if (applicationClassName == null) {
+            System.out.println("Application class name is required.");
+        } else {
+            Class<?> applicationClass = Class.forName(applicationClassName);
+            application = (Application)applicationClass.newInstance();
+        }
+
+        // Create the host frame
+        final HostFrame hostFrame = new HostFrame();
+        hostFrame.setTitle(DEFAULT_HOST_FRAME_TITLE);
+
+        hostFrame.setSize(width, height);
+        hostFrame.setResizable(resizable);
+
+        if (center) {
+            java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
+            hostFrame.setLocation((screenSize.width - width) / 2, (screenSize.height - height) / 2);
+        } else {
+            hostFrame.setLocation(x, y);
+        }
+
+        // Open the window and focus the display host
+        hostFrame.setVisible(true);
+
+        Window.getWindowClassListeners().add(new WindowClassListener() {
+            public void activeWindowChanged(Window previousActiveWindow) {
+                ApplicationContext.queueCallback(new Runnable() {
+                    public void run() {
+                        Window activeWindow = Window.getActiveWindow();
+
+                        if (activeWindow == null) {
+                            hostFrame.setTitle(DEFAULT_HOST_FRAME_TITLE);
+                        } else {
+                            Window rootOwner = activeWindow.getRootOwner();
+                            hostFrame.setTitle(rootOwner.getTitle());
+
+                            Image rootIcon = rootOwner.getIcon();
+                            if (rootIcon instanceof Picture) {
+                                Picture rootPicture = (Picture)rootIcon;
+                                hostFrame.setIconImage(rootPicture.getBufferedImage());
+                            }
+                        }
+                    }
+                });
+            }
+        });
+    }
+}

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/Dialog.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/Dialog.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/Dialog.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/Dialog.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,270 @@
+/*
+ * 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;
+
+import pivot.util.ListenerList;
+import pivot.util.Vote;
+
+/**
+ * Window class whose primary purpose is to facilitate interaction between
+ * an application and a user.
+ *
+ * @author gbrown
+ */
+@ComponentInfo(icon="Dialog.png")
+public class Dialog extends Frame {
+    private static class DialogStateListenerList extends ListenerList<DialogStateListener>
+        implements DialogStateListener {
+        public Vote previewDialogClose(Dialog dialog, boolean result) {
+            Vote vote = Vote.APPROVE;
+
+            for (DialogStateListener listener : this) {
+                vote = vote.tally(listener.previewDialogClose(dialog, result));
+            }
+
+            return vote;
+        }
+
+        public void dialogCloseVetoed(Dialog dialog, Vote reason) {
+            for (DialogStateListener listener : this) {
+                listener.dialogCloseVetoed(dialog, reason);
+            }
+        }
+
+        public void dialogClosed(Dialog dialog) {
+            for (DialogStateListener listener : this) {
+                listener.dialogClosed(dialog);
+            }
+        }
+    }
+
+    private class RepositionCallback implements Runnable {
+        private static final float GOLDEN_SECTION = 0.382f;
+
+        public void run() {
+            Window owner = getOwner();
+
+            if (owner == null) {
+                throw new IllegalStateException("Dialog has no owner.");
+            }
+
+            int deltaWidth = owner.getWidth() - getWidth();
+            int deltaHeight = owner.getHeight() - getHeight();
+
+            int x = Math.max(0, Math.round(owner.getX() + 0.5f * deltaWidth));
+            int y = Math.max(0, Math.round(owner.getY() + GOLDEN_SECTION * deltaHeight));
+
+            setLocation(x, y);
+        }
+    }
+
+    private boolean modal = false;
+    private DialogCloseListener dialogCloseListener = null;
+    private Window disabledOwner = null;
+    private boolean result = false;
+
+    private DialogStateListenerList dialogStateListeners = new DialogStateListenerList();
+
+    public Dialog() {
+        this(null, null);
+    }
+
+    public Dialog(String title) {
+        this(title, null);
+    }
+
+    public Dialog(Component content) {
+        this(null, content);
+    }
+
+    public Dialog(String title, Component content) {
+        super(title, content);
+        installSkin(Dialog.class);
+    }
+
+    /**
+     * Opens the dialog.
+     *
+     * @param display
+     */
+    public final void open(Display display) {
+        open(display, null);
+    }
+
+    /**
+     * Opens the dialog.
+     *
+     * @param display
+     * @param dialogCloseListener
+     */
+    public void open(Display display, DialogCloseListener dialogCloseListener) {
+        super.open(display);
+
+        if (isOpen()) {
+            this.dialogCloseListener = dialogCloseListener;
+            this.modal = false;
+        }
+    }
+
+    /**
+     * Opens the dialog as modal over its owner.
+     *
+     * @param owner
+     */
+    public final void open(Window owner) {
+        open(owner, true, null);
+    }
+
+    /**
+     * Opens the dialog.
+     *
+     * @param owner
+     * @param modal
+     */
+    public final void open(Window owner, boolean modal) {
+        open(owner, modal, null);
+    }
+
+    /**
+     * Opens the dialog as modal over its owner.
+     *
+     * @param owner
+     * The dialog's owner.
+     *
+     * @param dialogCloseListener
+     * Optional dialog close listener to be called when the dialog is closed.
+     */
+    public final void open(Window owner, DialogCloseListener dialogCloseListener) {
+        open(owner, true, dialogCloseListener);
+    }
+
+    /**
+     * Opens the dialog.
+     *
+     * @param owner
+     * The dialog's owner.
+     *
+     * @param modal
+     * If <tt>true</tt>, the dialog is opened as modal, disabling its owner
+     * tree.
+     *
+     * @param dialogCloseListener
+     * Optional dialog close listener to be called when the dialog is closed.
+     */
+    public void open(Window owner, boolean modal, DialogCloseListener dialogCloseListener) {
+        super.open(owner);
+
+        if (isOpen()) {
+            this.dialogCloseListener = dialogCloseListener;
+            this.modal = modal;
+
+            if (modal) {
+            	if (!owner.isEnabled()) {
+            		throw new IllegalStateException("Owner is already disabled.");
+            	}
+
+                // Walk owner tree to find the nearest enabled owning ancestor
+                // and disable it
+                Window disabledOwner = null;
+
+                while (owner != null
+                    && owner.isEnabled()) {
+                    disabledOwner = owner;
+                    owner = owner.getOwner();
+                }
+
+                // Disable the ancestor and maintain a reference to it so we can
+                // enable it when this dialog is closed
+                if (disabledOwner != null) {
+                    disabledOwner.setEnabled(false);
+                }
+
+                this.disabledOwner = disabledOwner;
+
+                // Disabling the owner tree also disabled this dialog; re-enable it
+                // and make it the active window
+                setEnabled(true);
+                setActiveWindow(this);
+
+                // Align the dialog with its owner
+                ApplicationContext.queueCallback(new RepositionCallback());
+            }
+        }
+    }
+
+    @Override
+    public final void close() {
+        close(false);
+    }
+
+    public void close(boolean result) {
+        if (!isClosed()) {
+            Vote vote = dialogStateListeners.previewDialogClose(this, result);
+
+            if (vote == Vote.APPROVE) {
+                super.close();
+
+                if (isClosed()) {
+                    this.result = result;
+
+                    // Enable the ancestor that was disabled when this dialog
+                    // was opened
+                    if (disabledOwner != null) {
+                        disabledOwner.setEnabled(true);
+
+                        // Move the owner to the front
+                        if (modal) {
+                            disabledOwner.moveToFront();
+                        }
+                    }
+
+                    modal = false;
+                    disabledOwner = null;
+
+                    // Notify listeners
+                    if (dialogCloseListener != null) {
+                        dialogCloseListener.dialogClosed(this);
+                        dialogCloseListener = null;
+                    }
+
+                    dialogStateListeners.dialogClosed(this);
+                }
+            } else {
+                dialogStateListeners.dialogCloseVetoed(this, vote);
+            }
+        }
+    }
+
+    public boolean isModal() {
+        return modal;
+    }
+
+    public DialogCloseListener getDialogCloseListener() {
+        return dialogCloseListener;
+    }
+
+    public Window getDisabledOwner() {
+        return disabledOwner;
+    }
+
+    public boolean getResult() {
+        return result;
+    }
+
+    public ListenerList<DialogStateListener> getDialogStateListeners() {
+        return dialogStateListeners;
+    }
+}

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/Dialog.png
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/Dialog.png?rev=754936&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/Dialog.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/DialogCloseListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/DialogCloseListener.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/DialogCloseListener.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/DialogCloseListener.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;
+
+/**
+ * Dialog close listener interface.
+ *
+ * @author gbrown
+ */
+public interface DialogCloseListener {
+    /**
+     * Called when a dialog has closed.
+     *
+     * @param dialog
+     */
+    public void dialogClosed(Dialog dialog);
+}

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/DialogStateListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/DialogStateListener.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/DialogStateListener.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/DialogStateListener.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,42 @@
+/*
+ * 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;
+
+import pivot.util.Vote;
+
+/**
+ * Dialog state listener interface.
+ *
+ * @author tvolkert
+ * @author gbrown
+ */
+public interface DialogStateListener extends DialogCloseListener {
+    /**
+     * Called to preview a dialog close event.
+     *
+     * @param dialog
+     * @param result
+     */
+    public Vote previewDialogClose(Dialog dialog, boolean result);
+
+    /**
+     * Called when a dialog close event has been vetoed.
+     *
+     * @param dialog
+     * @param reason
+     */
+    public void dialogCloseVetoed(Dialog dialog, Vote reason);
+}

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/Dimensions.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/Dimensions.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/Dimensions.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/Dimensions.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,78 @@
+/*
+ * 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;
+
+import pivot.collections.Dictionary;
+
+/**
+ * Class representing the dimensions of an object.
+ *
+ * @author gbrown
+ */
+public class Dimensions {
+    public int width = 0;
+    public int height = 0;
+
+    public static final String WIDTH_KEY = "width";
+    public static final String HEIGHT_KEY = "height";
+
+    public Dimensions() {
+    }
+
+    public Dimensions(Dictionary<String, ?> dimensions) {
+        if (dimensions == null) {
+            throw new IllegalArgumentException("dimensions is null.");
+        }
+
+        if (dimensions.containsKey(WIDTH_KEY)) {
+            width = (Integer)dimensions.get(WIDTH_KEY);
+        }
+
+        if (dimensions.containsKey(HEIGHT_KEY)) {
+            height = (Integer)dimensions.get(HEIGHT_KEY);
+        }
+    }
+
+    public Dimensions(int width, int height) {
+        this.width = width;
+        this.height = height;
+    }
+
+    public Dimensions(Dimensions dimensions) {
+        if (dimensions == null) {
+            throw new IllegalArgumentException("dimensions is null.");
+        }
+
+        this.width = dimensions.width;
+        this.height = dimensions.height;
+    }
+
+    public boolean equals(Object object) {
+        boolean equals = false;
+
+        if (object instanceof Dimensions) {
+            Dimensions dimensions = (Dimensions)object;
+            equals = (width == dimensions.width
+                && height == dimensions.height);
+        }
+
+        return equals;
+    }
+
+    public String toString() {
+        return getClass().getName() + " [" + width + "x" + height + "]";
+    }
+}

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/Direction.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/Direction.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/Direction.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/Direction.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;
+
+/**
+ * Enumeration representing a two-dimensional direction.
+ *
+ * @author gbrown
+ */
+public enum Direction {
+    FORWARD,
+    BACKWARD;
+
+    public static Direction decode(String value) {
+        return valueOf(value.toUpperCase());
+    }
+}

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/Display.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/Display.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/Display.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/Display.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,88 @@
+/*
+ * 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;
+
+import java.awt.Graphics2D;
+import pivot.wtk.skin.DisplaySkin;
+
+/**
+ * Container that serves as the root of a component hierarchy.
+ *
+ * @author gbrown
+ */
+public final class Display extends Container {
+    private class ValidateCallback implements Runnable {
+        public void run() {
+            validate();
+        }
+    }
+
+    private ApplicationContext applicationContext = null;
+
+    protected Display(ApplicationContext applicationContext) {
+        this.applicationContext = applicationContext;
+
+        super.setSkin(new DisplaySkin());
+    }
+
+    protected ApplicationContext getApplicationContext() {
+        return applicationContext;
+    }
+
+    public DragDropManager getDragDropManager() {
+        return applicationContext.getDragDropManager();
+    }
+
+    @Override
+    protected void setSkin(Skin skin) {
+        throw new UnsupportedOperationException("Can't replace Display skin.");
+    }
+
+    @Override
+    public void setLocation(int x, int y) {
+        throw new UnsupportedOperationException("Can't change the location of the display.");
+    }
+
+    @Override
+    public void invalidate() {
+        if (isValid()) {
+            super.invalidate();
+            ApplicationContext.queueCallback(new ValidateCallback());
+        }
+    }
+
+    @Override
+    public void repaint(int x, int y, int width, int height, boolean immediate) {
+        if (immediate) {
+            Graphics2D graphics = applicationContext.getGraphics();
+            graphics.clipRect(x, y, width, height);
+            paint(graphics);
+            graphics.dispose();
+        } else {
+            applicationContext.repaint(x, y, width, height);
+        }
+    }
+
+    @Override
+    public void insert(Component component, int index) {
+        if (!(component instanceof Window)) {
+            throw new IllegalArgumentException("component must be an instance "
+                                               + "of " + Window.class);
+        }
+
+        super.insert(component, index);
+    }
+}

Added: incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/DragDropManager.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/DragDropManager.java?rev=754936&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/DragDropManager.java (added)
+++ incubator/pivot/tags/v1.0.1/wtk/src/pivot/wtk/DragDropManager.java Mon Mar 16 16:36:10 2009
@@ -0,0 +1,209 @@
+/*
+ * 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;
+
+import java.awt.Graphics2D;
+
+/**
+ * Provides framework support for drag/drop operations.
+ * <p>
+ * TODO If Escape is pressed, cancel drag (call endDrag(null)).
+ * <p>
+ * TODO Paint an appropriate overlay icon if drop action is copy or link.
+ * <p>
+ * TODO ApplicationContext.DisplayHost should marshall/unmarshall native
+ * drag/drop content when a drag out/over occurs, respectively?
+ *
+ * @author gbrown
+ */
+public final class DragDropManager {
+    private ApplicationContext applicationContext = null;
+
+    private Point dragLocation = null;
+    private DragHandler dragHandler = null;
+
+    public static final int DRAG_THRESHOLD = 4;
+
+    protected DragDropManager(ApplicationContext applicationContext) {
+        this.applicationContext = applicationContext;
+    }
+
+    public boolean isActive() {
+        return (dragHandler != null);
+    }
+
+    public Object getContent() {
+        if (!isActive()) {
+            throw new IllegalStateException();
+        }
+
+        return dragHandler.getContent();
+    }
+
+    public Visual getRepresentation() {
+        if (!isActive()) {
+            throw new IllegalStateException();
+        }
+
+        return dragHandler.getRepresentation();
+    }
+
+    public Dimensions getOffset() {
+        if (!isActive()) {
+            throw new IllegalStateException();
+        }
+
+        return dragHandler.getOffset();
+    }
+
+    public int getSupportedDropActions() {
+        if (!isActive()) {
+            throw new IllegalStateException();
+        }
+
+        return dragHandler.getSupportedDropActions();
+    }
+
+    public void paint(Graphics2D graphics) {
+        if (isActive()) {
+            Visual representation = getRepresentation();
+
+            if (representation != null) {
+                Dimensions offset = getOffset();
+                int tx = dragLocation.x - offset.width;
+                int ty = dragLocation.y - offset.height;
+
+                Graphics2D representationGraphics = (Graphics2D)graphics.create(tx, ty,
+                    representation.getWidth(), representation.getHeight());
+
+                representation.paint(representationGraphics);
+
+                representationGraphics.dispose();
+            }
+        }
+    }
+
+    protected void mouseMove(int x, int y) {
+        if (isActive()) {
+            invalidate(x, y);
+        } else {
+            if (dragLocation != null) {
+                if (Math.abs(x - dragLocation.x) > DRAG_THRESHOLD
+                    || Math.abs(y - dragLocation.y) > DRAG_THRESHOLD) {
+                    Display display = applicationContext.getDisplay();
+                    Component dragSource = display.getDescendantAt(dragLocation.x,
+                        dragLocation.y);
+
+                    // Look for a drag handler
+                    dragHandler = null;
+                    while (dragSource != null) {
+                        dragHandler = dragSource.getDragHandler();
+
+                        if (dragHandler == null) {
+                            dragSource = dragSource.getParent();
+                        } else {
+                            break;
+                        }
+                    }
+
+                    if (dragHandler == null) {
+                        // A drag handler could not be found, so stop looking
+                        // until the next mouse down event
+                        dragLocation = null;
+                    } else {
+                        // A drag handler was found; begin the drag
+                        Mouse.setCursor(Cursor.DEFAULT);
+                        Point componentDragLocation = dragSource.mapPointFromAncestor(display,
+                            dragLocation.x, dragLocation.y);
+
+                        boolean drag = dragHandler.beginDrag(dragSource,
+                            componentDragLocation.x, componentDragLocation.y);
+
+                        if (!drag) {
+                            // The drag source rejected the drag
+                            dragLocation = null;
+                            dragHandler = null;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    protected void mouseDown(Mouse.Button button, int x, int y) {
+        dragLocation = new Point(x, y);
+    }
+
+    protected void mouseUp(Mouse.Button button, int x, int y) {
+        if (isActive()) {
+            Display display = applicationContext.getDisplay();
+            Component dropTarget = display.getDescendantAt(x, y);
+
+            // Look for a drop handler
+            DropHandler dropHandler = null;
+            while (dropTarget != null) {
+                dropHandler = dropTarget.getDropHandler();
+
+                if (dropHandler == null) {
+                    dropTarget = dropTarget.getParent();
+                } else {
+                    break;
+                }
+            }
+
+            DropAction dropAction = null;
+
+            if (dropHandler != null) {
+                // A drop handler was found; drop the content
+                Point componentDropLocation = dropTarget.mapPointFromAncestor(display, x, y);
+                dropAction = dropHandler.drop(dropTarget,
+                    componentDropLocation.x, componentDropLocation.y);
+            }
+
+            invalidate(x, y);
+
+            // End the drag
+            dragHandler.endDrag(dropAction);
+            dragHandler = null;
+
+            Mouse.setCursor(dropTarget == null ? Cursor.DEFAULT : dropTarget.getCursor());
+        }
+
+        dragLocation = null;
+    }
+
+    protected void keyPressed(int keyCode, Keyboard.KeyLocation keyLocation) {
+    }
+
+    protected void keyReleased(int keyCode, Keyboard.KeyLocation keyLocation) {
+    }
+
+    private void invalidate(int x, int y) {
+        Visual representation = getRepresentation();
+        Dimensions offset = getOffset();
+
+        applicationContext.repaint(dragLocation.x - offset.width,
+            dragLocation.y - offset.height,
+            representation.getWidth(), representation.getHeight());
+
+        dragLocation.x = x;
+        dragLocation.y = y;
+
+        applicationContext.repaint(dragLocation.x - offset.width,
+            dragLocation.y - offset.height,
+            representation.getWidth(), representation.getHeight());
+    }
+}