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/26 00:12:17 UTC

svn commit: r758461 [19/47] - in /incubator/pivot/branches: ./ 1.1/ 1.1/charts-test/ 1.1/charts-test/src/ 1.1/charts-test/src/pivot/ 1.1/charts-test/src/pivot/charts/ 1.1/charts-test/src/pivot/charts/test/ 1.1/charts/ 1.1/charts/lib/ 1.1/charts/src/ 1....

Added: incubator/pivot/branches/1.1/wtk/src/pivot/wtk/ComponentMouseListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/ComponentMouseListener.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/ComponentMouseListener.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/ComponentMouseListener.java Wed Mar 25 23:08:38 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/branches/1.1/wtk/src/pivot/wtk/ComponentMouseWheelListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/ComponentMouseWheelListener.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/ComponentMouseWheelListener.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/ComponentMouseWheelListener.java Wed Mar 25 23:08:38 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/branches/1.1/wtk/src/pivot/wtk/ComponentStateListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/ComponentStateListener.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/ComponentStateListener.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/ComponentStateListener.java Wed Mar 25 23:08:38 2009
@@ -0,0 +1,39 @@
+/*
+ * 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 state listener interface.
+ *
+ * @author gbrown
+ * @author tvolkert
+ */
+public interface ComponentStateListener {
+    /**
+     * Called when a component's enabled state has changed.
+     *
+     * @param component
+     */
+    public void enabledChanged(Component component);
+
+    /**
+     * Called when a component's focused state has changed.
+     *
+     * @param component
+     * @param temporary
+     */
+    public void focusedChanged(Component component, boolean temporary);
+}

Added: incubator/pivot/branches/1.1/wtk/src/pivot/wtk/ConstrainedVisual.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/ConstrainedVisual.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/ConstrainedVisual.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/ConstrainedVisual.java Wed Mar 25 23:08:38 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/branches/1.1/wtk/src/pivot/wtk/Container.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/Container.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/Container.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/Container.java Wed Mar 25 23:08:38 2009
@@ -0,0 +1,780 @@
+/*
+ * 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.awt.Rectangle;
+import java.util.Iterator;
+
+import pivot.beans.BeanDictionary;
+import pivot.collections.ArrayList;
+import pivot.collections.Dictionary;
+import pivot.collections.Map;
+import pivot.collections.Sequence;
+import pivot.util.ImmutableIterator;
+import pivot.util.ListenerList;
+import pivot.wtk.effects.Decorator;
+
+/**
+ * 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
+ */
+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 boolean mouseMove(Container container, int x, int y) {
+            boolean consumed = false;
+
+            for (ContainerMouseListener listener : this) {
+                consumed |= listener.mouseMove(container, x, y);
+            }
+
+            return consumed;
+        }
+
+        public boolean mouseDown(Container container, Mouse.Button button, int x, int y) {
+            boolean consumed = false;
+
+            for (ContainerMouseListener listener : this) {
+                consumed |= listener.mouseDown(container, button, x, y);
+            }
+
+            return consumed;
+        }
+
+        public boolean mouseUp(Container container, Mouse.Button button, int x, int y) {
+            boolean consumed = false;
+
+            for (ContainerMouseListener listener : this) {
+                consumed |= listener.mouseUp(container, button, x, y);
+            }
+
+            return consumed;
+        }
+
+        public boolean mouseWheel(Container container, Mouse.ScrollType scrollType,
+            int scrollAmount, int wheelRotation, int x, int y) {
+            boolean consumed = false;
+
+            for (ContainerMouseListener listener : this) {
+                consumed |= listener.mouseWheel(container, scrollType, scrollAmount, wheelRotation, x, y);
+            }
+
+            return consumed;
+        }
+    }
+
+    // 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 boolean mouseClickConsumed = false;
+
+    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
+        repaint(component.getDecoratedBounds());
+
+        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);
+
+        // 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);
+            if (component == mouseOverComponent) {
+                if (mouseOverComponent.isMouseOver()) {
+                    mouseOverComponent.mouseOut();
+                }
+
+                mouseOverComponent = null;
+                Mouse.setCursor(this);
+            }
+
+            repaint(component.getDecoratedBounds());
+            component.setParent(null);
+        }
+
+        if (removed.getLength() > 0) {
+            invalidate();
+            containerListeners.componentsRemoved(Container.this, index, removed);
+        }
+
+        return removed;
+    }
+
+    public final Sequence<Component> removeAll() {
+        return remove(0, getLength());
+    }
+
+    /**
+     * Moves a component within the component sequence. This method does not
+     * fire any events; it is the caller's responsibility to ensure that
+     * appropriate events are fired (see
+     * {@link WindowListener#windowMoved(Window, int, int)} as an example).
+     *
+     * @param from
+     * @param to
+     */
+    protected void move(int from, int to) {
+        if (from != to) {
+            Sequence<Component> removed = components.remove(from, 1);
+            Component component = removed.get(0);
+            components.insert(component, to);
+
+            // Repaint the area occupied by the component
+            repaint(component.getDecoratedBounds());
+        }
+    }
+
+    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 container = (Container)component;
+            component = container.getDescendantAt(x - component.getX(),
+                y - component.getY());
+        }
+
+        if (component == null) {
+            component = this;
+        }
+
+        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() {
+        valid = false;
+        super.invalidate();
+    }
+
+    @Override
+    public void validate() {
+        super.validate();
+
+        if (!valid) {
+            try {
+                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();
+
+        // Determine the paint bounds
+        Bounds paintBounds = new Bounds(0, 0, getWidth(), getHeight());
+        Rectangle clipBounds = graphics.getClipBounds();
+        if (clipBounds != null) {
+            paintBounds.intersect(new Bounds(clipBounds));
+        }
+
+        for (Component component : this) {
+            // Calculate the decorated bounds
+            Bounds decoratedBounds = component.getDecoratedBounds();
+
+            // Only paint components that are visible and intersect the
+            // current clip rectangle
+            if (component.isVisible()
+                && decoratedBounds.intersects(paintBounds)) {
+                Bounds componentBounds = component.getBounds();
+
+                // Create a copy of the current graphics context and
+                // translate to the component's coordinate system
+                Graphics2D decoratedGraphics = (Graphics2D)graphics.create();
+                decoratedGraphics.translate(componentBounds.x, componentBounds.y);
+
+                // Prepare the decorators
+                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
+                Graphics2D componentGraphics = (Graphics2D)decoratedGraphics.create();
+                componentGraphics.clipRect(0, 0, componentBounds.width, componentBounds.height);
+                component.paint(componentGraphics);
+                componentGraphics.dispose();
+
+                // Update the decorators
+                for (int i = 0; i < n; i++) {
+                    Decorator decorator = decorators.get(i);
+                    decorator.update();
+                }
+            }
+        }
+    }
+
+    @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, ?> context) {
+        if (contextKey != null
+            && context.containsKey(contextKey)) {
+        	Object value = context.get(contextKey);
+        	if (value instanceof Dictionary<?, ?>) {
+                context = (Map<String, Object>)value;
+        	} else {
+                context = new BeanDictionary(value);
+        	}
+        }
+
+        for (Component component : components) {
+            component.load(context);
+        }
+    }
+
+    /**
+     * Propagates binding to subcomponents by converting the given context
+     * to a bean dictionary.
+     *
+     * @param context
+     */
+    public void load(Object context) {
+    	load(new BeanDictionary(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, ?> context) {
+        if (contextKey != null) {
+            // Bound value is expected to be a sub-context
+        	Object value = context.get(contextKey);
+        	if (value instanceof Dictionary<?, ?>) {
+                context = (Map<String, Object>)value;
+        	} else {
+                context = new BeanDictionary(value);
+        	}
+        }
+
+        for (Component component : components) {
+            component.store(context);
+        }
+    }
+
+    /**
+     * Propagates binding to subcomponents by converting the given context
+     * to a bean dictionary.
+     *
+     * @param context
+     */
+    public void store(Object context) {
+    	store(new BeanDictionary(context));
+    }
+
+    @Override
+    protected boolean mouseMove(int x, int y) {
+        boolean consumed = false;
+
+        if (isEnabled()) {
+            // Notify container listeners
+            consumed = containerMouseListeners.mouseMove(this, x, y);
+
+            if (!consumed) {
+                // Clear the mouse over component if its mouse-over state has
+                // changed (e.g. if its enabled or visible properties have
+                // changed)
+                if (mouseOverComponent != null
+                    && !mouseOverComponent.isMouseOver()) {
+                    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) {
+                        Mouse.setCursor(this);
+                    } else {
+                        mouseOverComponent.mouseOver();
+                        Mouse.setCursor(mouseOverComponent);
+                    }
+                }
+
+                // 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.isMouseOver()) {
+            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
+            consumed = containerMouseListeners.mouseDown(this, button, x, y);
+
+            if (!consumed) {
+                // Synthesize mouse click event
+                Component component = getComponentAt(x, y);
+
+                long currentTime = System.currentTimeMillis();
+                int multiClickInterval = Platform.getMultiClickInterval();
+                if (mouseDownComponent == component
+                    && currentTime - mouseDownTime < multiClickInterval) {
+                    mouseClickCount++;
+                } else {
+                    mouseDownTime = System.currentTimeMillis();
+                    mouseClickCount = 1;
+                }
+
+                mouseDownComponent = component;
+
+                // 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
+            consumed = containerMouseListeners.mouseUp(this, button, x, y);
+
+            if (!consumed) {
+                // Propagate event to subcomponents
+                Component component = getComponentAt(x, y);
+
+                if (component != null) {
+                    consumed = component.mouseUp(button, x - component.getX(),
+                        y - component.getY());
+                }
+
+                // Notify the base class
+                if (!consumed) {
+                    consumed = super.mouseUp(button, x, y);
+                }
+
+                // Synthesize mouse click event
+                if (component != null
+                    && component == mouseDownComponent
+                    && mouseDownComponent.isEnabled()
+                    && mouseDownComponent.isVisible()) {
+                    mouseClickConsumed = component.mouseClick(button, x - component.getX(),
+                        y - component.getY(), mouseClickCount);
+                }
+            }
+        }
+
+        return consumed;
+    }
+
+    @Override
+    protected boolean mouseClick(Mouse.Button button, int x, int y, int count) {
+        if (isEnabled()) {
+            if (!mouseClickConsumed) {
+                // Allow the event to propagate
+                mouseClickConsumed = super.mouseClick(button, x, y, count);
+            }
+        }
+
+        return mouseClickConsumed;
+    }
+
+    @Override
+    protected boolean mouseWheel(Mouse.ScrollType scrollType, int scrollAmount,
+        int wheelRotation, int x, int y) {
+        boolean consumed = false;
+
+        if (isEnabled()) {
+            // Notify container listeners
+            consumed = containerMouseListeners.mouseWheel(this, scrollType, scrollAmount,
+                wheelRotation, x, y);
+
+            if (!consumed) {
+                // 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/branches/1.1/wtk/src/pivot/wtk/ContainerListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/ContainerListener.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/ContainerListener.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/ContainerListener.java Wed Mar 25 23:08:38 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/branches/1.1/wtk/src/pivot/wtk/ContainerMouseListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/ContainerMouseListener.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/ContainerMouseListener.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/ContainerMouseListener.java Wed Mar 25 23:08:38 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;
+
+/**
+ * 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
+     *
+     * @return
+     * <tt>true</tt> to consume the event; <tt>false</tt> to allow it to
+     * propagate.
+     */
+    public boolean mouseMove(Container container, int x, int y);
+
+    /**
+     * Called when the mouse is pressed over a container.
+     *
+     * @param container
+     * @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(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
+     *
+     * @return
+     * <tt>true</tt> to consume the event; <tt>false</tt> to allow it to
+     * propagate.
+     */
+    public boolean 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
+     *
+     * @return
+     * <tt>true</tt> to consume the event; <tt>false</tt> to allow it to
+     * propagate.
+     */
+    public boolean mouseWheel(Container container, Mouse.ScrollType scrollType,
+        int scrollAmount, int wheelRotation, int x, int y);
+}

Added: incubator/pivot/branches/1.1/wtk/src/pivot/wtk/CornerRadii.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/CornerRadii.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/CornerRadii.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/CornerRadii.java Wed Mar 25 23:08:38 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/branches/1.1/wtk/src/pivot/wtk/Cursor.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/Cursor.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/Cursor.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/Cursor.java Wed Mar 25 23:08:38 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/branches/1.1/wtk/src/pivot/wtk/DesktopApplicationContext.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/DesktopApplicationContext.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/DesktopApplicationContext.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/DesktopApplicationContext.java Wed Mar 25 23:08:38 2009
@@ -0,0 +1,260 @@
+/*
+ * 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
+ */
+@SuppressWarnings("deprecation")
+public final class DesktopApplicationContext extends ApplicationContext {
+    private static class HostFrame extends java.awt.Frame {
+        private 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();
+
+                    createTimer();
+
+                    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) {
+                        destroyTimer();
+
+                        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";
+
+    /**
+     * Terminates the application context.
+     */
+    public static void exit() {
+        System.exit(0);
+    }
+
+    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.err.println(arg + " is not a valid startup property.");
+                }
+            }
+        }
+
+        // Create the application context
+        applicationContext = new DesktopApplicationContext();
+
+        // Load the application
+        if (applicationClassName == null) {
+            System.err.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/branches/1.1/wtk/src/pivot/wtk/Dialog.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/Dialog.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/Dialog.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/Dialog.java Wed Mar 25 23:08:38 2009
@@ -0,0 +1,269 @@
+/*
+ * 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
+ */
+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/branches/1.1/wtk/src/pivot/wtk/DialogCloseListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/DialogCloseListener.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/DialogCloseListener.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/DialogCloseListener.java Wed Mar 25 23:08:38 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/branches/1.1/wtk/src/pivot/wtk/DialogStateListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/DialogStateListener.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/DialogStateListener.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/DialogStateListener.java Wed Mar 25 23:08:38 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/branches/1.1/wtk/src/pivot/wtk/Dimensions.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/Dimensions.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/Dimensions.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/Dimensions.java Wed Mar 25 23:08:38 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/branches/1.1/wtk/src/pivot/wtk/Direction.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/Direction.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/Direction.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/Direction.java Wed Mar 25 23:08:38 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/branches/1.1/wtk/src/pivot/wtk/Display.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/Display.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/Display.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/Display.java Wed Mar 25 23:08:38 2009
@@ -0,0 +1,110 @@
+/*
+ * 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();
+            if (!paintPending) {
+                validateCallback = null;
+            }
+        }
+    }
+
+    private ApplicationContext.DisplayHost displayHost;
+    private ValidateCallback validateCallback = null;
+    private boolean paintPending = false;
+
+    protected Display(ApplicationContext.DisplayHost displayHost) {
+        this.displayHost = displayHost;
+        super.setSkin(new DisplaySkin());
+    }
+
+    public ApplicationContext.DisplayHost getDisplayHost() {
+        return displayHost;
+    }
+
+    public Point getMouseLocation() {
+        return displayHost.getMouseLocation();
+    }
+
+    @Override
+    protected void setSkin(Skin skin) {
+        throw new UnsupportedOperationException("Can't replace Display skin.");
+    }
+
+    @Override
+    protected void setParent(Container parent) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void setLocation(int x, int y) {
+        throw new UnsupportedOperationException("Can't change the location of the display.");
+    }
+
+    @Override
+    public void invalidate() {
+        if (validateCallback == null) {
+            validateCallback = new ValidateCallback();
+            ApplicationContext.queueCallback(validateCallback);
+        }
+
+        super.invalidate();
+    }
+
+    @Override
+    public void repaint(int x, int y, int width, int height, boolean immediate) {
+        if (immediate) {
+            Graphics2D graphics = (Graphics2D)displayHost.getGraphics();
+            graphics.clipRect(x, y, width, height);
+            paint(graphics);
+            graphics.dispose();
+        } else {
+            displayHost.repaint(x, y, width, height);
+            paintPending = true;
+        }
+    }
+
+    @Override
+    public void paint(Graphics2D graphics) {
+        super.paint(graphics);
+        paintPending = false;
+
+        if (validateCallback != null) {
+            ApplicationContext.queueCallback(validateCallback);
+        }
+    }
+
+    @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/branches/1.1/wtk/src/pivot/wtk/DragSource.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/DragSource.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/DragSource.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/DragSource.java Wed Mar 25 23:08:38 2009
@@ -0,0 +1,83 @@
+/*
+ * 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;
+
+/**
+ * Interface representing a drag source.
+ *
+ * @author gbrown
+ */
+public interface DragSource {
+    /**
+     * Called by the framework to initiate a drag operation.
+     *
+     * @param component
+     * @param x
+     * @param y
+     *
+     * @return
+     * <tt>true</tt> to accept the drag; <tt>false</tt> to reject it.
+     */
+    public boolean beginDrag(Component component, int x, int y);
+
+    /**
+     * Called by the framework to terminate a drag operation.
+     *
+     * @param component
+     * @param dropAction
+     */
+    public void endDrag(Component component, DropAction dropAction);
+
+    /**
+     * Returns the drag source's native flag.
+     *
+     * @return
+     * If <tt>true</tt>, the drag will be executed via the native OS. Otherwise,
+     * it will be executed locally.
+     */
+    public boolean isNative();
+
+    /**
+     * Returns the drag content.
+     */
+    public LocalManifest getContent();
+
+    /**
+     * Returns a visual representing the drag content.
+     *
+     * @return
+     * The drag visual, or <tt>null</tt> for no visual.
+     */
+    public Visual getRepresentation();
+
+    /**
+     * Returns the offset of the mouse pointer within the drag visual. Not
+     * required unless a representation is specified.
+     *
+     * @return
+     * The mouse offset within the drag visual, or <tt>null</tt> if no visual
+     * is specified.
+     */
+    public Point getOffset();
+
+    /**
+     * Returns the drop actions supported by this drag source.
+     *
+     * @return
+     * A bitfield of the supported drop actions.
+     */
+    public int getSupportedDropActions();
+}

Added: incubator/pivot/branches/1.1/wtk/src/pivot/wtk/DropAction.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/DropAction.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/DropAction.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/DropAction.java Wed Mar 25 23:08:38 2009
@@ -0,0 +1,39 @@
+/*
+ * 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 supported drop actions.
+ *
+ * @author gbrown
+ */
+public enum DropAction {
+    COPY,
+    MOVE,
+    LINK;
+
+    public int getMask() {
+        return 1 << ordinal();
+    }
+
+    public boolean isSelected(int dropActions) {
+        return ((dropActions & getMask()) > 0);
+    }
+
+    public static DropAction decode(String value) {
+        return valueOf(value.toUpperCase());
+    }
+}

Added: incubator/pivot/branches/1.1/wtk/src/pivot/wtk/DropTarget.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/DropTarget.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/DropTarget.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/DropTarget.java Wed Mar 25 23:08:38 2009
@@ -0,0 +1,99 @@
+/*
+ * 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;
+
+/**
+ * Interface representing a drop target.
+ *
+ * @author gbrown
+ */
+public interface DropTarget {
+    /**
+     * Called when the mouse first enters a drop target during a drag
+     * operation.
+     *
+     * @param component
+     * @param dragContent
+     * @param supportedDropActions
+     * @param userDropAction
+     *
+     * @return
+     * The drop action that would result if the user dropped the item at this
+     * location, or <tt>null</tt> if the target cannot accept the drop.
+     */
+    public DropAction dragEnter(Component component, Manifest dragContent,
+        int supportedDropActions, DropAction userDropAction);
+
+    /**
+     * Called when the mouse leaves a drop target during a drag operation.
+     *
+     * @param component
+     */
+    public void dragExit(Component component);
+
+    /**
+     * Called when the mouse is moved while positioned over a drop target
+     * during a drag operation.
+     *
+     * @param component
+     * @param dragContent
+     * @param supportedDropActions
+     * @param x
+     * @param y
+     * @param userDropAction
+     *
+     * @return
+     * The drop action that would result if the user dropped the item at this
+     * location, or <tt>null</tt> if the target cannot accept the drop.
+     */
+    public DropAction dragMove(Component component, Manifest dragContent,
+        int supportedDropActions, int x, int y, DropAction userDropAction);
+
+    /**
+     * Called when the user drop action changes while the mouse is positioned
+     * over a drop target during a drag operation.
+     *
+     * @param component
+     * @param dragContent
+     * @param supportedDropActions
+     * @param x
+     * @param y
+     * @param userDropAction
+     *
+     * @return
+     * The drop action that would result if the user dropped the item at this
+     * location, or <tt>null</tt> if the target cannot accept the drop.
+     */
+    public DropAction userDropActionChange(Component component, Manifest dragContent,
+        int supportedDropActions, int x, int y, DropAction userDropAction);
+
+    /**
+     * Called to drop the drag content.
+     *
+     * @param component
+     * @param dragContent
+     * @param supportedDropActions
+     * @param x
+     * @param y
+     * @param userDropAction
+     *
+     * @return
+     * The drop action used to perform the drop, or <tt>null</tt> if the target
+     * rejected the drop.
+     */
+    public DropAction drop(Component component, Manifest dragContent,
+        int supportedDropActions, int x, int y, DropAction userDropAction);
+}

Added: incubator/pivot/branches/1.1/wtk/src/pivot/wtk/Editor.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/Editor.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/Editor.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/Editor.java Wed Mar 25 23:08:38 2009
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2009 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;
+
+/**
+ * Base interface for content editors.
+ *
+ * @author gbrown
+ */
+public interface Editor {
+    public boolean isEditing();
+    public void save();
+    public void cancel();
+}

Added: incubator/pivot/branches/1.1/wtk/src/pivot/wtk/Expander.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/Expander.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/Expander.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/Expander.java Wed Mar 25 23:08:38 2009
@@ -0,0 +1,160 @@
+/*
+ * 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;
+import pivot.util.ListenerList;
+import pivot.util.Vote;
+
+/**
+ * Navigation container that allows a user to expand and collapse a content
+ * component.
+ *
+ * @author tvolkert
+ */
+public class Expander extends Container {
+    private static class ExpanderListenerList extends ListenerList<ExpanderListener>
+    implements ExpanderListener {
+        public void titleChanged(Expander expander, String previousTitle) {
+            for (ExpanderListener listener : this) {
+                listener.titleChanged(expander, previousTitle);
+            }
+        }
+
+        public Vote previewExpandedChange(Expander expander) {
+            Vote vote = Vote.APPROVE;
+
+            for (ExpanderListener listener : this) {
+                vote = vote.tally(listener.previewExpandedChange(expander));
+            }
+
+            return vote;
+        }
+
+        public void expandedChangeVetoed(Expander expander, Vote reason) {
+            for (ExpanderListener listener : this) {
+                listener.expandedChangeVetoed(expander, reason);
+            }
+        }
+
+        public void expandedChanged(Expander expander) {
+            for (ExpanderListener listener : this) {
+                listener.expandedChanged(expander);
+            }
+        }
+
+        public void contentChanged(Expander expander, Component previousContent) {
+            for (ExpanderListener listener : this) {
+                listener.contentChanged(expander, previousContent);
+            }
+        }
+    }
+
+    private String title = null;
+    private boolean expanded = true;
+    private Component content = null;
+
+    private ExpanderListenerList expanderListeners = new ExpanderListenerList();
+
+    public Expander() {
+        installSkin(Expander.class);
+    }
+
+    /**
+     * Returns the expander's title.
+     *
+     * @return
+     * The pane's title, or <tt>null</tt> if no title is set.
+     */
+    public String getTitle() {
+        return title;
+    }
+
+    /**
+     * Sets the expander's title.
+     *
+     * @param title
+     * The new title, or <tt>null</tt> for no title.
+     */
+    public void setTitle(String title) {
+        String previousTitle = this.title;
+
+        if (previousTitle == null ^ title == null) {
+            this.title = title;
+            expanderListeners.titleChanged(this, previousTitle);
+        }
+    }
+
+    public boolean isExpanded() {
+        return expanded;
+    }
+
+    public void setExpanded(boolean expanded) {
+        if (expanded != this.expanded) {
+            Vote vote = expanderListeners.previewExpandedChange(this);
+
+            if (vote == Vote.APPROVE) {
+                this.expanded = expanded;
+                expanderListeners.expandedChanged(this);
+            } else {
+                expanderListeners.expandedChangeVetoed(this, vote);
+            }
+        }
+    }
+
+    public Component getContent() {
+        return content;
+    }
+
+    public void setContent(Component content) {
+        Component previousContent = this.content;
+
+        if (content != previousContent) {
+            this.content = null;
+
+            // Remove any previous content component
+            if (previousContent != null) {
+                remove(previousContent);
+            }
+
+            // Add the component
+            if (content != null) {
+                add(content);
+            }
+
+            this.content = content;
+
+            expanderListeners.contentChanged(this, previousContent);
+        }
+    }
+
+    @Override
+    public Sequence<Component> remove(int index, int count) {
+        for (int i = index, n = index + count; i < n; i++) {
+            Component component = get(i);
+            if (component == content) {
+                throw new UnsupportedOperationException();
+            }
+        }
+
+        // Call the base method to remove the components
+        return super.remove(index, count);
+    }
+
+    public ListenerList<ExpanderListener> getExpanderListeners() {
+        return expanderListeners;
+    }
+}