You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pivot.apache.org by gb...@apache.org on 2011/01/10 00:19:29 UTC

svn commit: r1057053 [7/12] - in /pivot/branches/3.x: ./ core/ core/src/ core/src/org/ core/src/org/apache/ core/src/org/apache/pivot/ core/src/org/apache/pivot/beans/ core/src/org/apache/pivot/bxml/ core/src/org/apache/pivot/csv/ core/src/org/apache/p...

Added: pivot/branches/3.x/platform-awt/src/org/apache/pivot/scene/AWTStageHost.java
URL: http://svn.apache.org/viewvc/pivot/branches/3.x/platform-awt/src/org/apache/pivot/scene/AWTStageHost.java?rev=1057053&view=auto
==============================================================================
--- pivot/branches/3.x/platform-awt/src/org/apache/pivot/scene/AWTStageHost.java (added)
+++ pivot/branches/3.x/platform-awt/src/org/apache/pivot/scene/AWTStageHost.java Sun Jan  9 23:19:19 2011
@@ -0,0 +1,603 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you 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 org.apache.pivot.scene;
+
+import java.awt.AWTEvent;
+import java.awt.Dimension;
+import java.awt.Graphics2D;
+import java.awt.GraphicsConfiguration;
+import java.awt.RenderingHints;
+import java.awt.Toolkit;
+import java.awt.Transparency;
+import java.awt.event.ComponentEvent;
+import java.awt.event.FocusEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseWheelEvent;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.Random;
+
+import org.apache.pivot.scene.Stage;
+
+/**
+ * AWT scene graph host component.
+ */
+public class AWTStageHost extends java.awt.Component {
+    private static final long serialVersionUID = 0;
+
+    private Stage stage = new Stage() {
+        @Override
+        public void invalidate() {
+            AWTStageHost.this.invalidate();
+        }
+
+        @Override
+        public void repaintHost(int x, int y, int width, int height) {
+            AWTStageHost.this.repaint(x, y, width, height);
+        }
+
+        @Override
+        public Graphics getHostGraphics() {
+            Graphics2D graphics2D = (Graphics2D)AWTStageHost.this.getGraphics();
+
+            Graphics graphics = null;
+            if (graphics2D != null) {
+                graphics2D.clipRect(0, 0, getWidth(), getHeight());
+                graphics = new AWTGraphics(graphics2D);
+            }
+
+            return graphics;
+        }
+
+        @Override
+        public void requestNativeFocus() {
+            requestFocusInWindow();
+        }
+
+        @Override
+        public Object getNativeHost() {
+            return AWTStageHost.this;
+        }
+    };
+
+    private Node mouseCapturer = null;
+    private Node focusOwner = null;
+
+    private boolean doubleBuffered = true;
+    private boolean disableVolatileBuffer = true;
+
+    private boolean debugPaint = false;
+    private boolean debugFocus = false;
+
+    private boolean paintPending = false;
+
+    public AWTStageHost() {
+        enableEvents(AWTEvent.COMPONENT_EVENT_MASK
+            | AWTEvent.FOCUS_EVENT_MASK
+            | AWTEvent.MOUSE_EVENT_MASK
+            | AWTEvent.MOUSE_MOTION_EVENT_MASK
+            | AWTEvent.MOUSE_WHEEL_EVENT_MASK
+            | AWTEvent.KEY_EVENT_MASK);
+
+        try {
+            System.setProperty("sun.awt.noerasebackground", "true");
+            System.setProperty("sun.awt.erasebackgroundonresize", "false");
+        } catch (SecurityException exception) {
+            // No-op
+        }
+
+        setFocusTraversalKeysEnabled(false);
+
+        // Listen for changes to the font desktop hints property
+        Toolkit toolkit = Toolkit.getDefaultToolkit();
+        toolkit.addPropertyChangeListener("awt.font.desktophints", new PropertyChangeListener() {
+            @Override
+            public void propertyChange(PropertyChangeEvent event) {
+                invalidate();
+            }
+        });
+    }
+
+    public Stage getStage() {
+        return stage;
+    }
+
+    @Override
+    public boolean isDoubleBuffered() {
+        return doubleBuffered;
+    }
+
+    public void setDoubleBuffered(boolean doubleBuffered) {
+        this.doubleBuffered = doubleBuffered;
+    }
+
+    public boolean getDisableVolatileBuffer() {
+        return disableVolatileBuffer;
+    }
+
+    public void setDisableVolatileBuffer(boolean disableVolatileBuffer) {
+        this.disableVolatileBuffer = disableVolatileBuffer;
+    }
+
+    public boolean getDebugPaint() {
+        return debugPaint;
+    }
+
+    public void setDebugPaint(boolean debugPaint) {
+        this.debugPaint = debugPaint;
+    }
+
+    public boolean getDebugFocus() {
+        return debugFocus;
+    }
+
+    public void setDebugFocus(boolean debugFocus) {
+        this.debugFocus = debugFocus;
+
+        // TODO
+
+        repaint();
+    }
+
+    @Override
+    public Dimension getPreferredSize() {
+        return new Dimension(stage.getPreferredWidth(), stage.getPreferredHeight());
+    }
+
+    @Override
+    public void repaint(int x, int y, int width, int height) {
+        // Ensure that the repaint call is properly bounded (some
+        // implementations of AWT do not properly clip the repaint call
+        // when x or y is negative: the negative value is converted to 0,
+        // but the width/height is not adjusted)
+        if (x < 0) {
+            width = Math.max(width + x, 0);
+            x = 0;
+        }
+
+        if (y < 0) {
+            height = Math.max(height + y, 0);
+            y = 0;
+        }
+
+        if (width > 0
+            && height > 0) {
+            super.repaint(x, y, width, height);
+
+            paintPending = true;
+        }
+    }
+
+    @Override
+    public void paint(java.awt.Graphics graphics) {
+        // Intersect the clip region with the bounds of this component
+        // (for some reason, AWT does not do this automatically)
+        graphics.clipRect(0, 0, getWidth(), getHeight());
+
+        java.awt.Rectangle clipBounds = graphics.getClipBounds();
+        if (clipBounds != null
+            && !clipBounds.isEmpty()) {
+            Graphics2D graphics2D = (Graphics2D)graphics;
+
+            try {
+                if (doubleBuffered) {
+                    if (disableVolatileBuffer
+                        || !paintVolatileBuffered(graphics2D)) {
+                        if (!paintBuffered(graphics2D)) {
+                            paintUnbuffered(graphics2D);
+                        }
+                    }
+                } else {
+                    paintUnbuffered(graphics2D);
+                }
+
+                if (debugPaint) {
+                    Random random = new Random();
+                    graphics.setColor(new java.awt.Color(random.nextInt(256),
+                        random.nextInt(256), random.nextInt(256), 75));
+                    graphics.fillRect(0, 0, getWidth(), getHeight());
+                }
+            } catch (RuntimeException exception) {
+                exception.printStackTrace();
+                throw exception;
+            }
+        }
+
+        paintPending = false;
+    }
+
+    @Override
+    public void update(java.awt.Graphics graphics) {
+        paint(graphics);
+    }
+
+    /**
+     * Attempts to paint the stage using an offscreen buffer.
+     *
+     * @param graphics
+     * The source graphics context.
+     *
+     * @return
+     * <tt>true</tt> if the stage was painted using the offscreen
+     * buffer; <tt>false</tt>, otherwise.
+     */
+    private boolean paintBuffered(Graphics2D graphics) {
+        boolean painted = false;
+
+        // Paint the stage into an offscreen buffer
+        GraphicsConfiguration gc = graphics.getDeviceConfiguration();
+        java.awt.Rectangle clipBounds = graphics.getClipBounds();
+        java.awt.image.BufferedImage bufferedImage =
+            gc.createCompatibleImage(clipBounds.width, clipBounds.height, Transparency.OPAQUE);
+
+        if (bufferedImage != null) {
+            Graphics2D bufferedImageGraphics = (Graphics2D)bufferedImage.getGraphics();
+            bufferedImageGraphics.setClip(0, 0, clipBounds.width, clipBounds.height);
+            bufferedImageGraphics.translate(-clipBounds.x, -clipBounds.y);
+
+            try {
+                paintUnbuffered(bufferedImageGraphics);
+                graphics.drawImage(bufferedImage, clipBounds.x, clipBounds.y, this);
+            } finally {
+                bufferedImageGraphics.dispose();
+            }
+
+            painted = true;
+        }
+
+        return painted;
+    }
+
+    /**
+     * Attempts to paint the stage using a volatile offscreen buffer.
+     *
+     * @param graphics
+     * The source graphics context.
+     *
+     * @return
+     * <tt>true</tt> if the stage was painted using the offscreen
+     * buffer; <tt>false</tt>, otherwise.
+     */
+    private boolean paintVolatileBuffered(Graphics2D graphics) {
+        boolean painted = false;
+
+        // Paint the stage into a volatile offscreen buffer
+        GraphicsConfiguration gc = graphics.getDeviceConfiguration();
+        java.awt.Rectangle clipBounds = graphics.getClipBounds();
+        java.awt.image.VolatileImage volatileImage =
+            gc.createCompatibleVolatileImage(clipBounds.width, clipBounds.height,
+                Transparency.OPAQUE);
+
+        if (volatileImage != null) {
+            int valid = volatileImage.validate(gc);
+
+            if (valid == java.awt.image.VolatileImage.IMAGE_OK
+                || valid == java.awt.image.VolatileImage.IMAGE_RESTORED) {
+                Graphics2D volatileImageGraphics = volatileImage.createGraphics();
+                volatileImageGraphics.setClip(0, 0, clipBounds.width, clipBounds.height);
+                volatileImageGraphics.translate(-clipBounds.x, -clipBounds.y);
+
+                try {
+                    paintUnbuffered(volatileImageGraphics);
+                    graphics.drawImage(volatileImage, clipBounds.x, clipBounds.y, this);
+                } finally {
+                    volatileImageGraphics.dispose();
+                }
+
+                painted = !volatileImage.contentsLost();
+            }
+        }
+
+        return painted;
+    }
+
+    /**
+     * Paints the stage without any buffering.
+     *
+     * @param graphics
+     */
+    private void paintUnbuffered(Graphics2D graphics) {
+        graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED);
+
+        AWTGraphics awtGraphics = new AWTGraphics(graphics);
+        stage.paint(awtGraphics);
+    }
+
+    @Override
+    protected void processComponentEvent(ComponentEvent event) {
+        super.processComponentEvent(event);
+
+        switch (event.getID()) {
+            case ComponentEvent.COMPONENT_RESIZED: {
+                stage.setSize(Math.max(getWidth(), 0), Math.max(getHeight(), 0));
+                break;
+            }
+        }
+    }
+
+    @Override
+    protected void processFocusEvent(FocusEvent event) {
+        super.processFocusEvent(event);
+
+        switch(event.getID()) {
+            case FocusEvent.FOCUS_GAINED: {
+                if (focusOwner != null
+                    && focusOwner.isShowing()
+                    && !focusOwner.isBlocked()) {
+                    focusOwner.requestFocus();
+                }
+
+                focusOwner = null;
+
+                break;
+            }
+
+            case FocusEvent.FOCUS_LOST: {
+                focusOwner = Node.getFocusedNode();
+                Node.clearFocus();
+
+                break;
+            }
+        }
+    }
+
+    @Override
+    protected void processMouseEvent(MouseEvent event) {
+        super.processMouseEvent(event);
+
+        int x = event.getX();
+        int y = event.getY();
+
+        // Set the mouse button state
+        int mouseButtons = 0x00;
+
+        int modifiersEx = event.getModifiersEx();
+        if ((modifiersEx & MouseEvent.BUTTON1_DOWN_MASK) > 0) {
+            mouseButtons |= Mouse.Button.LEFT.getMask();
+        }
+
+        if ((modifiersEx & MouseEvent.BUTTON2_DOWN_MASK) > 0) {
+            mouseButtons |= Mouse.Button.MIDDLE.getMask();
+        }
+
+        if ((modifiersEx & MouseEvent.BUTTON3_DOWN_MASK) > 0) {
+            mouseButtons |= Mouse.Button.RIGHT.getMask();
+        }
+
+        Mouse.setButtons(mouseButtons);
+
+        // Get the button associated with this event
+        Mouse.Button button = null;
+        switch (event.getButton()) {
+            case MouseEvent.BUTTON1: {
+                button = Mouse.Button.LEFT;
+                break;
+            }
+
+            case MouseEvent.BUTTON2: {
+                button = Mouse.Button.MIDDLE;
+                break;
+            }
+
+            case MouseEvent.BUTTON3: {
+                button = Mouse.Button.RIGHT;
+                break;
+            }
+        }
+
+        // Process the event
+        boolean consumed = false;
+        try {
+            switch(event.getID()) {
+                case MouseEvent.MOUSE_ENTERED: {
+                    stage.mouseEntered();
+                    break;
+                }
+
+                case MouseEvent.MOUSE_EXITED: {
+                    stage.mouseExited();
+                    break;
+                }
+
+                case MouseEvent.MOUSE_PRESSED: {
+                    consumed = stage.mousePressed(button, x, y);
+                    break;
+                }
+
+                case MouseEvent.MOUSE_RELEASED: {
+                    consumed = stage.mouseReleased(button, x, y);
+                    break;
+                }
+            }
+        } catch (Exception exception) {
+            exception.printStackTrace();
+        }
+
+        if (consumed) {
+            event.consume();
+        }
+    }
+
+    @Override
+    protected void processMouseMotionEvent(MouseEvent event) {
+        super.processMouseMotionEvent(event);
+
+        if (!paintPending) {
+            int x = event.getX();
+            int y = event.getY();
+
+            // Process the event
+            boolean consumed = false;
+            try {
+                switch (event.getID()) {
+                    case MouseEvent.MOUSE_MOVED: {
+                        mouseCapturer = null;
+
+                        consumed = stage.mouseMoved(x, y, false);
+                        break;
+                    }
+
+                    case MouseEvent.MOUSE_DRAGGED: {
+                        if (mouseCapturer == null) {
+                            mouseCapturer = stage.getDescendantAt(x, y);
+                        }
+
+                        Point location = mouseCapturer.mapPointFromAncestor(stage, x, y);
+                        consumed = mouseCapturer.mouseMoved(location.x, location.y, true);
+                        break;
+                    }
+                }
+            } catch (Exception exception) {
+                exception.printStackTrace();
+            }
+
+            if (consumed) {
+                event.consume();
+            }
+        }
+    }
+
+    @Override
+    protected void processMouseWheelEvent(MouseWheelEvent event) {
+        super.processMouseWheelEvent(event);
+
+        // Get the event coordinates
+        int x = event.getX();
+        int y = event.getY();
+
+        // Get the scroll type
+        Mouse.ScrollType scrollType = null;
+        switch (event.getScrollType()) {
+            case MouseWheelEvent.WHEEL_BLOCK_SCROLL: {
+                scrollType = Mouse.ScrollType.BLOCK;
+                break;
+            }
+
+            case MouseWheelEvent.WHEEL_UNIT_SCROLL: {
+                scrollType = Mouse.ScrollType.UNIT;
+                break;
+            }
+        }
+
+        // Process the event
+        boolean consumed = false;
+        try {
+            switch (event.getID()) {
+                case MouseEvent.MOUSE_WHEEL: {
+                    consumed = stage.mouseWheelScrolled(scrollType, event.getScrollAmount(),
+                        event.getWheelRotation(), x, y);
+                    break;
+                }
+            }
+        } catch (Exception exception) {
+            exception.printStackTrace();
+        }
+
+        if (consumed) {
+            event.consume();
+        }
+    }
+
+    @Override
+    protected void processKeyEvent(KeyEvent event) {
+        super.processKeyEvent(event);
+
+        if (focusOwner != null
+            && !focusOwner.isBlocked()) {
+            int modifiersEx = event.getModifiersEx();
+            int awtKeyLocation = event.getKeyLocation();
+
+            // Set the keyboard modifier state
+            int keyboardModifiers = 0;
+            if ((modifiersEx & KeyEvent.SHIFT_DOWN_MASK) > 0) {
+                keyboardModifiers |= Keyboard.Modifier.SHIFT.getMask();
+            }
+
+            // Ignore Control when Alt-Graphics is pressed
+            if ((modifiersEx & KeyEvent.CTRL_DOWN_MASK) > 0
+                && ((modifiersEx & KeyEvent.ALT_DOWN_MASK) == 0
+                    || awtKeyLocation == KeyEvent.KEY_LOCATION_RIGHT)) {
+                keyboardModifiers |= Keyboard.Modifier.CTRL.getMask();
+            }
+
+            if ((modifiersEx & KeyEvent.ALT_DOWN_MASK) > 0) {
+                keyboardModifiers |= Keyboard.Modifier.ALT.getMask();
+            }
+
+            if ((modifiersEx & KeyEvent.META_DOWN_MASK) > 0) {
+                keyboardModifiers |= Keyboard.Modifier.META.getMask();
+            }
+
+            Keyboard.setModifiers(keyboardModifiers);
+
+            // Get the key location
+            Keyboard.KeyLocation keyLocation = null;
+            switch (awtKeyLocation) {
+                case KeyEvent.KEY_LOCATION_STANDARD: {
+                    keyLocation = Keyboard.KeyLocation.STANDARD;
+                    break;
+                }
+
+                case KeyEvent.KEY_LOCATION_LEFT: {
+                    keyLocation = Keyboard.KeyLocation.LEFT;
+                    break;
+                }
+
+                case KeyEvent.KEY_LOCATION_RIGHT: {
+                    keyLocation = Keyboard.KeyLocation.RIGHT;
+                    break;
+                }
+
+                case KeyEvent.KEY_LOCATION_NUMPAD: {
+                    keyLocation = Keyboard.KeyLocation.KEYPAD;
+                    break;
+                }
+            }
+
+            // Process the event
+            boolean consumed = false;
+            try {
+                switch (event.getID()) {
+                    case KeyEvent.KEY_PRESSED: {
+                        int keyCode = event.getKeyCode();
+                        consumed = focusOwner.keyPressed(keyCode, keyLocation);
+                        break;
+                    }
+
+                    case KeyEvent.KEY_RELEASED: {
+                        int keyCode = event.getKeyCode();
+                        consumed = focusOwner.keyReleased(keyCode, keyLocation);
+                        break;
+                    }
+
+                    case KeyEvent.KEY_TYPED: {
+                        char keyChar = event.getKeyChar();
+                        consumed = focusOwner.keyTyped(keyChar);
+                        break;
+                    }
+                }
+            } catch (Exception exception) {
+                exception.printStackTrace();
+            }
+
+            if (consumed) {
+                event.consume();
+            }
+        }
+    }
+}

Added: pivot/branches/3.x/platform-awt/src/org/apache/pivot/scene/CharSequenceCharacterIterator.java
URL: http://svn.apache.org/viewvc/pivot/branches/3.x/platform-awt/src/org/apache/pivot/scene/CharSequenceCharacterIterator.java?rev=1057053&view=auto
==============================================================================
--- pivot/branches/3.x/platform-awt/src/org/apache/pivot/scene/CharSequenceCharacterIterator.java (added)
+++ pivot/branches/3.x/platform-awt/src/org/apache/pivot/scene/CharSequenceCharacterIterator.java Sun Jan  9 23:19:19 2011
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you 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 org.apache.pivot.scene;
+
+import java.text.CharacterIterator;
+
+/**
+ * Character iterator that is backed by a {@link java.lang.CharSequence}.
+ */
+public class CharSequenceCharacterIterator implements CharacterIterator {
+    private CharSequence charSequence;
+    private int beginIndex;
+    private int endIndex;
+
+    private int index = -1;
+
+    public CharSequenceCharacterIterator(CharSequence charSequence) {
+        this(charSequence, 0);
+    }
+
+    public CharSequenceCharacterIterator(CharSequence charSequence, int beginIndex) {
+        this(charSequence, beginIndex, -1);
+    }
+
+    public CharSequenceCharacterIterator(CharSequence charSequence, int beginIndex, int endIndex) {
+        this(charSequence, beginIndex, endIndex, beginIndex);
+    }
+
+    public CharSequenceCharacterIterator(CharSequence charSequence, int beginIndex, int endIndex, int index) {
+        if (charSequence == null) {
+            throw new IllegalArgumentException();
+        }
+
+        if (endIndex == -1) {
+            endIndex = charSequence.length();
+        }
+
+        if (beginIndex > endIndex) {
+            throw new IllegalArgumentException();
+        }
+
+        if (beginIndex < 0
+            || endIndex > charSequence.length()) {
+            throw new IndexOutOfBoundsException();
+        }
+
+        if (index < beginIndex
+            || index > endIndex) {
+            throw new IndexOutOfBoundsException();
+        }
+
+        this.charSequence = charSequence;
+        this.beginIndex = beginIndex;
+        this.endIndex = endIndex;
+
+        setIndex(index);
+    }
+
+    @Override
+    public char first() {
+        return setIndex(beginIndex);
+    }
+
+    @Override
+    public char last() {
+        return setIndex(charSequence.length() == 0 ? endIndex : endIndex - 1);
+    }
+
+    @Override
+    public char next() {
+        return setIndex(index < endIndex ? index + 1 : DONE);
+    }
+
+    @Override
+    public char previous() {
+        return setIndex(index > beginIndex ? index - 1 : DONE);
+    }
+
+    @Override
+    public char current() {
+        return (index < endIndex) ? charSequence.charAt(index) : DONE;
+    }
+
+    @Override
+    public int getBeginIndex() {
+        return beginIndex;
+    }
+
+    @Override
+    public int getEndIndex() {
+        return endIndex;
+    }
+
+    @Override
+    public int getIndex() {
+        return index;
+    }
+
+    @Override
+    public char setIndex(int index) {
+        if (index < beginIndex
+            || index > endIndex) {
+            throw new IndexOutOfBoundsException();
+        }
+
+        this.index = index;
+
+        return current();
+    }
+
+    @Override
+    public Object clone() {
+        return new CharSequenceCharacterIterator(charSequence, beginIndex, endIndex, index);
+    }
+}

Added: pivot/branches/3.x/platform-awt/src/org/apache/pivot/ui/BrowserApplicationContext.java
URL: http://svn.apache.org/viewvc/pivot/branches/3.x/platform-awt/src/org/apache/pivot/ui/BrowserApplicationContext.java?rev=1057053&view=auto
==============================================================================
--- pivot/branches/3.x/platform-awt/src/org/apache/pivot/ui/BrowserApplicationContext.java (added)
+++ pivot/branches/3.x/platform-awt/src/org/apache/pivot/ui/BrowserApplicationContext.java Sun Jan  9 23:19:19 2011
@@ -0,0 +1,203 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you 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 org.apache.pivot.ui;
+
+import java.applet.Applet;
+import java.awt.EventQueue;
+import java.awt.Graphics;
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.InvocationTargetException;
+import java.net.URLDecoder;
+import java.util.HashMap;
+import java.util.Locale;
+
+import org.apache.pivot.scene.AWTStageHost;
+
+/**
+ * Applet used to host applications in a web browser.
+ * <p>
+ * This applet supports the following parameters:
+ * <ul>
+ * <li><tt>application_class_name</tt> - the class name of the application to launch.</li>
+ * <li><tt>startup_properties</tt> - startup properties to be passed to the application.
+ * Properties use HTTP query string syntax; e.g. "a=1&b=2".</li>
+ * <li><tt>system_properties</tt> - system properties to set at startup. Properties use HTTP
+ * query string syntax; e.g. "a=1&b=2" (trusted applets only).</li>
+ * </ul>
+ */
+public class BrowserApplicationContext extends Applet {
+    private static final long serialVersionUID = 0;
+
+    private Application application = null;
+
+    public static final String APPLICATION_CLASS_NAME_PARAMETER = "application_class_name";
+    public static final String STARTUP_PROPERTIES_PARAMETER = "startup_properties";
+    public static final String SYSTEM_PROPERTIES_PARAMETER = "system_properties";
+
+    @Override
+    public void init() {
+        // Load the application
+        String applicationClassName = getParameter(APPLICATION_CLASS_NAME_PARAMETER);
+
+        if (applicationClassName == null) {
+            System.err.println(APPLICATION_CLASS_NAME_PARAMETER + " parameter is required.");
+        } else {
+            try {
+                Class<?> applicationClass = Class.forName(applicationClassName);
+                application = (Application)applicationClass.newInstance();
+            } catch (Throwable throwable) {
+                throw new RuntimeException(throwable);
+            }
+        }
+
+        // Load properties specified in the startup properties parameter
+        final HashMap<String, String> startupProperties = new HashMap<String, String>();
+
+        String startupPropertiesParameter = getParameter(STARTUP_PROPERTIES_PARAMETER);
+        if (startupPropertiesParameter != null) {
+            String[] arguments = startupPropertiesParameter.split("&");
+
+            for (int i = 0, n = arguments.length; i < n; i++) {
+                String argument = arguments[i];
+                String[] property = argument.split("=");
+
+                if (property.length == 2) {
+                    String key = property[0].trim();
+                    String value;
+                    try {
+                        value = URLDecoder.decode(property[1].trim(), "UTF-8");
+                    } catch (UnsupportedEncodingException exception) {
+                        throw new RuntimeException(exception);
+                    }
+                    startupProperties.put(key, value);
+                } else {
+                    System.err.println(argument + " is not a valid startup property.");
+                }
+            }
+        }
+
+        // Load properties specified in the system properties parameter
+        String systemPropertiesParameter = getParameter(SYSTEM_PROPERTIES_PARAMETER);
+        if (systemPropertiesParameter != null) {
+            String[] arguments = systemPropertiesParameter.split("&");
+
+            String language = null;
+            String region = null;
+
+            for (int i = 0, n = arguments.length; i < n; i++) {
+                String argument = arguments[i];
+                String[] property = argument.split("=");
+
+                if (property.length == 2) {
+                    String key = property[0].trim();
+                    String value;
+                    try {
+                        value = URLDecoder.decode(property[1].trim(), "UTF-8");
+                    } catch (UnsupportedEncodingException exception) {
+                        throw new RuntimeException(exception);
+                    }
+
+                    if (key.equals("user.language")) {
+                        language = value;
+                    } else if (key.equals("user.region")) {
+                        region = value;
+                    } else {
+                        System.setProperty(key, value);
+                    }
+                } else {
+                    System.err.println(argument + " is not a valid system property.");
+                }
+            }
+
+            if (language != null) {
+                Locale.setDefault((region == null) ? new Locale(language) : new Locale(language, region));
+            }
+        }
+
+        // Add stage host to applet
+        final AWTStageHost awtStageHost = new AWTStageHost();
+        awtStageHost.getStage().setLayout(new StageLayout());
+        setLayout(new java.awt.BorderLayout());
+        add(awtStageHost);
+
+        // Set applet properties
+        setFocusTraversalKeysEnabled(false);
+        setBackground(null);
+
+        // Start up the application
+        Runnable startupCallback = new Runnable() {
+            @Override
+            public void run() {
+                if (application != null) {
+                    try {
+                        application.startup(awtStageHost.getStage(), startupProperties);
+                    } catch (Exception exception) {
+                        exception.printStackTrace();
+                    }
+                }
+            }
+        };
+
+        if (java.awt.EventQueue.isDispatchThread()) {
+            startupCallback.run();
+        } else {
+            try {
+                EventQueue.invokeAndWait(startupCallback);
+            } catch (InterruptedException exception) {
+                throw new RuntimeException(exception);
+            } catch (InvocationTargetException exception) {
+                throw new RuntimeException(exception);
+            }
+        }
+    }
+
+    @Override
+    public void destroy() {
+        // Shut down the application
+        Runnable shutdownCallback = new Runnable() {
+            @Override
+            public void run() {
+                if (application != null) {
+                    try {
+                        application.shutdown(false);
+                    } catch (Exception exception) {
+                        exception.printStackTrace();
+                    }
+
+                    application = null;
+                }
+            }
+        };
+
+        if (java.awt.EventQueue.isDispatchThread()) {
+            shutdownCallback.run();
+        } else {
+            try {
+                EventQueue.invokeAndWait(shutdownCallback);
+            } catch (InterruptedException exception) {
+                throw new RuntimeException(exception);
+            } catch (InvocationTargetException exception) {
+                throw new RuntimeException(exception);
+            }
+        }
+    }
+
+    @Override
+    public void update(Graphics graphics) {
+        paint(graphics);
+    }
+}

Added: pivot/branches/3.x/platform-awt/src/org/apache/pivot/ui/DesktopApplicationContext.java
URL: http://svn.apache.org/viewvc/pivot/branches/3.x/platform-awt/src/org/apache/pivot/ui/DesktopApplicationContext.java?rev=1057053&view=auto
==============================================================================
--- pivot/branches/3.x/platform-awt/src/org/apache/pivot/ui/DesktopApplicationContext.java (added)
+++ pivot/branches/3.x/platform-awt/src/org/apache/pivot/ui/DesktopApplicationContext.java Sun Jan  9 23:19:19 2011
@@ -0,0 +1,303 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you 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 org.apache.pivot.ui;
+
+import java.awt.Graphics;
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsEnvironment;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.awt.image.BufferedImage;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.prefs.BackingStoreException;
+import java.util.prefs.Preferences;
+
+import org.apache.pivot.scene.AWTStageHost;
+import org.apache.pivot.scene.media.Image;
+
+/**
+ * Application context used to execute applications in a native frame window.
+ */
+public class DesktopApplicationContext {
+    private static Application application = null;
+
+    private static java.awt.Frame hostFrame = new java.awt.Frame() {
+        private static final long serialVersionUID = 0;
+
+        @Override
+        public void update(Graphics graphics) {
+            paint(graphics);
+        }
+    };
+
+    public static final String X_ARGUMENT = "x";
+    public static final String Y_ARGUMENT = "y";
+    public static final String WIDTH_ARGUMENT = "width";
+    public static final String HEIGHT_ARGUMENT = "height";
+    public static final String CENTER_ARGUMENT = "center";
+    public static final String MAXIMIZED_ARGUMENT = "maximized";
+    public static final String RESIZABLE_ARGUMENT = "resizable";
+    public static final String UNDECORATED_ARGUMENT = "undecorated";
+
+    private static final String INVALID_PROPERTY_FORMAT_MESSAGE = "\"%s\" is not a valid startup "
+        + "property (expected format is \"--name=value\").";
+    private static final String INVALID_PROPERTY_VALUE_MESSAGE = "\"%s\" is not a valid value for "
+        + "startup property \"%s\".";
+
+    public static Application getApplication() {
+        return application;
+    }
+
+    public static java.awt.Frame getHostFrame() {
+        return hostFrame;
+    }
+
+    /**
+     * Primary aplication entry point.
+     *
+     * @param args
+     */
+    public static void main(String[] args) {
+        // Load the application
+        if (args.length == 0) {
+            System.err.println("Application class name is required.");
+            return;
+        }
+
+        String applicationClassName = args[0];
+
+        try {
+            Class<?> applicationClass = Class.forName(applicationClassName);
+            application = (Application)applicationClass.newInstance();
+        } catch (Throwable throwable) {
+            throw new RuntimeException(throwable);
+        }
+
+        // Get the startup properties
+        HashMap<String, String> properties = new HashMap<String, String>();
+
+        int x = 0;
+        int y = 0;
+        int width = 800;
+        int height = 600;
+        boolean center = false;
+        boolean maximized = false;
+        boolean resizable = true;
+        boolean undecorated = false;
+
+        try {
+            Preferences preferences = Preferences.userNodeForPackage(DesktopApplicationContext.class);
+            preferences = preferences.node(applicationClassName);
+
+            x = preferences.getInt(X_ARGUMENT, x);
+            y = preferences.getInt(Y_ARGUMENT, y);
+            width = preferences.getInt(WIDTH_ARGUMENT, width);
+            height = preferences.getInt(HEIGHT_ARGUMENT, height);
+            maximized = preferences.getBoolean(MAXIMIZED_ARGUMENT, maximized);
+
+            // Update positioning if window is off-screen
+            GraphicsDevice[] screenDevices = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices();
+            if (screenDevices.length == 1) {
+                if (x < 0) {
+                    x = 0;
+                }
+
+                if (y < 0) {
+                    y = 0;
+                }
+            }
+        } catch (SecurityException exception) {
+            System.err.println("Unable to retrieve startup preferences: " + exception);
+        }
+
+        for (int i = 1, n = args.length; i < n; i++) {
+            String arg = args[i];
+
+            if (arg.startsWith("--")) {
+                arg = arg.substring(2);
+                String[] property = arg.split("=");
+
+                if (property.length == 2) {
+                    String key = property[0];
+                    String value = property[1];
+
+                    try {
+                        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(MAXIMIZED_ARGUMENT)) {
+                            maximized = Boolean.parseBoolean(value);
+                        } else if (key.equals(RESIZABLE_ARGUMENT)) {
+                            resizable = Boolean.parseBoolean(value);
+                        } else if (key.equals(UNDECORATED_ARGUMENT)) {
+                            undecorated = Boolean.parseBoolean(value);
+                        } else {
+                            properties.put(key, value);
+                        }
+                    } catch (Exception exception) {
+                        System.err.println(String.format(INVALID_PROPERTY_VALUE_MESSAGE, value, key));
+                    }
+                } else {
+                    System.err.println(String.format(INVALID_PROPERTY_FORMAT_MESSAGE, arg));
+                }
+            } else {
+                System.err.println(String.format(INVALID_PROPERTY_FORMAT_MESSAGE, arg));
+            }
+        }
+
+        // Add stage host to host frame
+        AWTStageHost awtStageHost = new AWTStageHost();
+        awtStageHost.getStage().setLayout(new StageLayout());
+        hostFrame.add(awtStageHost);
+
+        // Add host frame listeners
+        hostFrame.addWindowListener(new WindowAdapter() {
+            @Override
+            public void windowOpened(WindowEvent event) {
+                event.getWindow().requestFocus();
+            }
+
+            @Override
+            public void windowClosing(WindowEvent arg0) {
+                exit();
+            }
+
+            @Override
+            public void windowClosed(WindowEvent arg0) {
+                System.exit(0);
+            }
+
+            @Override
+            public void windowIconified(WindowEvent arg0) {
+                try {
+                    application.suspend();
+                } catch(Exception exception) {
+                    exception.printStackTrace();
+                }
+            }
+
+            @Override
+            public void windowDeiconified(WindowEvent arg0) {
+                try {
+                    application.resume();
+                } catch(Exception exception) {
+                    exception.printStackTrace();
+                }
+            }
+        });
+
+        // Set the host frame properties
+        hostFrame.setTitle(application.getTitle());
+
+        List<Image> icons = application.getIcons();
+        if (icons != null) {
+            ArrayList<java.awt.Image> iconImages = new ArrayList<java.awt.Image>(icons.size());
+            for (Image image : icons) {
+                iconImages.add((BufferedImage)image.getRaster().getNativeRaster());
+            }
+
+            hostFrame.setIconImages(iconImages);
+        } else {
+            hostFrame.setIconImages(null);
+        }
+
+        hostFrame.setFocusTraversalKeysEnabled(false);
+        hostFrame.setBackground(null);
+
+        hostFrame.setSize(width, height);
+
+        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);
+        }
+
+        if (maximized) {
+            hostFrame.setExtendedState(java.awt.Frame.MAXIMIZED_BOTH);
+        }
+
+        hostFrame.setResizable(resizable);
+        hostFrame.setUndecorated(undecorated);
+
+        // Show the host frame
+        hostFrame.setVisible(true);
+
+        // Start up the application
+        try {
+            application.startup(awtStageHost.getStage(), properties);
+        } catch (Exception exception) {
+            exception.printStackTrace();
+        }
+    }
+
+    /**
+     * Terminates the application context.
+     */
+    public static boolean exit() {
+        boolean cancelShutdown = false;
+
+        if (application != null) {
+            // Shut down the application
+            try {
+                cancelShutdown = application.shutdown(true);
+            } catch(Exception exception) {
+                exception.printStackTrace();
+            }
+
+            if (!cancelShutdown) {
+                try {
+                    Preferences preferences = Preferences.userNodeForPackage(DesktopApplicationContext.class);
+                    preferences = preferences.node(application.getClass().getName());
+
+                    boolean maximized = (hostFrame.getExtendedState()
+                        & java.awt.Frame.MAXIMIZED_BOTH) == java.awt.Frame.MAXIMIZED_BOTH;
+                    if (!maximized) {
+                        preferences.putInt(X_ARGUMENT, hostFrame.getX());
+                        preferences.putInt(Y_ARGUMENT, hostFrame.getY());
+                        preferences.putInt(WIDTH_ARGUMENT, hostFrame.getWidth());
+                        preferences.putInt(HEIGHT_ARGUMENT, hostFrame.getHeight());
+                    }
+
+                    preferences.putBoolean(MAXIMIZED_ARGUMENT, maximized);
+
+                    preferences.flush();
+                } catch (SecurityException exception) {
+                    // No-op
+                } catch (BackingStoreException exception) {
+                    // No-op
+                }
+            }
+        }
+
+        if (!cancelShutdown) {
+            hostFrame.dispose();
+        }
+
+        return cancelShutdown;
+    }
+}

Added: pivot/branches/3.x/platform-swt/.classpath
URL: http://svn.apache.org/viewvc/pivot/branches/3.x/platform-swt/.classpath?rev=1057053&view=auto
==============================================================================
--- pivot/branches/3.x/platform-swt/.classpath (added)
+++ pivot/branches/3.x/platform-swt/.classpath Sun Jan  9 23:19:19 2011
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/core"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/scene"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/ui"/>
+	<classpathentry kind="lib" path="lib/swt-debug.jar"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>

Added: pivot/branches/3.x/platform-swt/.project
URL: http://svn.apache.org/viewvc/pivot/branches/3.x/platform-swt/.project?rev=1057053&view=auto
==============================================================================
--- pivot/branches/3.x/platform-swt/.project (added)
+++ pivot/branches/3.x/platform-swt/.project Sun Jan  9 23:19:19 2011
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>platform-swt</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>

Added: pivot/branches/3.x/platform-swt/lib/swt-debug.jar
URL: http://svn.apache.org/viewvc/pivot/branches/3.x/platform-swt/lib/swt-debug.jar?rev=1057053&view=auto
==============================================================================
Binary file - no diff available.

Propchange: pivot/branches/3.x/platform-swt/lib/swt-debug.jar
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: pivot/branches/3.x/platform-swt/src/META-INF/org.apache.pivot.scene.Platform
URL: http://svn.apache.org/viewvc/pivot/branches/3.x/platform-swt/src/META-INF/org.apache.pivot.scene.Platform?rev=1057053&view=auto
==============================================================================
--- pivot/branches/3.x/platform-swt/src/META-INF/org.apache.pivot.scene.Platform (added)
+++ pivot/branches/3.x/platform-swt/src/META-INF/org.apache.pivot.scene.Platform Sun Jan  9 23:19:19 2011
@@ -0,0 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to you 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.
+
+# Service provider for SWT platform 
+org.apache.pivot.scene.SWTPlatform

Added: pivot/branches/3.x/platform-swt/src/org/apache/pivot/scene/SWTGraphics.java
URL: http://svn.apache.org/viewvc/pivot/branches/3.x/platform-swt/src/org/apache/pivot/scene/SWTGraphics.java?rev=1057053&view=auto
==============================================================================
--- pivot/branches/3.x/platform-swt/src/org/apache/pivot/scene/SWTGraphics.java (added)
+++ pivot/branches/3.x/platform-swt/src/org/apache/pivot/scene/SWTGraphics.java Sun Jan  9 23:19:19 2011
@@ -0,0 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you 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 org.apache.pivot.scene;
+
+public class SWTGraphics {
+    // TODO
+}

Added: pivot/branches/3.x/platform-swt/src/org/apache/pivot/scene/SWTPlatform.java
URL: http://svn.apache.org/viewvc/pivot/branches/3.x/platform-swt/src/org/apache/pivot/scene/SWTPlatform.java?rev=1057053&view=auto
==============================================================================
--- pivot/branches/3.x/platform-swt/src/org/apache/pivot/scene/SWTPlatform.java (added)
+++ pivot/branches/3.x/platform-swt/src/org/apache/pivot/scene/SWTPlatform.java Sun Jan  9 23:19:19 2011
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you 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 org.apache.pivot.scene;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.apache.pivot.scene.Font;
+import org.apache.pivot.scene.LinearGradientPaint;
+import org.apache.pivot.scene.PathGeometry;
+import org.apache.pivot.scene.Platform;
+import org.apache.pivot.scene.RadialGradientPaint;
+import org.apache.pivot.scene.SolidColorPaint;
+import org.apache.pivot.scene.Stroke;
+import org.apache.pivot.scene.media.Raster;
+import org.eclipse.swt.graphics.Pattern;
+
+/**
+ * AWT platform implementation.
+ */
+public class SWTPlatform extends Platform {
+    @Override
+    public Font.Metrics getFontMetrics(Font font) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public float measureText(Font font, CharSequence text, int start, int length) {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public Raster readRaster(InputStream inputStream) throws IOException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public void writeRaster(Raster raster, String mimeType,  OutputStream outputStream)
+        throws IOException {
+    }
+
+    @Override
+    protected org.eclipse.swt.graphics.Font getNativeFont(Font font) {
+        // TODO Return a FontReference; this will be a wrapper class that
+        // contains both a reference to the Font itself as well as the
+        // native font instance. In the FontReference finalizer(), we'll
+        // remove the entry from the reference-counted map and dispose
+        // the native font, if necessary. We'll also dispose() all
+        // undisposed resources when the stage host component is disposed.
+
+        return null;
+    }
+
+    @Override
+    protected org.eclipse.swt.graphics.Color getNativePaint(SolidColorPaint solidColorPaint) {
+        // TODO Return a ColorReference
+        return null;
+    }
+
+    @Override
+    protected Pattern getNativePaint(LinearGradientPaint linearGradientPaint) {
+        // TODO Return a PatternReference
+        return null;
+    }
+
+    @Override
+    protected Pattern getNativePaint(RadialGradientPaint radialGradientPaint) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    protected Object getNativeStroke(Stroke stroke) {
+        return null;
+    }
+
+    @Override
+    protected Object getNativePathGeometry(PathGeometry pathGeometry) {
+        // TODO
+        return null;
+    }
+}

Added: pivot/branches/3.x/platform-swt/src/org/apache/pivot/scene/SWTRaster.java
URL: http://svn.apache.org/viewvc/pivot/branches/3.x/platform-swt/src/org/apache/pivot/scene/SWTRaster.java?rev=1057053&view=auto
==============================================================================
--- pivot/branches/3.x/platform-swt/src/org/apache/pivot/scene/SWTRaster.java (added)
+++ pivot/branches/3.x/platform-swt/src/org/apache/pivot/scene/SWTRaster.java Sun Jan  9 23:19:19 2011
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you 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 org.apache.pivot.scene;
+
+import org.apache.pivot.scene.Color;
+import org.apache.pivot.scene.Graphics;
+import org.apache.pivot.scene.media.Raster;
+
+/**
+ * SWT raster implementation.
+ */
+public class SWTRaster extends Raster {
+    @Override
+    public int getWidth() {
+        // TODO
+        return 0;
+    }
+
+    @Override
+    public int getHeight() {
+        // TODO
+        return 0;
+    }
+
+    @Override
+    public Color getPixel(int x, int y) {
+        // TODO
+        return null;
+    }
+
+    @Override
+    public void setPixel(int x, int y, Color color) {
+        // TODO
+    }
+
+    @Override
+    public Graphics getGraphics() {
+        // TODO
+        return null;
+    }
+
+    @Override
+    // TODO Return typed value
+    public Object getNativeRaster() {
+        // TODO
+        return null;
+    }
+}

Added: pivot/branches/3.x/platform-swt/src/org/apache/pivot/scene/SWTStageHost.java
URL: http://svn.apache.org/viewvc/pivot/branches/3.x/platform-swt/src/org/apache/pivot/scene/SWTStageHost.java?rev=1057053&view=auto
==============================================================================
--- pivot/branches/3.x/platform-swt/src/org/apache/pivot/scene/SWTStageHost.java (added)
+++ pivot/branches/3.x/platform-swt/src/org/apache/pivot/scene/SWTStageHost.java Sun Jan  9 23:19:19 2011
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you 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 org.apache.pivot.scene;
+
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.Composite;
+
+public class SWTStageHost extends Canvas {
+    public SWTStageHost(Composite parent, int style) {
+        super(parent, style);
+
+        // TODO Use appropriate styles to control redraws
+
+        // TODO Add a paint listener
+    }
+
+    // TODO We'll need to maintain a reference-counted cache of resources
+    // such as fonts and paints. We'll need to dispose that cache when the
+    // stage host is disposed. Maybe we can use weak references to manage
+    // this. We could use a weak map of org.apache.pivot.scene.Font to
+    // org.eclipse.swt.graphics.Font, etc. When the gargbage collector
+    // detects that no more references to a given Font are outstanding,
+    // the association will be removed from the map and we will dispose
+    // the resource.
+}

Added: pivot/branches/3.x/platform-swt/src/org/apache/pivot/ui/DesktopApplicationContext.java
URL: http://svn.apache.org/viewvc/pivot/branches/3.x/platform-swt/src/org/apache/pivot/ui/DesktopApplicationContext.java?rev=1057053&view=auto
==============================================================================
--- pivot/branches/3.x/platform-swt/src/org/apache/pivot/ui/DesktopApplicationContext.java (added)
+++ pivot/branches/3.x/platform-swt/src/org/apache/pivot/ui/DesktopApplicationContext.java Sun Jan  9 23:19:19 2011
@@ -0,0 +1,5 @@
+package org.apache.pivot.ui;
+
+public class DesktopApplicationContext {
+
+}

Added: pivot/branches/3.x/platform-swt/src/org/apache/pivot/ui/PluginApplicationContext.java
URL: http://svn.apache.org/viewvc/pivot/branches/3.x/platform-swt/src/org/apache/pivot/ui/PluginApplicationContext.java?rev=1057053&view=auto
==============================================================================
--- pivot/branches/3.x/platform-swt/src/org/apache/pivot/ui/PluginApplicationContext.java (added)
+++ pivot/branches/3.x/platform-swt/src/org/apache/pivot/ui/PluginApplicationContext.java Sun Jan  9 23:19:19 2011
@@ -0,0 +1,5 @@
+package org.apache.pivot.ui;
+
+public class PluginApplicationContext {
+
+}

Added: pivot/branches/3.x/scene/.classpath
URL: http://svn.apache.org/viewvc/pivot/branches/3.x/scene/.classpath?rev=1057053&view=auto
==============================================================================
--- pivot/branches/3.x/scene/.classpath (added)
+++ pivot/branches/3.x/scene/.classpath Sun Jan  9 23:19:19 2011
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/core"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>

Added: pivot/branches/3.x/scene/.project
URL: http://svn.apache.org/viewvc/pivot/branches/3.x/scene/.project?rev=1057053&view=auto
==============================================================================
--- pivot/branches/3.x/scene/.project (added)
+++ pivot/branches/3.x/scene/.project Sun Jan  9 23:19:19 2011
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>scene</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>

Added: pivot/branches/3.x/scene/src/org/apache/pivot/scene/Bounds.java
URL: http://svn.apache.org/viewvc/pivot/branches/3.x/scene/src/org/apache/pivot/scene/Bounds.java?rev=1057053&view=auto
==============================================================================
--- pivot/branches/3.x/scene/src/org/apache/pivot/scene/Bounds.java (added)
+++ pivot/branches/3.x/scene/src/org/apache/pivot/scene/Bounds.java Sun Jan  9 23:19:19 2011
@@ -0,0 +1,227 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you 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 org.apache.pivot.scene;
+
+import java.io.Serializable;
+import java.util.Map;
+
+import org.apache.pivot.beans.BeanAdapter;
+import org.apache.pivot.io.SerializationException;
+import org.apache.pivot.json.JSONSerializer;
+
+/**
+ * Class representing the bounds of an object.
+ */
+public final class Bounds implements Serializable {
+    private static final long serialVersionUID = 0;
+
+    public final int x;
+    public final int y;
+    public final int width;
+    public final int height;
+
+    public static final String X_KEY = "x";
+    public static final String Y_KEY = "y";
+    public static final String WIDTH_KEY = "width";
+    public static final String HEIGHT_KEY = "height";
+
+    public static final Bounds EMPTY = new Bounds(0, 0, 0, 0);
+
+    public Bounds(int x, int y, int width, int height) {
+        this.x = x;
+        this.y = y;
+        this.width = width;
+        this.height = height;
+    }
+
+    public Bounds(Point origin, Dimensions size) {
+        if (origin == null) {
+            throw new IllegalArgumentException("origin is null.");
+        }
+
+        if (size == null) {
+            throw new IllegalArgumentException("size is null.");
+        }
+
+        x = origin.x;
+        y = origin.y;
+        width = size.width;
+        height = size.height;
+    }
+
+    public Bounds(Bounds bounds) {
+        if (bounds == null) {
+            throw new IllegalArgumentException("bounds is null.");
+        }
+
+        x = bounds.x;
+        y = bounds.y;
+        width = bounds.width;
+        height = bounds.height;
+    }
+
+    public Point getLocation() {
+        return new Point(x, y);
+    }
+
+    public Dimensions getSize() {
+        return new Dimensions(width, height);
+    }
+
+    public Bounds union(int x, int y, int width, int height) {
+        int x1 = Math.min(this.x, x);
+        int y1 = Math.min(this.y, y);
+        int x2 = Math.max(this.x + this.width, x + width);
+        int y2 = Math.max(this.y + this.height, y + height);
+
+        return new Bounds(x1, y1, x2 - x1, y2 - y1);
+
+    }
+
+    public Bounds union(Bounds bounds) {
+        return union(bounds.x, bounds.y, bounds.width, bounds.height);
+    }
+
+    public Bounds intersect(int x, int y, int width, int height) {
+        int x1 = Math.max(this.x, x);
+        int y1 = Math.max(this.y, y);
+        int x2 = Math.min(this.x + this.width, x + width);
+        int y2 = Math.min(this.y + this.height, y + height);
+
+        return new Bounds(x1, y1, x2 - x1, y2 - y1);
+    }
+
+    public Bounds intersect(Bounds bounds) {
+        return intersect(bounds.x, bounds.y, bounds.width, bounds.height);
+    }
+
+    public Bounds translate(int dx, int dy) {
+        return new Bounds(x + dx, y + dy, width, height);
+    }
+
+    public Bounds translate(Point offset) {
+        if (offset == null) {
+            throw new IllegalArgumentException("offset is null");
+        }
+
+        return translate(offset.x, offset.y);
+    }
+
+    public boolean contains(Point point) {
+        if (point == null) {
+            throw new IllegalArgumentException("point is null");
+        }
+
+        return contains(point.x, point.y);
+    }
+
+    public boolean contains(int x, int y) {
+        return (x >= this.x
+            && y >= this.y
+            && x < this.x + width
+            && y < this.y + height);
+    }
+
+    public boolean contains(Bounds bounds) {
+        if (bounds == null) {
+            throw new IllegalArgumentException("bounds is null");
+        }
+
+        return contains(bounds.x, bounds.y, bounds.width, bounds.height);
+    }
+
+    public boolean contains(int x, int y, int width, int height) {
+        return (!isEmpty()
+            && x >= this.x
+            && y >= this.y
+            && x + width <= this.x + this.width
+            && y + height <= this.y + this.height);
+    }
+
+    public boolean intersects(Bounds bounds) {
+        if (bounds == null) {
+            throw new IllegalArgumentException("bounds is null");
+        }
+
+        return intersects(bounds.x, bounds.y, bounds.width, bounds.height);
+    }
+
+    public boolean intersects(int x, int y, int width, int height) {
+        return (!isEmpty()
+            && x + width > this.x
+            && y + height > this.y
+            && x < this.x + this.width
+            && y < this.y + this.height);
+    }
+
+    public boolean isEmpty() {
+        return (width <= 0
+            || height <= 0);
+    }
+
+    @Override
+    public boolean equals(Object object) {
+        boolean equals = false;
+
+        if (object instanceof Bounds) {
+            Bounds bounds = (Bounds)object;
+            equals = (x == bounds.x
+                && y == bounds.y
+                && width == bounds.width
+                && height == bounds.height);
+        }
+
+        return equals;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + x;
+        result = prime * result + y;
+        result = prime * result + height;
+        result = prime * result + width;
+
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        return getClass().getName() + " [" + x + "," + y + ";" + width + "x" + height + "]";
+    }
+
+    public static Bounds decode(String value) {
+        if (value == null) {
+            throw new IllegalArgumentException();
+        }
+
+        Map<String, ?> map;
+        try {
+            map = JSONSerializer.parseMap(value);
+        } catch (SerializationException exception) {
+            throw new IllegalArgumentException(exception);
+        }
+
+        int x = BeanAdapter.getInt(map, X_KEY);
+        int y = BeanAdapter.getInt(map, Y_KEY);
+        int width = BeanAdapter.getInt(map, WIDTH_KEY);
+        int height = BeanAdapter.getInt(map, HEIGHT_KEY);
+
+        return new Bounds(x, y, width, height);
+    }
+}

Added: pivot/branches/3.x/scene/src/org/apache/pivot/scene/Color.java
URL: http://svn.apache.org/viewvc/pivot/branches/3.x/scene/src/org/apache/pivot/scene/Color.java?rev=1057053&view=auto
==============================================================================
--- pivot/branches/3.x/scene/src/org/apache/pivot/scene/Color.java (added)
+++ pivot/branches/3.x/scene/src/org/apache/pivot/scene/Color.java Sun Jan  9 23:19:19 2011
@@ -0,0 +1,168 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you 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 org.apache.pivot.scene;
+
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.pivot.beans.BeanAdapter;
+import org.apache.pivot.io.SerializationException;
+import org.apache.pivot.json.JSONSerializer;
+
+/**
+ * Class representing a color.
+ */
+public class Color {
+    public final int red;
+    public final int green;
+    public final int blue;
+    public final int alpha;
+
+    public static final String RED_KEY = "red";
+    public static final String GREEN_KEY = "green";
+    public static final String BLUE_KEY = "blue";
+    public static final String ALPHA_KEY = "alpha";
+
+    public static final Color WHITE = new Color(0xff, 0xff, 0xff);
+    public static final Color SILVER = new Color(0xc0, 0xc0, 0xc0);
+    public static final Color GRAY = new Color(0x80, 0x80, 0x80);
+    public static final Color BLACK = new Color(0x00, 0x00, 0x00);
+    public static final Color RED = new Color(0xff, 0x00, 0x00);
+    public static final Color MAROON = new Color(0x80, 0x00, 0x00);
+    public static final Color YELLOW = new Color(0xff, 0xff, 0x00);
+    public static final Color OLIVE = new Color(0x80, 0x80, 0x00);
+    public static final Color LIME = new Color(0x00, 0xff, 0x00);
+    public static final Color GREEN = new Color(0x00, 0x80, 0x00);
+    public static final Color AQUA = new Color(0x00, 0xff, 0xff);
+    public static final Color TEAL = new Color(0x00, 0x80, 0x80);
+    public static final Color BLUE = new Color(0x00, 0x00, 0xff);
+    public static final Color NAVY = new Color(0x00, 0x00, 0x80);
+    public static final Color FUSCHIA = new Color(0xff, 0x00, 0xff);
+    public static final Color PURPLE = new Color(0x80, 0x00, 0x80);
+
+    public Color(Color color) {
+        this(color.red, color.green, color.blue, color.alpha);
+    }
+
+    public Color(int red, int green, int blue) {
+        this(red, green, blue, 0xff);
+    }
+
+    public Color(int red, int green, int blue, int alpha) {
+        this.red = red;
+        this.green = green;
+        this.blue = blue;
+        this.alpha = alpha;
+    }
+
+    public Color(int color) {
+        alpha = color & 0xff;
+        blue = (color >>= 8) & 0xff;
+        green = (color >>= 8) & 0xff;
+        red = (color >>= 8) & 0xff;
+    }
+
+    @Override
+    public boolean equals(Object object) {
+        boolean equals = false;
+
+        if (object instanceof Color) {
+            Color color = (Color)object;
+            equals = (red == color.red
+                && green == color.green
+                && blue == color.blue
+                && alpha == color.alpha);
+        }
+
+        return equals;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + red;
+        result = prime * result + green;
+        result = prime * result + blue;
+        result = prime * result + alpha;
+
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        return getClass().getName() + " 0x" + toInt();
+    }
+
+    public int toInt() {
+        return (red << 24) | (green << 16) | (blue << 8) | alpha;
+    }
+
+    public static Color decode(String value) {
+        if (value == null) {
+            throw new IllegalArgumentException();
+        }
+
+        value = value.toLowerCase(Locale.ENGLISH);
+
+        Color color;
+        if (value.startsWith("0x")) {
+            value = value.substring(2);
+            if (value.length() != 8) {
+                throw new IllegalArgumentException();
+            }
+
+            color = new Color(Integer.parseInt(value, 16));
+        } else if (value.startsWith("#")) {
+            value = value.substring(1);
+            if (value.length() != 6) {
+                throw new IllegalArgumentException();
+            }
+
+            color = new Color((Integer.parseInt(value, 16) << 8) & 0xff);
+        } else if (value.startsWith("{")) {
+            Map<String, ?> map;
+            try {
+                map = JSONSerializer.parseMap(value);
+            } catch (SerializationException exception) {
+                throw new IllegalArgumentException(exception);
+            }
+
+            int red = BeanAdapter.getInt(map, RED_KEY);
+            int green = BeanAdapter.getInt(map, GREEN_KEY);
+            int blue = BeanAdapter.getInt(map, BLUE_KEY);
+            int alpha = BeanAdapter.getInt(map, ALPHA_KEY);
+
+            color = new Color(red, green, blue, alpha);
+        } else {
+            if (value.length() > 0
+                && Character.isLowerCase(value.charAt(0))) {
+                value = BeanAdapter.toAllCaps(value);
+            }
+
+            try {
+                color = (Color)Color.class.getDeclaredField(value).get(null);
+            } catch (Exception exception) {
+                throw new IllegalArgumentException("\"" + value + "\" is not a valid color constant.");
+            }
+        }
+
+        return color;
+    }
+
+    // TODO Add static methods to darken/brighten, etc.
+}

Added: pivot/branches/3.x/scene/src/org/apache/pivot/scene/Dimensions.java
URL: http://svn.apache.org/viewvc/pivot/branches/3.x/scene/src/org/apache/pivot/scene/Dimensions.java?rev=1057053&view=auto
==============================================================================
--- pivot/branches/3.x/scene/src/org/apache/pivot/scene/Dimensions.java (added)
+++ pivot/branches/3.x/scene/src/org/apache/pivot/scene/Dimensions.java Sun Jan  9 23:19:19 2011
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you 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 org.apache.pivot.scene;
+
+import java.io.Serializable;
+import java.util.Map;
+
+import org.apache.pivot.beans.BeanAdapter;
+import org.apache.pivot.io.SerializationException;
+import org.apache.pivot.json.JSONSerializer;
+
+/**
+ * Class representing the dimensions of an object.
+ */
+public final class Dimensions implements Serializable {
+    private static final long serialVersionUID = 0;
+
+    public final int width;
+    public final int height;
+
+    public static final String WIDTH_KEY = "width";
+    public static final String HEIGHT_KEY = "height";
+
+    public static final Dimensions EMPTY = new Dimensions(0, 0);
+
+    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;
+    }
+
+    @Override
+    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;
+    }
+
+    @Override
+    public int hashCode() {
+        return 31 * width + height;
+    }
+
+    @Override
+    public String toString() {
+        return getClass().getName() + " [" + width + "x" + height + "]";
+    }
+
+    public static Dimensions decode(String value) {
+        if (value == null) {
+            throw new IllegalArgumentException();
+        }
+
+        Map<String, ?> map;
+        try {
+            map = JSONSerializer.parseMap(value);
+        } catch (SerializationException exception) {
+            throw new IllegalArgumentException(exception);
+        }
+
+        int width = BeanAdapter.getInt(map, WIDTH_KEY);
+        int height = BeanAdapter.getInt(map, HEIGHT_KEY);
+
+        return new Dimensions(width, height);
+    }
+}

Added: pivot/branches/3.x/scene/src/org/apache/pivot/scene/Extents.java
URL: http://svn.apache.org/viewvc/pivot/branches/3.x/scene/src/org/apache/pivot/scene/Extents.java?rev=1057053&view=auto
==============================================================================
--- pivot/branches/3.x/scene/src/org/apache/pivot/scene/Extents.java (added)
+++ pivot/branches/3.x/scene/src/org/apache/pivot/scene/Extents.java Sun Jan  9 23:19:19 2011
@@ -0,0 +1,224 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you 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 org.apache.pivot.scene;
+
+import java.util.Map;
+
+import org.apache.pivot.beans.BeanAdapter;
+import org.apache.pivot.io.SerializationException;
+import org.apache.pivot.json.JSONSerializer;
+
+/**
+ * Class representing the extents of an object.
+ */
+public class Extents {
+    public final int minimumX;
+    public final int maximumX;
+    public final int minimumY;
+    public final int maximumY;
+
+    public static final String MINIMUM_X_KEY = "minimumX";
+    public static final String MAXIMUM_X_KEY = "maximumX";
+    public static final String MINIMUM_Y_KEY = "minimumY";
+    public static final String MAXIMUM_Y_KEY = "maximumX";
+
+    public static final Extents EMPTY = new Extents(0, 0, 0, 0);
+
+    public Extents(int minimumX, int maximumX, int minimumY, int maximumY) {
+        this.minimumX = minimumX;
+        this.maximumX = maximumX;
+        this.minimumY = minimumY;
+        this.maximumY = maximumY;
+    }
+
+    public Extents(Limits xLimits, Limits yLimits) {
+        if (xLimits == null) {
+            throw new IllegalArgumentException("xLimits is null.");
+        }
+
+        if (yLimits == null) {
+            throw new IllegalArgumentException("yLimits is null.");
+        }
+
+        this.minimumX = xLimits.minimum;
+        this.maximumX = xLimits.maximum;
+        this.minimumY = yLimits.minimum;
+        this.maximumY = yLimits.maximum;
+    }
+
+    public Extents(Extents extents) {
+        if (extents == null) {
+            throw new IllegalArgumentException("extents is null.");
+        }
+
+        this.minimumX = extents.minimumX;
+        this.maximumX = extents.maximumX;
+        this.minimumY = extents.minimumY;
+        this.maximumY = extents.maximumY;
+    }
+
+    public Limits getXLimits() {
+        return new Limits(minimumX, maximumX);
+    }
+
+    public Limits getYLimits() {
+        return new Limits(minimumY, maximumY);
+    }
+
+    public Extents union(int minimumX, int maximumX, int minimumY, int maximumY) {
+        minimumX = Math.min(this.minimumX, minimumX);
+        maximumX = Math.max(this.maximumX, maximumX);
+        minimumY = Math.min(this.minimumY, minimumY);
+        maximumY = Math.max(this.maximumY, maximumY);
+
+        return new Extents(minimumX, maximumX, minimumY, maximumY);
+
+    }
+
+    public Extents union(Extents extents) {
+        return union(extents.minimumX, extents.maximumX, extents.minimumY, extents.maximumY);
+    }
+
+    public Extents intersect(int minimumX, int maximumX, int minimumY, int maximumY) {
+        minimumX = Math.max(this.minimumX, minimumX);
+        maximumX = Math.min(this.maximumX, maximumX);
+        minimumY = Math.max(this.minimumY, minimumY);
+        maximumY = Math.min(this.maximumY, maximumY);
+
+        return new Extents(minimumX, maximumX, minimumY, maximumY);
+    }
+
+    public Extents intersect(Extents extents) {
+        return intersect(extents.minimumX, extents.maximumX, extents.minimumY, extents.maximumY);
+    }
+
+    public Extents translate(int dx, int dy) {
+        return new Extents(minimumX + dx, maximumX + dx, minimumY + dy, maximumY + dy);
+    }
+
+    public Extents translate(Point offset) {
+        if (offset == null) {
+            throw new IllegalArgumentException("offset is null");
+        }
+
+        return translate(offset.x, offset.y);
+    }
+
+    public boolean contains(Point point) {
+        if (point == null) {
+            throw new IllegalArgumentException("point is null");
+        }
+
+        return contains(point.x, point.y);
+    }
+
+    public boolean contains(int x, int y) {
+        return (x >= this.minimumX
+            && x < this.maximumX
+            && y >= this.minimumY
+            && y < this.maximumY);
+    }
+
+    public boolean contains(Extents extents) {
+        if (extents == null) {
+            throw new IllegalArgumentException("extents is null");
+        }
+
+        return contains(extents.minimumX, extents.maximumX, extents.minimumY, extents.maximumY);
+    }
+
+    public boolean contains(int minimumX, int maximumX, int minimumY, int maximumY) {
+        return (!isEmpty()
+            && minimumX >= this.minimumX
+            && maximumX < this.maximumX
+            && minimumY >= this.maximumX
+            && maximumY < this.maximumY);
+    }
+
+    public boolean intersects(Extents extents) {
+        if (extents == null) {
+            throw new IllegalArgumentException("extents is null");
+        }
+
+        return intersects(extents.minimumX, extents.maximumX, extents.minimumY, extents.maximumY);
+    }
+
+    public boolean intersects(int minimumX, int maximumX, int minimumY, int maximumY) {
+        return (!isEmpty()
+            && maximumX > this.minimumX
+            && minimumX < this.maximumX
+            && maximumY > this.minimumY
+            && minimumY < this.maximumY);
+    }
+
+    public boolean isEmpty() {
+        return (maximumX <= minimumX
+            || maximumY <= minimumY);
+    }
+
+    @Override
+    public boolean equals(Object object) {
+        boolean equals = false;
+
+        if (object instanceof Extents) {
+            Extents extents = (Extents)object;
+            equals = (minimumX == extents.minimumX
+                && maximumX == extents.maximumX
+                && minimumY == extents.minimumY
+                && maximumY == extents.maximumY);
+        }
+
+        return equals;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + minimumX;
+        result = prime * result + maximumX;
+        result = prime * result + minimumY;
+        result = prime * result + maximumY;
+
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        return getClass().getName() + " [" + minimumX + ".." + maximumX  + ";" + minimumY + ".." + maximumY + "]";
+    }
+
+    public static Extents decode(String value) {
+        if (value == null) {
+            throw new IllegalArgumentException();
+        }
+
+        Map<String, ?> map;
+        try {
+            map = JSONSerializer.parseMap(value);
+        } catch (SerializationException exception) {
+            throw new IllegalArgumentException(exception);
+        }
+
+        int minimumX = BeanAdapter.getInt(map, MINIMUM_X_KEY);
+        int maximumX = BeanAdapter.getInt(map, MAXIMUM_X_KEY);
+        int minimumY = BeanAdapter.getInt(map, MINIMUM_Y_KEY);
+        int maximumY = BeanAdapter.getInt(map, MINIMUM_Y_KEY);
+
+        return new Extents(minimumX, maximumX, minimumY, maximumY);
+    }
+}

Added: pivot/branches/3.x/scene/src/org/apache/pivot/scene/FocusTraversalDirection.java
URL: http://svn.apache.org/viewvc/pivot/branches/3.x/scene/src/org/apache/pivot/scene/FocusTraversalDirection.java?rev=1057053&view=auto
==============================================================================
--- pivot/branches/3.x/scene/src/org/apache/pivot/scene/FocusTraversalDirection.java (added)
+++ pivot/branches/3.x/scene/src/org/apache/pivot/scene/FocusTraversalDirection.java Sun Jan  9 23:19:19 2011
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you 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 org.apache.pivot.scene;
+
+/**
+ * Enumeration representing a focus traversal direction.
+ */
+public enum FocusTraversalDirection {
+    FORWARD,
+    BACKWARD
+}

Added: pivot/branches/3.x/scene/src/org/apache/pivot/scene/FocusTraversalPolicy.java
URL: http://svn.apache.org/viewvc/pivot/branches/3.x/scene/src/org/apache/pivot/scene/FocusTraversalPolicy.java?rev=1057053&view=auto
==============================================================================
--- pivot/branches/3.x/scene/src/org/apache/pivot/scene/FocusTraversalPolicy.java (added)
+++ pivot/branches/3.x/scene/src/org/apache/pivot/scene/FocusTraversalPolicy.java Sun Jan  9 23:19:19 2011
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you 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 org.apache.pivot.scene;
+
+/**
+ * Defines the order in which nodes will receive focus during focus
+ * traversal.
+ */
+public interface FocusTraversalPolicy {
+    /**
+     * Returns the next focus destination according to this traversal policy.
+     *
+     * @param group
+     * The group to which the traversal policy applies.
+     *
+     * @param node
+     * The node from which focus is being transferred. If <tt>null</tt>,
+     * implementations should return the first node for a forward
+     * traversal and the last node for a backward traversal.
+     *
+     * @param direction
+     * The direction in which to transfer focus.
+     *
+     * @return
+     * The node to focus, or <tt>null</tt> if there are no more nodes
+     * in the given direction or next node cannot be determined.
+     */
+    Node getNextNode(Group group, Node node, FocusTraversalDirection direction);
+}