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

svn commit: r754926 [23/38] - in /incubator/pivot/tags/v1.0: ./ charts-test/ charts-test/src/ charts-test/src/pivot/ charts-test/src/pivot/charts/ charts-test/src/pivot/charts/test/ charts/ charts/lib/ charts/src/ charts/src/pivot/ charts/src/pivot/cha...

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/MenuItemData.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/MenuItemData.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/MenuItemData.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/MenuItemData.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,98 @@
+/*
+ * 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.content;
+
+import pivot.wtk.Keyboard;
+import pivot.wtk.media.Image;
+
+/**
+ * Default menu item data implementation.
+ *
+ * @author gbrown
+ */
+public class MenuItemData extends ButtonData {
+    private Keyboard.KeyStroke keyboardShortcut = null;
+
+    /**
+     * Constructor.
+     */
+    public MenuItemData() {
+        this(null, null, null);
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param icon
+     * The icon to display in the menu item.
+     */
+    public MenuItemData(Image icon) {
+        this(icon, null, null);
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param text
+     * The text to display in the menu item.
+     */
+    public MenuItemData(String text) {
+        this(null, text, null);
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param icon
+     * The icon to display in the menu item.
+     *
+     * @param text
+     * The text to display in the menu item.
+     */
+    public MenuItemData(Image icon, String text) {
+        this(icon, text, null);
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param icon
+     * The icon to display in the menu item.
+     *
+     * @param text
+     * The text to display in the menu item.
+     *
+     * @param keyboardShortcut
+     * The keyboard shortcut associated with this menu item.
+     */
+    public MenuItemData(Image icon, String text, Keyboard.KeyStroke keyboardShortcut) {
+        super(icon, text);
+
+        this.keyboardShortcut = keyboardShortcut;
+    }
+
+    public Keyboard.KeyStroke getKeyboardShortcut() {
+        return keyboardShortcut;
+    }
+
+    public void setKeyboardShortcut(Keyboard.KeyStroke keyboardShortcut) {
+        this.keyboardShortcut = keyboardShortcut;
+    }
+
+    public void setKeyboardShortcut(String keyboardShortcut) {
+        setKeyboardShortcut(Keyboard.KeyStroke.decode(keyboardShortcut));
+    }
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/MenuItemDataRenderer.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/MenuItemDataRenderer.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/MenuItemDataRenderer.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/MenuItemDataRenderer.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,143 @@
+/*
+ * 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.content;
+
+import java.awt.Color;
+import java.awt.Font;
+
+import pivot.wtk.Button;
+import pivot.wtk.FlowPane;
+import pivot.wtk.HorizontalAlignment;
+import pivot.wtk.ImageView;
+import pivot.wtk.Insets;
+import pivot.wtk.Keyboard;
+import pivot.wtk.Label;
+import pivot.wtk.Menu;
+import pivot.wtk.VerticalAlignment;
+import pivot.wtk.media.Image;
+
+/**
+ * Default menu item data renderer.
+ *
+ * @author gbrown
+ */
+public class MenuItemDataRenderer extends FlowPane implements Button.DataRenderer {
+    protected ImageView imageView = new ImageView();
+    protected Label textLabel = new Label();
+    protected Label keyboardShortcutLabel = new Label();
+
+    public MenuItemDataRenderer() {
+        getStyles().put("verticalAlignment", VerticalAlignment.CENTER);
+        getStyles().put("padding", new Insets(2));
+
+        add(imageView);
+        add(textLabel);
+        add(keyboardShortcutLabel);
+
+        imageView.getStyles().put("backgroundColor", null);
+
+        keyboardShortcutLabel.getStyles().put("horizontalAlignment",
+            HorizontalAlignment.RIGHT);
+    }
+
+    public void setSize(int width, int height) {
+        super.setSize(width, height);
+
+        // Since this component doesn't have a parent, it won't be validated
+        // via layout; ensure that it is valid here
+        validate();
+    }
+
+    @SuppressWarnings("unchecked")
+    public void render(Object data, Button button, boolean highlighted) {
+        Image icon = null;
+        String text = null;
+        Keyboard.KeyStroke keyboardShortcut = null;
+
+        if (data instanceof ButtonData) {
+            ButtonData buttonData = (ButtonData)data;
+            icon = buttonData.getIcon();
+            text = buttonData.getText();
+
+            if (buttonData instanceof MenuItemData) {
+                MenuItemData menuItemData = (MenuItemData)buttonData;
+                keyboardShortcut = menuItemData.getKeyboardShortcut();
+            }
+        } else if (data instanceof Image) {
+            icon = (Image)data;
+        } else {
+            if (data != null) {
+                text = data.toString();
+            }
+        }
+
+        // If the button is selected, icon is a checkmark; otherwise,
+        // attempt to retrieve icon from button data
+        if (button.isSelected()) {
+            icon = (Image)button.getStyles().get("checkmarkImage");
+        }
+
+        // Update the image view
+        Menu.Item menuItem = (Menu.Item)button;
+        Menu menu = menuItem.getSection().getMenu();
+
+        int margin = (Integer)menu.getStyles().get("margin");
+        Insets padding = (Insets)getStyles().get("padding");
+
+        imageView.setImage(icon);
+        imageView.setPreferredWidth(margin - padding.left * 2);
+        imageView.getStyles().put("opacity", button.isEnabled() ? 1.0f : 0.5f);
+
+        // Update the labels
+        Object font = menu.getStyles().get("font");
+        if (font instanceof Font) {
+            textLabel.getStyles().put("font", font);
+            keyboardShortcutLabel.getStyles().put("font",
+                ((Font)font).deriveFont(Font.ITALIC));
+        }
+
+        Object color;
+        if (button.isEnabled()) {
+            if (highlighted) {
+                color = menu.getStyles().get("highlightColor");
+            } else {
+                color = menu.getStyles().get("color");
+            }
+        } else {
+            color = menu.getStyles().get("disabledColor");
+        }
+
+        if (color instanceof Color) {
+            textLabel.getStyles().put("color", color);
+            keyboardShortcutLabel.getStyles().put("color", color);
+        }
+
+        textLabel.setText(text);
+
+        boolean showKeyboardShortcuts = false;
+        if (menu.getStyles().containsKey("showKeyboardShortcuts")) {
+            showKeyboardShortcuts = (Boolean)menu.getStyles().get("showKeyboardShortcuts");
+        }
+
+        if (showKeyboardShortcuts) {
+            keyboardShortcutLabel.setDisplayable(true);
+            keyboardShortcutLabel.setText(keyboardShortcut == null ?
+                null : keyboardShortcut.toString());
+        } else {
+            keyboardShortcutLabel.setDisplayable(false);
+        }
+    }
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/NumericSpinnerData.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/NumericSpinnerData.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/NumericSpinnerData.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/NumericSpinnerData.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,222 @@
+/*
+ * 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.content;
+
+import java.util.Comparator;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+import pivot.collections.List;
+import pivot.collections.ListListener;
+import pivot.collections.Sequence;
+import pivot.util.ListenerList;
+
+/**
+ * Spinner data model that presents a bounded list of integers. This is a
+ * lightweight class that spoofs the actual list data (no data is stored in
+ * the list).
+ * <p>
+ * The iterator returned by this class's <tt>iterator</tt> method is
+ * <i>fail-fast</i>: if the data is structurally modified at any time after
+ * the iterator is created, in any way except through the iterator's own
+ * remove or add methods, the iterator will throw a
+ * <tt>ConcurrentModificationException</tt>. Thus, in the face of concurrent
+ * modification, the iterator fails quickly and cleanly, rather than risking
+ * arbitrary, non-deterministic behavior at an undetermined time in the
+ * future.
+ * <p>
+ * Note that the fail-fast behavior of an iterator cannot be guaranteed
+ * as it is, generally speaking, impossible to make any hard guarantees in the
+ * presence of unsynchronized concurrent modification.  Fail-fast iterators
+ * throw <tt>ConcurrentModificationException</tt> on a best-effort basis.
+ * Therefore, it would be wrong to write a program that depended on this
+ * exception for its correctness: <i>the fail-fast behavior of iterators
+ * should be used only to detect bugs.</i>
+ *
+ * @author tvolkert
+ */
+public class NumericSpinnerData implements List<Integer> {
+    private class DataIterator implements Iterator<Integer> {
+        // Parity members to support ConcurrentModificationException check
+        private int lowerBound = NumericSpinnerData.this.lowerBound;
+        private int upperBound = NumericSpinnerData.this.upperBound;
+        private int increment = NumericSpinnerData.this.increment;
+
+        private int value = lowerBound;
+
+        public boolean hasNext() {
+            return (value <= upperBound);
+        }
+
+        public Integer next() {
+            if (lowerBound != NumericSpinnerData.this.lowerBound
+                || upperBound != NumericSpinnerData.this.upperBound
+                || increment != NumericSpinnerData.this.increment) {
+                throw new ConcurrentModificationException();
+            }
+
+            if (value > upperBound) {
+                throw new NoSuchElementException();
+            }
+
+            int next = value;
+            value += increment;
+            return next;
+        }
+
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    private int lowerBound;
+    private int upperBound;
+    private int increment;
+
+    private ListListenerList<Integer> listListeners = new ListListenerList<Integer>();
+
+    /**
+     * Creates a new <tt>NumericSpinnerData</tt> instance bounded from
+     * <tt>Short.MIN_VALUE</tt> to <tt>Short.MAX_VALUE</tt> and an increment
+     * of one.
+     */
+    public NumericSpinnerData() {
+        this(Short.MIN_VALUE, Short.MAX_VALUE, 1);
+    }
+
+    /**
+     * Creates a new <tt>NumericSpinnerData</tt> with the specified bounded
+     * range and an increment of one.
+     */
+    public NumericSpinnerData(int lowerBound, int upperBound) {
+        this(lowerBound, upperBound, 1);
+    }
+
+    /**
+     * Creates a new <tt>NumericSpinnerData</tt> with the specified bounded
+     * range and increment.
+     */
+    public NumericSpinnerData(int lowerBound, int upperBound, int increment) {
+        if (lowerBound >= upperBound) {
+            throw new IllegalArgumentException("Lower bound must be less than upper bound.");
+        }
+
+        long length = ((upperBound - lowerBound) / increment) + 1;
+
+        if (length > Integer.MAX_VALUE) {
+            throw new IllegalArgumentException("Bounded range is too large.");
+        }
+
+        this.lowerBound = lowerBound;
+        this.upperBound = upperBound;
+        this.increment = increment;
+    }
+
+    public int getLowerBound() {
+        return lowerBound;
+    }
+
+    public void setLowerBound(int lowerBound) {
+        this.lowerBound = lowerBound;
+        // TODO Notify listListeners of change
+    }
+
+    public int getUpperBound() {
+        return upperBound;
+    }
+
+    public void setUpperBound(int upperBound) {
+        this.upperBound = upperBound;
+        // TODO Notify listListeners of change
+    }
+
+    public int getIncrement() {
+        return increment;
+    }
+
+    public void setIncrement(int increment) {
+        this.increment = increment;
+        // TODO Notify listListeners of change
+    }
+
+    public int add(Integer item) {
+        throw new UnsupportedOperationException();
+    }
+
+    public void insert(Integer item, int index) {
+        throw new UnsupportedOperationException();
+    }
+
+    public Integer update(int index, Integer item) {
+        throw new UnsupportedOperationException();
+    }
+
+    public int remove(Integer item) {
+        throw new UnsupportedOperationException();
+    }
+
+    public Sequence<Integer> remove(int index, int count) {
+        throw new UnsupportedOperationException();
+    }
+
+    public Integer get(int index) {
+        if (index < 0 || index >= getLength()) {
+            throw new IndexOutOfBoundsException("Invalid index: " + index);
+        }
+
+        return lowerBound + (index * increment);
+    }
+
+    public int indexOf(Integer item) {
+        int index = -1;
+
+        if (item >= lowerBound && item <= upperBound) {
+            int distance = item - lowerBound;
+
+            // Ensure that our increment lands us on the item
+            if (distance % increment == 0) {
+                index = distance / increment;
+            }
+        }
+
+        return index;
+    }
+
+    public void clear() {
+        throw new UnsupportedOperationException();
+    }
+
+    public int getLength() {
+        return ((upperBound - lowerBound) / increment) + 1;
+    }
+
+    public Comparator<Integer> getComparator() {
+        return null;
+    }
+
+    public void setComparator(Comparator<Integer> comparator) {
+        throw new UnsupportedOperationException();
+    }
+
+    public Iterator<Integer> iterator() {
+        return new DataIterator();
+    }
+
+    public ListenerList<ListListener<Integer>> getListListeners() {
+        return listListeners;
+    }
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/SpinnerItemRenderer.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/SpinnerItemRenderer.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/SpinnerItemRenderer.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/SpinnerItemRenderer.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,67 @@
+/*
+ * 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.content;
+
+import java.awt.Color;
+import java.awt.Font;
+
+import pivot.wtk.Component;
+import pivot.wtk.Insets;
+import pivot.wtk.Label;
+import pivot.wtk.Spinner;
+import pivot.wtk.VerticalAlignment;
+
+/**
+ * Default spinner item renderer, which renders all items as strings by
+ * calling <tt>toString()</tt> on them.
+ *
+ * @author tvolkert
+ */
+public class SpinnerItemRenderer extends Label implements Spinner.ItemRenderer {
+    public SpinnerItemRenderer() {
+        getStyles().put("verticalAlignment", VerticalAlignment.CENTER);
+        getStyles().put("padding", new Insets(2));
+    }
+
+    public void render(Object item, Spinner spinner) {
+        setText(item == null ? null : item.toString());
+
+        renderStyles(spinner);
+    }
+
+    protected void renderStyles(Spinner spinner) {
+        Component.StyleDictionary spinnerStyles = spinner.getStyles();
+        Component.StyleDictionary styles = getStyles();
+
+        Object font = spinnerStyles.get("font");
+
+        if (font instanceof Font) {
+            styles.put("font", font);
+        }
+
+        Object color = null;
+
+        if (spinner.isEnabled()) {
+            color = spinnerStyles.get("color");
+        } else {
+            color = spinnerStyles.get("disabledColor");
+        }
+
+        if (color instanceof Color) {
+            styles.put("color", color);
+        }
+    }
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TableRow.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TableRow.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TableRow.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TableRow.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk.content;
+
+import pivot.collections.Dictionary;
+import pivot.collections.HashMap;
+
+/**
+ * Default table row implementation.
+ *
+ * @author gbrown
+ */
+public class TableRow implements Dictionary<String, Object> {
+    private HashMap<String, Object> cells = new HashMap<String, Object>();
+
+    public Object get(String key) {
+        return cells.get(key);
+    }
+
+    public Object put(String key, Object value) {
+        return cells.put(key, value);
+    }
+
+    public Object remove(String key) {
+        return cells.remove(key);
+    }
+
+    public boolean containsKey(String key) {
+        return cells.containsKey(key);
+    }
+
+    public boolean isEmpty() {
+        return cells.isEmpty();
+    }
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TableViewBooleanCellRenderer.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TableViewBooleanCellRenderer.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TableViewBooleanCellRenderer.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TableViewBooleanCellRenderer.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,76 @@
+/*
+ * 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.content;
+
+import pivot.collections.Dictionary;
+import pivot.wtk.Checkbox;
+import pivot.wtk.FlowPane;
+import pivot.wtk.HorizontalAlignment;
+import pivot.wtk.TableView;
+import pivot.wtk.VerticalAlignment;
+
+/**
+ * Default renderer for table view cells that contain boolean data. Renders
+ * cell contents as a checkbox.
+ *
+ * @author gbrown
+ */
+public class TableViewBooleanCellRenderer extends FlowPane
+    implements TableView.CellRenderer {
+    private Checkbox checkbox = new Checkbox();
+
+    public TableViewBooleanCellRenderer() {
+        super();
+
+        add(checkbox);
+
+        getStyles().put("verticalAlignment", VerticalAlignment.CENTER);
+        getStyles().put("horizontalAlignment", HorizontalAlignment.CENTER);
+    }
+
+    @Override
+    public void setSize(int width, int height) {
+        super.setSize(width, height);
+
+        // Since this component doesn't have a parent, it won't be validated
+        // via layout; ensure that it is valid here
+        validate();
+    }
+
+    @SuppressWarnings("unchecked")
+    public void render(Object value, TableView tableView, TableView.Column column,
+        boolean rowSelected, boolean rowHighlighted, boolean rowDisabled) {
+        boolean checkboxSelected = false;
+
+        // Get the row and cell data
+        String columnName = column.getName();
+        if (columnName != null) {
+            Dictionary<String, Object> rowData = (Dictionary<String, Object>)value;
+            Object cellData = rowData.get(columnName);
+
+            if (cellData instanceof String) {
+                cellData = Boolean.parseBoolean((String)cellData);
+            }
+
+            if (cellData instanceof Boolean) {
+                checkboxSelected = (Boolean)cellData;
+            }
+        }
+
+        checkbox.setSelected(checkboxSelected);
+        checkbox.setEnabled(tableView.isEnabled() && !rowDisabled);
+    }
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TableViewCellRenderer.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TableViewCellRenderer.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TableViewCellRenderer.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TableViewCellRenderer.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,87 @@
+/*
+ * 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.content;
+
+import java.awt.Color;
+import java.awt.Font;
+
+import pivot.collections.Dictionary;
+import pivot.wtk.Component;
+import pivot.wtk.Insets;
+import pivot.wtk.Label;
+import pivot.wtk.TableView;
+import pivot.wtk.VerticalAlignment;
+
+/**
+ * Default table cell renderer. Renders cell contents as a string.
+ *
+ * @author gbrown
+ */
+public class TableViewCellRenderer extends Label
+    implements TableView.CellRenderer {
+    public TableViewCellRenderer() {
+        getStyles().put("verticalAlignment", VerticalAlignment.CENTER);
+        getStyles().put("padding", new Insets(2));
+    }
+
+    @SuppressWarnings("unchecked")
+    public void render(Object value, TableView tableView, TableView.Column column,
+        boolean rowSelected, boolean rowHighlighted, boolean rowDisabled) {
+        Object cellData = null;
+
+        // Get the row and cell data
+        String columnName = column.getName();
+        if (columnName != null) {
+            Dictionary<String, Object> rowData = (Dictionary<String, Object>)value;
+            cellData = rowData.get(columnName);
+        }
+
+        setText(cellData == null ? null : cellData.toString());
+
+        renderStyles(tableView, rowSelected, rowDisabled);
+    }
+
+    protected void renderStyles(TableView tableView, boolean rowSelected, boolean rowDisabled) {
+        Component.StyleDictionary tableViewStyles = tableView.getStyles();
+        Component.StyleDictionary styles = getStyles();
+
+        Object font = tableViewStyles.get("font");
+
+        if (font instanceof Font) {
+            styles.put("font", font);
+        }
+
+        Object color = null;
+
+        if (tableView.isEnabled() && !rowDisabled) {
+            if (rowSelected) {
+                if (tableView.isFocused()) {
+                    color = tableViewStyles.get("selectionColor");
+                } else {
+                    color = tableViewStyles.get("inactiveSelectionColor");
+                }
+            } else {
+                color = tableViewStyles.get("color");
+            }
+        } else {
+            color = tableViewStyles.get("disabledColor");
+        }
+
+        if (color instanceof Color) {
+            styles.put("color", color);
+        }
+    }
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TableViewDateCellRenderer.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TableViewDateCellRenderer.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TableViewDateCellRenderer.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TableViewDateCellRenderer.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk.content;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import pivot.collections.Dictionary;
+import pivot.wtk.TableView;
+
+/**
+ * Default renderer for table view cells that contain date data. Renders
+ * cell contents as a formatted date.
+ *
+ * @author gbrown
+ */
+public class TableViewDateCellRenderer extends TableViewCellRenderer {
+    private DateFormat dateFormat = DEFAULT_DATE_FORMAT;
+
+    public static final DateFormat DEFAULT_DATE_FORMAT = DateFormat.getDateInstance();
+
+    public DateFormat getDateFormat() {
+        return dateFormat;
+    }
+
+    public void setDateFormat(DateFormat dateFormat) {
+        if (dateFormat == null) {
+            throw new IllegalArgumentException("dateFormat is null.");
+        }
+
+        this.dateFormat = dateFormat;
+    }
+
+    public void setDateFormat(String dateFormat) {
+        setDateFormat(new SimpleDateFormat(dateFormat));
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public void render(Object value, TableView tableView, TableView.Column column,
+        boolean rowSelected, boolean rowHighlighted, boolean rowDisabled) {
+        String formattedDate = null;
+
+        // Get the row and cell data
+        String columnName = column.getName();
+        if (columnName != null) {
+            Dictionary<String, Object> rowData = (Dictionary<String, Object>)value;
+            Object cellData = rowData.get(columnName);
+
+            if (cellData instanceof Date) {
+                formattedDate = dateFormat.format((Date)cellData);
+            }
+        }
+
+        setText(formattedDate);
+
+        renderStyles(tableView, rowSelected, rowDisabled);
+    }
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TableViewHeaderData.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TableViewHeaderData.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TableViewHeaderData.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TableViewHeaderData.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,80 @@
+/*
+ * 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.content;
+
+import java.net.URL;
+
+import pivot.wtk.ApplicationContext;
+import pivot.wtk.media.Image;
+
+/**
+ * Default table header data implementation.
+ *
+ * @author gbrown
+ */
+public class TableViewHeaderData {
+    private Image icon = null;
+    private String text = null;
+
+    public TableViewHeaderData() {
+        this(null, null);
+    }
+
+    public TableViewHeaderData(Image icon) {
+        this(icon, null);
+    }
+
+    public TableViewHeaderData(String text) {
+        this(null, text);
+    }
+
+    public TableViewHeaderData(Image icon, String text) {
+        this.icon = icon;
+        this.text = text;
+    }
+
+    public Image getIcon() {
+        return icon;
+    }
+
+    public void setIcon(Image icon) {
+        this.icon = icon;
+    }
+
+    public void setIcon(URL iconURL) {
+        Image icon = (Image)ApplicationContext.getResourceCache().get(iconURL);
+
+        if (icon == null) {
+            icon = Image.load(iconURL);
+            ApplicationContext.getResourceCache().put(iconURL, icon);
+        }
+
+        setIcon(icon);
+    }
+
+    public void setIcon(String iconName) {
+        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+        setIcon(classLoader.getResource(iconName));
+    }
+
+    public String getText() {
+        return text;
+    }
+
+    public void setText(String text) {
+        this.text = text;
+    }
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TableViewHeaderDataRenderer.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TableViewHeaderDataRenderer.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TableViewHeaderDataRenderer.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TableViewHeaderDataRenderer.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,117 @@
+/*
+ * 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.content;
+
+import java.awt.Color;
+import java.awt.Font;
+
+import pivot.wtk.Component;
+import pivot.wtk.FlowPane;
+import pivot.wtk.HorizontalAlignment;
+import pivot.wtk.ImageView;
+import pivot.wtk.Insets;
+import pivot.wtk.Label;
+import pivot.wtk.TableViewHeader;
+import pivot.wtk.VerticalAlignment;
+import pivot.wtk.media.Image;
+
+/**
+ * Default table view header data renderer.
+ *
+ * @author gbrown
+ */
+public class TableViewHeaderDataRenderer extends FlowPane
+    implements TableViewHeader.DataRenderer {
+    protected ImageView imageView = new ImageView();
+    protected Label label = new Label();
+
+    public TableViewHeaderDataRenderer() {
+        getStyles().put("horizontalAlignment", HorizontalAlignment.LEFT);
+        getStyles().put("verticalAlignment", VerticalAlignment.CENTER);
+        getStyles().put("padding", new Insets(1, 2, 1, 2));
+
+        add(imageView);
+        add(label);
+    }
+
+    @Override
+    public void setSize(int width, int height) {
+        super.setSize(width, height);
+
+        // Since this component doesn't have a parent, it won't be validated
+        // via layout; ensure that it is valid here
+        validate();
+    }
+
+    public void render(Object data, TableViewHeader tableViewHeader, boolean highlighted) {
+        Image icon = null;
+        String text = null;
+
+        if (data instanceof TableViewHeaderData) {
+            TableViewHeaderData tableViewHeaderData = (TableViewHeaderData)data;
+            icon = tableViewHeaderData.getIcon();
+            text = tableViewHeaderData.getText();
+        } else if (data instanceof Image) {
+            icon = (Image)data;
+        } else {
+            if (data != null) {
+                text = data.toString();
+            }
+        }
+
+        // Left-align the content
+        getStyles().put("horizontalAlignment", (text == null) ?
+            HorizontalAlignment.CENTER : HorizontalAlignment.LEFT);
+
+        // Update the icon image view
+        imageView.setImage(icon);
+
+        if (icon == null) {
+            imageView.setDisplayable(false);
+        } else {
+            imageView.setDisplayable(true);
+            imageView.getStyles().put("opacity", tableViewHeader.isEnabled() ? 1.0f : 0.5f);
+        }
+
+        // Show/hide the label
+        label.setText(text);
+
+        if (text == null) {
+            label.setDisplayable(false);
+        } else {
+            label.setDisplayable(true);
+
+            // Update the label styles
+            Component.StyleDictionary labelStyles = label.getStyles();
+
+            Object labelFont = tableViewHeader.getStyles().get("font");
+            if (labelFont instanceof Font) {
+                labelStyles.put("font", labelFont);
+            }
+
+            Object color = null;
+            if (tableViewHeader.isEnabled()) {
+                color = tableViewHeader.getStyles().get("color");
+            } else {
+                color = tableViewHeader.getStyles().get("disabledColor");
+            }
+
+            if (color instanceof Color) {
+                labelStyles.put("color", color);
+            }
+        }
+    }
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TableViewImageCellRenderer.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TableViewImageCellRenderer.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TableViewImageCellRenderer.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TableViewImageCellRenderer.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,74 @@
+/*
+ * 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.content;
+
+import pivot.collections.Dictionary;
+import pivot.wtk.ImageView;
+import pivot.wtk.TableView;
+import pivot.wtk.TableView.CellRenderer;
+import pivot.wtk.media.Image;
+
+/**
+ * Default renderer for table view cells that contain image data.
+ *
+ * @author gbrown
+ */
+public class TableViewImageCellRenderer extends ImageView implements CellRenderer {
+    public static int DEFAULT_HEIGHT = 16;
+
+    public TableViewImageCellRenderer() {
+        super();
+
+        setPreferredHeight(DEFAULT_HEIGHT);
+    }
+
+    @Override
+    public void setPreferredHeight(int preferredHeight) {
+        if (preferredHeight == -1) {
+            throw new IllegalArgumentException("Preferred height must be a fixed value.");
+        }
+
+        super.setPreferredHeight(preferredHeight);
+    }
+
+    @Override
+    public void setPreferredSize(int preferredWidth, int preferredHeight) {
+        if (preferredHeight == -1) {
+            throw new IllegalArgumentException("Preferred height must be a fixed value.");
+        }
+
+        super.setPreferredSize(preferredWidth, preferredHeight);
+    }
+
+    @SuppressWarnings("unchecked")
+    public void render(Object value, TableView tableView, TableView.Column column,
+        boolean rowSelected, boolean rowHighlighted, boolean rowDisabled) {
+        Image image = null;
+
+        // Get the row and cell data
+        String columnName = column.getName();
+        if (columnName != null) {
+            Dictionary<String, Object> rowData = (Dictionary<String, Object>)value;
+            Object cellData = rowData.get(columnName);
+
+            if (cellData instanceof Image) {
+                image = (Image)cellData;
+            }
+        }
+
+        setImage(image);
+    }
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TableViewMultiCellRenderer.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TableViewMultiCellRenderer.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TableViewMultiCellRenderer.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TableViewMultiCellRenderer.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,338 @@
+/*
+ * 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.content;
+
+import java.awt.Graphics2D;
+
+import pivot.collections.ArrayList;
+import pivot.collections.Dictionary;
+import pivot.collections.HashMap;
+import pivot.collections.Sequence;
+import pivot.wtk.Dimensions;
+import pivot.wtk.TableView;
+import pivot.wtk.content.TableViewCellRenderer;
+
+/**
+ * Table cell renderer that supports dynamic rendering based on the type of
+ * content being rendered.
+ *
+ * @author tvolkert
+ */
+public class TableViewMultiCellRenderer implements TableView.CellRenderer {
+    /**
+     * Internal style dictionary that supports no styles.
+     *
+     * @author tvolkert
+     */
+    private static class StyleDictionary implements Dictionary<String, Object> {
+        public Object get(String key) {
+            return null;
+        }
+
+        public Object put(String key, Object value) {
+            throw new UnsupportedOperationException();
+        }
+
+        public Object remove(String key) {
+            throw new UnsupportedOperationException();
+        }
+
+        public boolean containsKey(String key) {
+            return false;
+        }
+
+        public boolean isEmpty() {
+            return true;
+        }
+    }
+
+    /**
+     * Maps the type of value being rendered (the value class) to a specific
+     * cell renderer.
+     *
+     * @author tvolkert
+     */
+    public static final class RendererMapping {
+        private Class<?> valueClass = null;
+        private TableView.CellRenderer cellRenderer = null;
+
+        private TableViewMultiCellRenderer multiCellRenderer = null;
+
+        public Class<?> getValueClass() {
+            return valueClass;
+        }
+
+        public void setValueClass(Class<?> valueClass) {
+            if (valueClass == null) {
+                throw new IllegalArgumentException("valueClass is null.");
+            }
+
+            Class<?> previousValueClass = this.valueClass;
+
+            if (valueClass != previousValueClass) {
+                this.valueClass = valueClass;
+
+                if (multiCellRenderer != null) {
+                    multiCellRenderer.cellRenderers.remove(previousValueClass);
+                    multiCellRenderer.cellRenderers.put(valueClass, cellRenderer);
+                }
+            }
+        }
+
+        public void setValueClass(String valueClass) {
+            if (valueClass == null) {
+                throw new IllegalArgumentException("valueClass is null.");
+            }
+
+            try {
+                setValueClass(Class.forName(valueClass));
+            } catch (ClassNotFoundException ex) {
+                throw new RuntimeException(ex);
+            }
+        }
+
+        public TableView.CellRenderer getCellRenderer() {
+            return cellRenderer;
+        }
+
+        public void setCellRenderer(TableView.CellRenderer cellRenderer) {
+            if (cellRenderer == null) {
+                throw new IllegalArgumentException("cellRenderer is null.");
+            }
+
+            TableView.CellRenderer previousCellRenderer = this.cellRenderer;
+
+            if (cellRenderer != previousCellRenderer) {
+                this.cellRenderer = cellRenderer;
+
+                if (multiCellRenderer != null) {
+                    multiCellRenderer.cellRenderers.put(valueClass, cellRenderer);
+                }
+            }
+        }
+
+        private void setMultiCellRenderer(TableViewMultiCellRenderer multiCellRenderer) {
+            this.multiCellRenderer = multiCellRenderer;
+        }
+    }
+
+    /**
+     * Provides a sequence hook into this renderer's mappings, thus enabling
+     * developers to define their multi-cell renderer in WTKX.
+     *
+     * @author tvolkert
+     */
+    private class RendererMappingSequence implements Sequence<RendererMapping> {
+        private ArrayList<RendererMapping> mappings = new ArrayList<RendererMapping>();
+
+        public int add(RendererMapping item) {
+            int index = mappings.getLength();
+            insert(item, index);
+            return index;
+        }
+
+        public void insert(RendererMapping item, int index) {
+            if (item == null) {
+                throw new IllegalArgumentException("item is null.");
+            }
+
+            Class<?> valueClass = item.getValueClass();
+
+            if (cellRenderers.containsKey(valueClass)) {
+                throw new IllegalArgumentException("Duplicate value class mapping: " +
+                    (valueClass == null ? "null" : valueClass.getName()));
+            }
+
+            mappings.insert(item, index);
+
+            TableView.CellRenderer cellRenderer = item.getCellRenderer();
+            cellRenderers.put(valueClass, cellRenderer);
+
+            item.setMultiCellRenderer(TableViewMultiCellRenderer.this);
+        }
+
+        public RendererMapping update(int index, RendererMapping item) {
+            if (item == null) {
+                throw new IllegalArgumentException("item is null.");
+            }
+
+            if (index >= getLength()) {
+                throw new IndexOutOfBoundsException();
+            }
+
+            RendererMapping previousItem = mappings.get(index);
+
+            if (item != previousItem) {
+                Class<?> valueClass = item.getValueClass();
+                Class<?> previousValueClass = previousItem.getValueClass();
+
+                if (cellRenderers.containsKey(valueClass)
+                    && valueClass != previousValueClass) {
+                    throw new IllegalArgumentException("Duplicate value class mapping: " +
+                        valueClass.getName());
+                }
+
+                mappings.update(index, item);
+
+                TableView.CellRenderer cellRenderer = item.getCellRenderer();
+                cellRenderers.remove(previousValueClass);
+                cellRenderers.put(valueClass, cellRenderer);
+
+                previousItem.setMultiCellRenderer(null);
+                item.setMultiCellRenderer(TableViewMultiCellRenderer.this);
+            }
+
+            return previousItem;
+        }
+
+        public int remove(RendererMapping item) {
+            int index = mappings.indexOf(item);
+
+            if (index >= 0) {
+                remove(index, 1);
+            }
+
+            return index;
+        }
+
+        public Sequence<RendererMapping> remove(int index, int count) {
+            Sequence<RendererMapping> removed = mappings.remove(index, count);
+
+            for (int i = 0, n = removed.getLength(); i < n; i++) {
+                RendererMapping item = removed.get(i);
+                Class<?> valueClass = item.getValueClass();
+
+                cellRenderers.remove(valueClass);
+                item.setMultiCellRenderer(null);
+            }
+
+            return removed;
+        }
+
+        public RendererMapping get(int index) {
+            return mappings.get(index);
+        }
+
+        public int indexOf(RendererMapping item) {
+            return mappings.indexOf(item);
+        }
+
+        public int getLength() {
+            return mappings.getLength();
+        }
+    }
+
+    private int width;
+    private int height;
+
+    private HashMap<Class<?>, TableView.CellRenderer> cellRenderers =
+        new HashMap<Class<?>, TableView.CellRenderer>();
+
+    private TableView.CellRenderer defaultRenderer = new TableViewCellRenderer();
+    private TableView.CellRenderer currentRenderer = defaultRenderer;
+
+    private RendererMappingSequence rendererMappings = new RendererMappingSequence();
+
+    private static final StyleDictionary STYLES = new StyleDictionary();
+
+    public int getWidth() {
+        return width;
+    }
+
+    public int getHeight() {
+        return height;
+    }
+
+    public void paint(Graphics2D graphics) {
+        currentRenderer.paint(graphics);
+    }
+
+    public void setSize(int width, int height) {
+        this.width = width;
+        this.height = height;
+
+        currentRenderer.setSize(width, height);
+    }
+
+    public int getPreferredWidth(int height) {
+        return currentRenderer.getPreferredWidth(height);
+    }
+
+    public int getPreferredHeight(int width) {
+        // Our preferred height is the maximum of all our possible renderers'
+        // preferred height
+        int preferredHeight = defaultRenderer.getPreferredHeight(width);
+
+        for (Class<?> key : cellRenderers) {
+            TableView.CellRenderer renderer = cellRenderers.get(key);
+            preferredHeight = Math.max(preferredHeight,
+                renderer.getPreferredHeight(width));
+        }
+
+        return preferredHeight;
+    }
+
+    public Dimensions getPreferredSize() {
+        return new Dimensions(getPreferredWidth(-1), getPreferredHeight(-1));
+    }
+
+    public Dictionary<String, Object> getStyles() {
+        return STYLES;
+    }
+
+    @SuppressWarnings("unchecked")
+    public void render(Object value, TableView tableView, TableView.Column column,
+        boolean rowSelected, boolean rowHighlighted, boolean rowDisabled) {
+        Object cellData = null;
+
+        // Get the row and cell data
+        String columnName = column.getName();
+        if (columnName != null) {
+            Dictionary<String, Object> rowData = (Dictionary<String, Object>)value;
+            cellData = rowData.get(columnName);
+        }
+
+        Class<?> valueClass = (cellData == null ? null : cellData.getClass());
+        TableView.CellRenderer cellRenderer = cellRenderers.get(valueClass);
+
+        if (cellRenderer == null) {
+            cellRenderer = defaultRenderer;
+        }
+
+        if (cellRenderer != currentRenderer) {
+            currentRenderer = cellRenderer;
+            cellRenderer.setSize(width, height);
+        }
+
+        cellRenderer.render(value, tableView, column, rowSelected, rowHighlighted, rowDisabled);
+    }
+
+    public TableView.CellRenderer getDefaultRenderer() {
+        return defaultRenderer;
+    }
+
+    public void setDefaultRenderer(TableView.CellRenderer defaultRenderer) {
+        if (defaultRenderer == null) {
+            throw new IllegalArgumentException("defaultRenderer is null.");
+        }
+
+        this.defaultRenderer = defaultRenderer;
+    }
+
+    public Sequence<RendererMapping> getRendererMappings() {
+        return rendererMappings;
+    }
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TableViewNumberCellRenderer.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TableViewNumberCellRenderer.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TableViewNumberCellRenderer.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TableViewNumberCellRenderer.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,71 @@
+/*
+ * 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.content;
+
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+import pivot.collections.Dictionary;
+import pivot.wtk.TableView;
+
+/**
+ * Default renderer for table view cells that contain numeric data. Renders
+ * cell contents as a formatted number.
+ *
+ * @author gbrown
+ */
+public class TableViewNumberCellRenderer extends TableViewCellRenderer {
+    private NumberFormat numberFormat = DEFAULT_NUMBER_FORMAT;
+
+    public static final NumberFormat DEFAULT_NUMBER_FORMAT = NumberFormat.getNumberInstance();
+
+    public NumberFormat getNumberFormat() {
+        return numberFormat;
+    }
+
+    public void setNumberFormat(NumberFormat numberFormat) {
+        if (numberFormat == null) {
+            throw new IllegalArgumentException("numberFormat is null.");
+        }
+
+        this.numberFormat = numberFormat;
+    }
+
+    public void setNumberFormat(String numberFormat) {
+        setNumberFormat(new DecimalFormat(numberFormat));
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public void render(Object value, TableView tableView, TableView.Column column,
+        boolean rowSelected, boolean rowHighlighted, boolean rowDisabled) {
+        String formattedNumber = null;
+
+        // Get the row and cell data
+        String columnName = column.getName();
+        if (columnName != null) {
+            Dictionary<String, Object> rowData = (Dictionary<String, Object>)value;
+            Object cellData = rowData.get(columnName);
+
+            if (cellData instanceof Number) {
+                formattedNumber = numberFormat.format((Number)cellData);
+            }
+        }
+
+        setText(formattedNumber);
+
+        renderStyles(tableView, rowSelected, rowDisabled);
+    }
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TreeBranch.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TreeBranch.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TreeBranch.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TreeBranch.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,139 @@
+/*
+ * 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.content;
+
+import java.util.Comparator;
+import java.util.Iterator;
+
+import pivot.collections.ArrayList;
+import pivot.collections.List;
+import pivot.collections.ListListener;
+import pivot.collections.Sequence;
+import pivot.util.ImmutableIterator;
+import pivot.util.ListenerList;
+import pivot.wtk.media.Image;
+
+/**
+ * Default tree branch implementation.
+ *
+ * @author gbrown
+ */
+public class TreeBranch extends TreeNode implements List<TreeNode> {
+    private Image expandedIcon = null;
+
+    private ArrayList<TreeNode> nodes = new ArrayList<TreeNode>();
+    private ListListenerList<TreeNode> listListeners = new ListListenerList<TreeNode>();
+
+    public TreeBranch() {
+        this(null, null, null);
+    }
+
+    public TreeBranch(Image icon) {
+        this(icon, null, null);
+    }
+
+    public TreeBranch(String text) {
+        this(null, null, text);
+    }
+
+    public TreeBranch(Image icon, String text) {
+        this(icon, null, text);
+    }
+
+    public TreeBranch(Image icon, Image expandedIcon, String text) {
+        super(icon, text);
+
+        this.expandedIcon = expandedIcon;
+    }
+
+    public Image getExpandedIcon() {
+        return expandedIcon;
+    }
+
+    public void setExpandedIcon(Image expandedIcon) {
+        this.expandedIcon = expandedIcon;
+    }
+
+    public int add(TreeNode treeNode) {
+        int index = nodes.getLength();
+        insert(treeNode, index);
+
+        return index;
+    }
+
+    public void insert(TreeNode treeNode, int index) {
+        nodes.insert(treeNode, index);
+        listListeners.itemInserted(this, index);
+    }
+
+    public TreeNode update(int index, TreeNode treeNode) {
+        TreeNode previousTreeNode = nodes.update(index, treeNode);
+        listListeners.itemUpdated(this, index, previousTreeNode);
+
+        return previousTreeNode;
+    }
+
+    public int remove(TreeNode treeNode) {
+        int index = nodes.indexOf(treeNode);
+        if (index != -1) {
+            remove(index, 1);
+        }
+
+        return index;
+    }
+
+    public Sequence<TreeNode> remove(int index, int count) {
+        Sequence<TreeNode> removed = nodes.remove(index, count);
+        listListeners.itemsRemoved(this, index, removed);
+
+        return removed;
+    }
+
+    public void clear() {
+        nodes.clear();
+        listListeners.itemsRemoved(this, 0, null);
+    }
+
+    public TreeNode get(int index) {
+        return nodes.get(index);
+    }
+
+    public int indexOf(TreeNode treeNode) {
+        return nodes.indexOf(treeNode);
+    }
+
+    public int getLength() {
+        return nodes.getLength();
+    }
+
+    public Comparator<TreeNode> getComparator() {
+        return nodes.getComparator();
+    }
+
+    public void setComparator(Comparator<TreeNode> comparator) {
+        Comparator<TreeNode> previousComparator = nodes.getComparator();
+        nodes.setComparator(comparator);
+        listListeners.comparatorChanged(this, previousComparator);
+    }
+
+    public Iterator<TreeNode> iterator() {
+        return new ImmutableIterator<TreeNode>(nodes.iterator());
+    }
+
+    public ListenerList<ListListener<TreeNode>> getListListeners() {
+        return listListeners;
+    }
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TreeNode.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TreeNode.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TreeNode.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TreeNode.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,80 @@
+/*
+ * 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.content;
+
+import java.net.URL;
+
+import pivot.wtk.ApplicationContext;
+import pivot.wtk.media.Image;
+
+/**
+ * Default tree node implementation.
+ *
+ * @author gbrown
+ */
+public class TreeNode {
+    private Image icon = null;
+    private String text = null;
+
+    public TreeNode() {
+        this(null, null);
+    }
+
+    public TreeNode(Image icon) {
+        this(icon, null);
+    }
+
+    public TreeNode(String text) {
+        this(null, text);
+    }
+
+    public TreeNode(Image icon, String text) {
+        this.icon = icon;
+        this.text = text;
+    }
+
+    public Image getIcon() {
+        return icon;
+    }
+
+    public void setIcon(Image icon) {
+        this.icon = icon;
+    }
+
+    public void setIcon(URL iconURL) {
+        Image icon = (Image)ApplicationContext.getResourceCache().get(iconURL);
+
+        if (icon == null) {
+            icon = Image.load(iconURL);
+            ApplicationContext.getResourceCache().put(iconURL, icon);
+        }
+
+        setIcon(icon);
+    }
+
+    public void setIcon(String iconName) {
+        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+        setIcon(classLoader.getResource(iconName));
+    }
+
+    public String getText() {
+        return text;
+    }
+
+    public void setText(String text) {
+        this.text = text;
+    }
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TreeViewNodeRenderer.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TreeViewNodeRenderer.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TreeViewNodeRenderer.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/TreeViewNodeRenderer.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,168 @@
+/*
+ * 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.content;
+
+import java.awt.Color;
+import java.awt.Font;
+
+import pivot.wtk.Component;
+import pivot.wtk.FlowPane;
+import pivot.wtk.HorizontalAlignment;
+import pivot.wtk.ImageView;
+import pivot.wtk.Label;
+import pivot.wtk.TreeView;
+import pivot.wtk.VerticalAlignment;
+import pivot.wtk.media.Image;
+
+/**
+ * Default tree node renderer.
+ *
+ * @author gbrown
+ */
+public class TreeViewNodeRenderer extends FlowPane implements TreeView.NodeRenderer {
+    protected ImageView imageView = new ImageView();
+    protected Label label = new Label();
+
+    public static final int DEFAULT_ICON_WIDTH = 16;
+    public static final int DEFAULT_ICON_HEIGHT = 16;
+    public static boolean DEFAULT_SHOW_ICON = true;
+
+    public TreeViewNodeRenderer() {
+        super();
+
+        getStyles().put("horizontalAlignment", HorizontalAlignment.LEFT);
+        getStyles().put("verticalAlignment", VerticalAlignment.CENTER);
+
+        add(imageView);
+        add(label);
+
+        imageView.setPreferredSize(DEFAULT_ICON_WIDTH, DEFAULT_ICON_HEIGHT);
+        imageView.setDisplayable(DEFAULT_SHOW_ICON);
+
+        setPreferredHeight(DEFAULT_ICON_HEIGHT);
+    }
+
+    public void setSize(int width, int height) {
+        super.setSize(width, height);
+
+        // Since this component doesn't have a parent, it won't be validated
+        // via layout; ensure that it is valid here
+        validate();
+    }
+
+    @SuppressWarnings("unchecked")
+    public void render(Object node, TreeView treeView, boolean expanded,
+        boolean selected, boolean highlighted, boolean disabled) {
+        Image icon = null;
+        String text = null;
+
+        if (node instanceof TreeNode) {
+            TreeNode treeNode = (TreeNode)node;
+
+            if (expanded
+                && treeNode instanceof TreeBranch) {
+                TreeBranch treeBranch = (TreeBranch)treeNode;
+                icon = treeBranch.getExpandedIcon();
+
+                if (icon == null) {
+                    icon = treeBranch.getIcon();
+                }
+            } else {
+                icon = treeNode.getIcon();
+            }
+
+            text = treeNode.getText();
+        } else if (node instanceof Image) {
+            icon = (Image)node;
+        } else {
+            if (node != null) {
+                text = node.toString();
+            }
+        }
+
+        // Update the image view
+        imageView.setImage(icon);
+        imageView.getStyles().put("opacity",
+            (treeView.isEnabled() && !disabled) ? 1.0f : 0.5f);
+
+        // Show/hide the label
+        if (text == null) {
+            label.setDisplayable(false);
+        } else {
+            label.setDisplayable(true);
+            label.setText(text);
+
+            // Update the label styles
+            Component.StyleDictionary labelStyles = label.getStyles();
+
+            Object labelFont = treeView.getStyles().get("font");
+            if (labelFont instanceof Font) {
+                labelStyles.put("font", labelFont);
+            }
+
+            Object color = null;
+            if (treeView.isEnabled() && !disabled) {
+                if (selected) {
+                    if (treeView.isFocused()) {
+                        color = treeView.getStyles().get("selectionColor");
+                    } else {
+                        color = treeView.getStyles().get("inactiveSelectionColor");
+                    }
+                } else {
+                    color = treeView.getStyles().get("color");
+                }
+            } else {
+                color = treeView.getStyles().get("disabledColor");
+            }
+
+            if (color instanceof Color) {
+                labelStyles.put("color", color);
+            }
+        }
+    }
+
+    public int getIconWidth() {
+        return imageView.getPreferredWidth(-1);
+    }
+
+    public void setIconWidth(int iconWidth) {
+        if (iconWidth == -1) {
+            throw new IllegalArgumentException();
+        }
+
+        imageView.setPreferredWidth(iconWidth);
+    }
+
+    public int getIconHeight() {
+        return imageView.getPreferredHeight(-1);
+    }
+
+    public void setIconHeight(int iconHeight) {
+        if (iconHeight == -1) {
+            throw new IllegalArgumentException();
+        }
+
+        imageView.setPreferredHeight(iconHeight);
+    }
+
+    public boolean getShowIcon() {
+        return imageView.isDisplayable();
+    }
+
+    public void setShowIcon(boolean showIcon) {
+        imageView.setDisplayable(showIcon);
+    }
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/package.html
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/package.html?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/package.html (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/content/package.html Mon Mar 16 16:16:40 2009
@@ -0,0 +1,6 @@
+<html>
+<head></head>
+<body>
+<p>Contains classes representing component data, such as list items or table rows.</p>
+</body>
+</html>

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/effects/BlurDecorator.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/effects/BlurDecorator.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/effects/BlurDecorator.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/effects/BlurDecorator.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk.effects;
+
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+import java.awt.image.ConvolveOp;
+import java.awt.image.Kernel;
+
+import pivot.wtk.Component;
+import pivot.wtk.Decorator;
+import pivot.wtk.Bounds;
+
+/**
+ * Decorator that applies a blur to a component.
+ * <p>
+ * Blurs are given an integer magnitude, which represents the intensity of
+ * the blur. This value translates to a grid of pixels (<tt>blurMagnitude^2</tt>),
+ * where each pixel value is calculated by consulting its neighboring pixels
+ * according to the grid. Because of this, note that you will get "prettier"
+ * blurring if you choose odd values for the blur magnitude; this allows the
+ * pixel in question to reside at the center of the grid, thus preventing any
+ * arbitrary shifting of pixels. Also note that the greater the intensity of
+ * the blur, the greater the intensity of the calculations necessary to
+ * accomplish the blur (and the longer it will take to perform the blur).
+ * <p>
+ * TODO Increase size of buffered image to account for edge conditions of the
+ * blur.
+ * <p>
+ * TODO Use unequal values in the blur kernel to make pixels that are farther
+ * away count less towards the blur.
+ *
+ * @author tvolkert
+ */
+public class BlurDecorator implements Decorator {
+    private int blurMagnitude;
+
+    private Graphics2D graphics = null;
+
+    private BufferedImage bufferedImage = null;
+    private Graphics2D bufferedImageGraphics = null;
+
+    /**
+     * Creates a <tt>BlurDecorator</tt> with the default blur magnitude.
+     *
+     * @see #BlurDecorator(int)
+     */
+    public BlurDecorator() {
+        this(9);
+    }
+
+    /**
+     * Creates a <tt>BlurDecorator</tt> with the specified blur magnitude.
+     *
+     * @param blurMagnitude
+     * The intensity of the blur.
+     */
+    public BlurDecorator(int blurMagnitude) {
+        this.blurMagnitude = blurMagnitude;
+    }
+
+    public Graphics2D prepare(Component component, Graphics2D graphics) {
+        this.graphics = graphics;
+
+        int width = component.getWidth();
+        int height = component.getHeight();
+
+        if (bufferedImage == null
+            || bufferedImage.getWidth() != width
+            || bufferedImage.getHeight() != height) {
+            bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
+        }
+
+        bufferedImageGraphics = bufferedImage.createGraphics();
+        bufferedImageGraphics.setClip(graphics.getClip());
+
+        return bufferedImageGraphics;
+    }
+
+    public void update() {
+        bufferedImageGraphics.dispose();
+        bufferedImage.flush();
+
+        float[] kernel = new float[blurMagnitude * blurMagnitude];
+        for (int i = 0, n = kernel.length; i < n; i++) {
+            kernel[i] = 1f / n;
+        }
+
+        ConvolveOp blur = new ConvolveOp(new Kernel(blurMagnitude, blurMagnitude,
+            kernel), ConvolveOp.EDGE_NO_OP, null);
+        bufferedImage = blur.filter(bufferedImage, null);
+
+        this.graphics.drawImage(bufferedImage, 0, 0, null);
+    }
+
+    public Bounds getAffectedArea(Component component, int x, int y, int width, int height) {
+        return new Bounds(x, y, width, height);
+    }
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/effects/DropShadowDecorator.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/effects/DropShadowDecorator.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/effects/DropShadowDecorator.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/effects/DropShadowDecorator.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,399 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Contains code and concepts from ShadowRenderer.java v1.6,
+ * copyright 2006 Sun Microsystems, Inc., 4150 Network Circle,
+ * Santa Clara, California 95054, U.S.A. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk.effects;
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+import java.awt.image.Raster;
+import java.awt.image.WritableRaster;
+import pivot.wtk.Component;
+import pivot.wtk.Decorator;
+import pivot.wtk.Bounds;
+
+/**
+ * Decorator that adds a drop shadows to a component.
+ *
+ * TODO Drop shadows do not work with any background opacity?
+ *
+ * TODO Optimize so we only repaint on resize?
+ *
+ * @author gbrown
+ * @author tvolkert
+ * @author eryzhikov
+ * @author Romain Guy
+ * @author Sebastien Petrucci
+ */
+public class DropShadowDecorator implements Decorator {
+    private int blurRadius;
+    private int xOffset;
+    private int yOffset;
+
+    private Color shadowColor = Color.BLACK;
+    private float shadowOpacity = 0.33f;
+
+    private Component component = null;
+    private Graphics2D graphics = null;
+
+    private BufferedImage componentImage = null;
+    private Graphics2D componentGraphics = null;
+
+    public DropShadowDecorator() {
+        this(5, 5, 5);
+    }
+
+    public DropShadowDecorator(int blurRadius, int xOffset, int yOffset) {
+        this.blurRadius = blurRadius;
+        this.xOffset = xOffset;
+        this.yOffset = yOffset;
+    }
+
+    /**
+     * Returns the color used to draw the shadow.
+     *
+     * @return
+     * The color used to draw the shadow.
+     */
+    public Color getShadowColor() {
+        return shadowColor;
+    }
+
+    /**
+     * Sets the color used to draw the shadow.
+     *
+     * @param shadowColor
+     * The color used to draw the shadow.
+     */
+    public void setShadowColor(Color shadowColor) {
+        this.shadowColor = shadowColor;
+    }
+
+    /**
+     * Sets the color used to draw the shadow.
+     *
+     * @param shadowColor
+     * The color used to draw the shadow.
+     */
+    public final void setShadowColor(String shadowColor) {
+        if (shadowColor == null) {
+            throw new IllegalArgumentException("shadowColor is null.");
+        }
+
+        setShadowColor(Color.decode(shadowColor));
+    }
+
+    /**
+     * Returns the opacity used to draw the shadow.
+     *
+     * @return
+     * The color used to draw the shadow.
+     */
+    public float getShadowOpacity() {
+        return shadowOpacity;
+    }
+
+    /**
+     * Sets the opacity used to draw the shadow.
+     *
+     * @param shadowOpacity
+     * The opacity used to draw the shadow.
+     */
+    public void setShadowOpacity(float shadowOpacity) {
+        this.shadowOpacity = shadowOpacity;
+    }
+
+    /**
+     * Returns the blur radius used to draw the shadow.
+     *
+     * @return
+     * The blur radius used to draw the shadow.
+     */
+    public int getBlurRadius() {
+        return blurRadius;
+    }
+
+    /**
+     * Sets the blur radius used to draw the shadow.
+     *
+     * @param blurRadius
+     * The blur radius used to draw the shadow.
+     */
+    public void setBlurRadius(int blurRadius) {
+        this.blurRadius = blurRadius;
+    }
+
+    /**
+     * Returns the amount that the drop shadow will be offset along the x axis.
+     *
+     * @return
+     * The x offset used to draw the shadow
+     */
+    public int getXOffset() {
+        return xOffset;
+    }
+
+    /**
+     * Sets the amount that the drop shadow will be offset along the x axis.
+     *
+     * @param xOffset
+     * The x offset used to draw the shadow
+     */
+    public void setXOffset(int xOffset) {
+        this.xOffset = xOffset;
+    }
+
+    /**
+     * Returns the amount that the drop shadow will be offset along the y axis.
+     *
+     * @return
+     * The y offset used to draw the shadow
+     */
+    public int getYOffset() {
+        return yOffset;
+    }
+
+    /**
+     * Sets the amount that the drop shadow will be offset along the y axis.
+     *
+     * @param yOffset
+     * The y offset used to draw the shadow
+     */
+    public void setYOffset(int yOffset) {
+        this.yOffset = yOffset;
+    }
+
+    public Graphics2D prepare(Component component, Graphics2D graphics) {
+        int width = component.getWidth();
+        int height = component.getHeight();
+
+        if (this.component != component
+            || componentImage == null
+            || componentImage.getWidth() != width
+            || componentImage.getHeight() != height) {
+            componentImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
+        }
+
+        this.component = component;
+        this.graphics = graphics;
+
+        componentGraphics = componentImage.createGraphics();
+        componentGraphics.setClip(graphics.getClip());
+
+        return componentGraphics;
+    }
+
+    public void update() {
+        componentGraphics.dispose();
+
+        BufferedImage shadowImage = createShadow(componentImage);
+
+        java.awt.Shape clip = graphics.getClip();
+        if (clip != null) {
+            java.awt.Rectangle clipBounds = clip.getBounds();
+            Bounds affectedArea = getAffectedArea(component, clipBounds.x, clipBounds.y,
+                clipBounds.width, clipBounds.height);
+            clipBounds = affectedArea.toRectangle();
+            graphics.setClip(clipBounds);
+        }
+
+        graphics.drawImage(shadowImage, xOffset - blurRadius, yOffset - blurRadius, null);
+        graphics.setClip(clip);
+        graphics.drawImage(componentImage, 0, 0, null);
+    }
+
+    public Bounds getAffectedArea(Component component, int x, int y, int width, int height) {
+        return new Bounds(x + xOffset - blurRadius,
+            y + yOffset - blurRadius,
+            width + blurRadius * 2,
+            height + blurRadius * 2);
+    }
+
+    /**
+     * Generates the shadow for a given picture and the current properties of
+     * the decorator. The generated image dimensions are computed as follows:
+     *
+     * <pre>
+     * width = imageWidth + 2 * blurRadius
+     * height = imageHeight + 2 * blurRadius
+     * </pre>
+     *
+     * @param image
+     * The image from which the shadow will be cast.
+     *
+     * @return
+     * An image containing the generated shadow.
+     */
+    private BufferedImage createShadow(BufferedImage src) {
+        int shadowSize = blurRadius * 2;
+
+        int srcWidth = src.getWidth();
+        int srcHeight = src.getHeight();
+
+        int dstWidth = srcWidth + shadowSize;
+        int dstHeight = srcHeight + shadowSize;
+
+        int left = blurRadius;
+        int right = shadowSize - left;
+
+        int yStop = dstHeight - right;
+
+        int shadowRgb = shadowColor.getRGB() & 0x00FFFFFF;
+        int[] aHistory = new int[shadowSize];
+        int historyIdx;
+
+        int aSum;
+
+        BufferedImage dst = new BufferedImage(dstWidth, dstHeight,
+            BufferedImage.TYPE_INT_ARGB);
+
+        int[] dstBuffer = new int[dstWidth * dstHeight];
+        int[] srcBuffer = new int[srcWidth * srcHeight];
+
+        Raster srcRaster = src.getRaster();
+        srcRaster.getDataElements(0, 0, srcWidth, srcHeight, srcBuffer);
+
+        int lastPixelOffset = right * dstWidth;
+        float hSumDivider = 1.0f / shadowSize;
+        float vSumDivider = shadowOpacity / shadowSize;
+
+        int[] hSumLookup = new int[256 * shadowSize];
+        for (int i = 0; i < hSumLookup.length; i++) {
+            hSumLookup[i] = (int) (i * hSumDivider);
+        }
+
+        int[] vSumLookup = new int[256 * shadowSize];
+        for (int i = 0; i < vSumLookup.length; i++) {
+            vSumLookup[i] = (int) (i * vSumDivider);
+        }
+
+        int srcOffset;
+
+        // Horizontal pass: extract the alpha mask from the source picture and
+        // blur it into the destination picture
+        for (int srcY = 0, dstOffset = left * dstWidth; srcY < srcHeight; srcY++) {
+            // First pixels are empty
+            for (historyIdx = 0; historyIdx < shadowSize;) {
+                aHistory[historyIdx++] = 0;
+            }
+
+            aSum = 0;
+            historyIdx = 0;
+            srcOffset = srcY * srcWidth;
+
+            // Compute the blur average with pixels from the source image
+            for (int srcX = 0; srcX < srcWidth; srcX++) {
+                int a = hSumLookup[aSum];
+                // Store the alpha value only; the shadow color will be added
+                // in the next pass
+                dstBuffer[dstOffset++] = a << 24;
+
+                // Substract the oldest pixel from the sum
+                aSum -= aHistory[historyIdx];
+
+                // Extract the new pixel and store its value into history...
+                a = srcBuffer[srcOffset + srcX] >>> 24;
+                aHistory[historyIdx] = a;
+
+                // ...and add its value to the sum
+                aSum += a;
+
+                if (++historyIdx >= shadowSize) {
+                    historyIdx -= shadowSize;
+                }
+            }
+
+            // Blur the end of the row - no new pixels to grab
+            for (int i = 0; i < shadowSize; i++) {
+                int a = hSumLookup[aSum];
+                dstBuffer[dstOffset++] = a << 24;
+
+                // Substract the oldest pixel from the sum...and nothing new
+                // to add!
+                aSum -= aHistory[historyIdx];
+
+                if (++historyIdx >= shadowSize) {
+                    historyIdx -= shadowSize;
+                }
+            }
+        }
+
+        // Vertical pass
+        for (int x = 0, bufferOffset = 0; x < dstWidth; x++, bufferOffset = x) {
+            aSum = 0;
+
+            // First pixels are empty...
+            for (historyIdx = 0; historyIdx < left;) {
+                aHistory[historyIdx++] = 0;
+            }
+
+            // ...and then they come from the dstBuffer
+            for (int y = 0; y < right; y++, bufferOffset += dstWidth) {
+                // Extract alpha and store into history...
+                int a = dstBuffer[bufferOffset] >>> 24;
+                aHistory[historyIdx++] = a;
+
+                // ...and add to sum
+                aSum += a;
+            }
+
+            bufferOffset = x;
+            historyIdx = 0;
+
+            // Compute the blur avera`ge with pixels from the previous pass
+            for (int y = 0; y < yStop; y++, bufferOffset += dstWidth) {
+                // Store alpha value + shadow color
+                int a = vSumLookup[aSum];
+                dstBuffer[bufferOffset] = a << 24 | shadowRgb;
+
+                // Substract the oldest pixel from the sum
+                aSum -= aHistory[historyIdx];
+
+                // Extract the new pixel and store its value into history...
+                a = dstBuffer[bufferOffset + lastPixelOffset] >>> 24;
+                aHistory[historyIdx] = a;
+
+                // ... and add its value to the sum
+                aSum += a;
+
+                if (++historyIdx >= shadowSize) {
+                    historyIdx -= shadowSize;
+                }
+            }
+
+            // Blur the end of the column - no pixels to grab anymore
+            for (int y = yStop; y < dstHeight; y++, bufferOffset += dstWidth) {
+                int a = vSumLookup[aSum];
+                dstBuffer[bufferOffset] = a << 24 | shadowRgb;
+
+                // Substract the oldest pixel from the sum
+                aSum -= aHistory[historyIdx];
+
+                if (++historyIdx >= shadowSize) {
+                    historyIdx -= shadowSize;
+                }
+            }
+        }
+
+        WritableRaster dstRaster = dst.getRaster();
+        dstRaster.setDataElements(0, 0, dstWidth, dstHeight, dstBuffer);
+
+        return dst;
+    }
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/effects/FadeDecorator.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/effects/FadeDecorator.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/effects/FadeDecorator.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/effects/FadeDecorator.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,51 @@
+package pivot.wtk.effects;
+
+import java.awt.AlphaComposite;
+import java.awt.Graphics2D;
+
+import pivot.wtk.Component;
+import pivot.wtk.Decorator;
+import pivot.wtk.Bounds;
+
+/**
+ * Decorator that applies an opacity to a component.
+ *
+ * @author gbrown
+ */
+public class FadeDecorator implements Decorator {
+    private float opacity;
+
+    public FadeDecorator() {
+        this(0.5f);
+    }
+
+    public FadeDecorator(float opacity) {
+        this.opacity = opacity;
+    }
+
+    public float getOpacity() {
+        return opacity;
+    }
+
+    public void setOpacity(float opacity) {
+        if (opacity < 0f
+            || opacity > 1f) {
+            throw new IllegalArgumentException("opacity must be a value between 0 and 1, inclusive.");
+        }
+
+        this.opacity = opacity;
+    }
+
+    public Graphics2D prepare(Component component, Graphics2D graphics) {
+        graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, opacity));
+        return graphics;
+    }
+
+    public void update() {
+        // No-op
+    }
+
+    public Bounds getAffectedArea(Component component, int x, int y, int width, int height) {
+        return new Bounds(x, y, width, height);
+    }
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/effects/GrayscaleDecorator.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/effects/GrayscaleDecorator.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/effects/GrayscaleDecorator.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/effects/GrayscaleDecorator.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk.effects;
+
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+
+import pivot.wtk.Component;
+import pivot.wtk.Decorator;
+import pivot.wtk.Bounds;
+
+/**
+ * Decorator that applies a grayscale conversion to a component.
+ *
+ * @author tvolkert
+ * @author gbrown
+ */
+public class GrayscaleDecorator implements Decorator {
+    private Graphics2D graphics = null;
+
+    private BufferedImage bufferedImage = null;
+    private Graphics2D bufferedImageGraphics = null;
+
+    public Graphics2D prepare(Component component, Graphics2D graphics) {
+        this.graphics = graphics;
+
+        int width = component.getWidth();
+        int height = component.getHeight();
+
+        if (bufferedImage == null
+            || bufferedImage.getWidth() < width
+            || bufferedImage.getHeight() < height) {
+            bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
+        }
+
+        bufferedImageGraphics = bufferedImage.createGraphics();
+        bufferedImageGraphics.setClip(graphics.getClip());
+
+        return bufferedImageGraphics;
+    }
+
+    public void update() {
+        bufferedImageGraphics.dispose();
+        bufferedImage.flush();
+
+        graphics.drawImage(bufferedImage, 0, 0, null);
+    }
+
+    public Bounds getAffectedArea(Component component, int x, int y, int width, int height) {
+        return new Bounds(x, y, width, height);
+    }
+}