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

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

Added: incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/MenuItemData.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/MenuItemData.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/MenuItemData.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/MenuItemData.java Wed Mar 25 23:08:38 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/branches/1.1/wtk/src/pivot/wtk/content/MenuItemDataRenderer.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/MenuItemDataRenderer.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/MenuItemDataRenderer.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/MenuItemDataRenderer.java Wed Mar 25 23:08:38 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/branches/1.1/wtk/src/pivot/wtk/content/NumericSpinnerData.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/NumericSpinnerData.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/NumericSpinnerData.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/NumericSpinnerData.java Wed Mar 25 23:08:38 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/branches/1.1/wtk/src/pivot/wtk/content/SpinnerItemRenderer.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/SpinnerItemRenderer.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/SpinnerItemRenderer.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/SpinnerItemRenderer.java Wed Mar 25 23:08:38 2009
@@ -0,0 +1,63 @@
+/*
+ * 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.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) {
+        Object font = spinner.getStyles().get("font");
+
+        if (font instanceof Font) {
+            getStyles().put("font", font);
+        }
+
+        Object color = null;
+
+        if (spinner.isEnabled()) {
+            color = spinner.getStyles().get("color");
+        } else {
+            color = spinner.getStyles().get("disabledColor");
+        }
+
+        if (color instanceof Color) {
+            getStyles().put("color", color);
+        }
+    }
+}

Added: incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TableRow.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TableRow.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TableRow.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TableRow.java Wed Mar 25 23:08:38 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/branches/1.1/wtk/src/pivot/wtk/content/TableViewBooleanCellRenderer.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TableViewBooleanCellRenderer.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TableViewBooleanCellRenderer.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TableViewBooleanCellRenderer.java Wed Mar 25 23:08:38 2009
@@ -0,0 +1,86 @@
+/*
+ * 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.beans.BeanDictionary;
+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;
+            if (value instanceof Dictionary<?, ?>) {
+                rowData = (Dictionary<String, Object>)value;
+            } else {
+                rowData = new BeanDictionary(value);
+            }
+
+            Object cellData = rowData.get(columnName);
+
+            if (cellData instanceof String) {
+                cellData = Boolean.parseBoolean((String)cellData);
+            }
+
+            if (cellData instanceof Boolean) {
+                checkboxSelected = (Boolean)cellData;
+            } else {
+                System.err.println("Data for \"" + columnName + "\" is not an instance of "
+                    + Boolean.class.getName());
+            }
+        }
+
+        checkbox.setSelected(checkboxSelected);
+        checkbox.setEnabled(tableView.isEnabled() && !rowDisabled);
+    }
+}

Added: incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TableViewCellRenderer.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TableViewCellRenderer.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TableViewCellRenderer.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TableViewCellRenderer.java Wed Mar 25 23:08:38 2009
@@ -0,0 +1,94 @@
+/*
+ * 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.beans.BeanDictionary;
+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;
+            if (value instanceof Dictionary<?, ?>) {
+            	rowData = (Dictionary<String, Object>)value;
+            } else {
+            	rowData = new BeanDictionary(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/branches/1.1/wtk/src/pivot/wtk/content/TableViewDateCellRenderer.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TableViewDateCellRenderer.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TableViewDateCellRenderer.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TableViewDateCellRenderer.java Wed Mar 25 23:08:38 2009
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk.content;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import pivot.beans.BeanDictionary;
+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;
+            if (value instanceof Dictionary<?, ?>) {
+                rowData = (Dictionary<String, Object>)value;
+            } else {
+                rowData = new BeanDictionary(value);
+            }
+
+            Object cellData = rowData.get(columnName);
+
+            if (cellData instanceof Date) {
+                formattedDate = dateFormat.format((Date)cellData);
+            } else {
+                System.err.println("Data for \"" + columnName + "\" is not an instance of "
+                    + Date.class.getName());
+            }
+        }
+
+        setText(formattedDate);
+
+        renderStyles(tableView, rowSelected, rowDisabled);
+    }
+}

Added: incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TableViewHeaderData.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TableViewHeaderData.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TableViewHeaderData.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TableViewHeaderData.java Wed Mar 25 23:08:38 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/branches/1.1/wtk/src/pivot/wtk/content/TableViewHeaderDataRenderer.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TableViewHeaderDataRenderer.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TableViewHeaderDataRenderer.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TableViewHeaderDataRenderer.java Wed Mar 25 23:08:38 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/branches/1.1/wtk/src/pivot/wtk/content/TableViewImageCellRenderer.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TableViewImageCellRenderer.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TableViewImageCellRenderer.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TableViewImageCellRenderer.java Wed Mar 25 23:08:38 2009
@@ -0,0 +1,84 @@
+/*
+ * 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.beans.BeanDictionary;
+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;
+            if (value instanceof Dictionary<?, ?>) {
+            	rowData = (Dictionary<String, Object>)value;
+            } else {
+            	rowData = new BeanDictionary(value);
+            }
+
+            Object cellData = rowData.get(columnName);
+
+            if (cellData instanceof Image) {
+                image = (Image)cellData;
+            } else {
+                System.err.println("Data for \"" + columnName + "\" is not an instance of "
+                    + Image.class.getName());
+            }
+        }
+
+        setImage(image);
+    }
+}

Added: incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TableViewMultiCellRenderer.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TableViewMultiCellRenderer.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TableViewMultiCellRenderer.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TableViewMultiCellRenderer.java Wed Mar 25 23:08:38 2009
@@ -0,0 +1,345 @@
+/*
+ * 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.beans.BeanDictionary;
+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;
+            if (value instanceof Dictionary<?, ?>) {
+            	rowData = (Dictionary<String, Object>)value;
+            } else {
+            	rowData = new BeanDictionary(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/branches/1.1/wtk/src/pivot/wtk/content/TableViewNumberCellRenderer.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TableViewNumberCellRenderer.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TableViewNumberCellRenderer.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TableViewNumberCellRenderer.java Wed Mar 25 23:08:38 2009
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk.content;
+
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+
+import pivot.beans.BeanDictionary;
+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;
+            if (value instanceof Dictionary<?, ?>) {
+                rowData = (Dictionary<String, Object>)value;
+            } else {
+                rowData = new BeanDictionary(value);
+            }
+
+            Object cellData = rowData.get(columnName);
+
+            if (cellData instanceof Number) {
+                formattedNumber = numberFormat.format((Number)cellData);
+            } else {
+                System.err.println("Data for \"" + columnName + "\" is not an instance of "
+                    + Number.class.getName());
+            }
+        }
+
+        setText(formattedNumber);
+
+        renderStyles(tableView, rowSelected, rowDisabled);
+    }
+}

Added: incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TreeBranch.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TreeBranch.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TreeBranch.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TreeBranch.java Wed Mar 25 23:08:38 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/branches/1.1/wtk/src/pivot/wtk/content/TreeNode.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TreeNode.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TreeNode.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TreeNode.java Wed Mar 25 23:08:38 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/branches/1.1/wtk/src/pivot/wtk/content/TreeViewFileRenderer.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TreeViewFileRenderer.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TreeViewFileRenderer.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TreeViewFileRenderer.java Wed Mar 25 23:08:38 2009
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2009 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk.content;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.FileNotFoundException;
+
+import pivot.io.Folder;
+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;
+import pivot.wtk.media.Picture;
+import sun.awt.shell.ShellFolder;
+
+/**
+ * Tree view renderer for displaying file system contents.
+ *
+ * @author gbrown
+ */
+public class TreeViewFileRenderer extends FlowPane implements TreeView.NodeRenderer {
+    private ImageView imageView = new ImageView();
+    private Label label = new Label();
+
+    private boolean useNativeIcons = true;
+
+    public static final int ICON_WIDTH = 16;
+    public static final int ICON_HEIGHT = 16;
+
+    private static final Image defaultFolderImage =
+        Image.load(TreeViewFileRenderer.class.getResource("folder.png"));
+    private static final Image defaultFileImage =
+        Image.load(TreeViewFileRenderer.class.getResource("page_white.png"));
+
+    public TreeViewFileRenderer() {
+        super();
+
+        getStyles().put("horizontalAlignment", HorizontalAlignment.LEFT);
+        getStyles().put("verticalAlignment", VerticalAlignment.CENTER);
+
+        add(imageView);
+        add(label);
+
+        imageView.setPreferredSize(ICON_WIDTH, 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();
+    }
+
+    @Override
+    public int getPreferredHeight(int width) {
+        int preferredHeight = super.getPreferredHeight(width);
+        return preferredHeight;
+    }
+
+    public void render(Object node, TreeView treeView, boolean expanded,
+        boolean selected, TreeView.NodeCheckState checkState,
+        boolean highlighted, boolean disabled) {
+        File file = (File)node;
+
+        // Update the image view
+        Image icon = null;
+
+        ShellFolder shellFolder = null;
+        try {
+            shellFolder = ShellFolder.getShellFolder(file);
+        } catch(FileNotFoundException exception) {
+        }
+
+        java.awt.Image image = null;
+        if (shellFolder != null) {
+            image = shellFolder.getIcon(false);
+        }
+
+        if (image instanceof BufferedImage
+            && useNativeIcons) {
+            icon = new Picture((BufferedImage)image);
+        } else {
+            if (file instanceof Folder) {
+                icon = defaultFolderImage;
+            } else {
+                icon = defaultFileImage;
+            }
+        }
+
+        imageView.setImage(icon);
+        imageView.getStyles().put("opacity",
+            (treeView.isEnabled() && !disabled) ? 1.0f : 0.5f);
+
+        // Update the label
+        label.setText(file.getName());
+
+        Object labelFont = treeView.getStyles().get("font");
+        if (labelFont instanceof Font) {
+            label.getStyles().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) {
+            label.getStyles().put("color", color);
+        }
+    }
+
+    public boolean getUseNativeIcons() {
+        return useNativeIcons;
+    }
+
+    public void setUseNativeIcons(boolean useNativeIcons) {
+        this.useNativeIcons = useNativeIcons;
+    }
+}

Added: incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TreeViewNodeEditor.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TreeViewNodeEditor.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TreeViewNodeEditor.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TreeViewNodeEditor.java Wed Mar 25 23:08:38 2009
@@ -0,0 +1,303 @@
+/*
+ * Copyright (c) 2009 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk.content;
+
+import pivot.collections.ArrayList;
+import pivot.collections.List;
+import pivot.collections.Sequence;
+import pivot.util.Vote;
+import pivot.wtk.Bounds;
+import pivot.wtk.Component;
+import pivot.wtk.ComponentKeyListener;
+import pivot.wtk.Container;
+import pivot.wtk.ContainerMouseListener;
+import pivot.wtk.Display;
+import pivot.wtk.Insets;
+import pivot.wtk.Keyboard;
+import pivot.wtk.Mouse;
+import pivot.wtk.TextInput;
+import pivot.wtk.TreeView;
+import pivot.wtk.TreeViewListener;
+import pivot.wtk.TreeViewNodeListener;
+import pivot.wtk.Window;
+import pivot.wtk.WindowStateListener;
+import pivot.wtk.content.TreeNode;
+import pivot.wtk.content.TreeViewNodeRenderer;
+
+/**
+ * Default tree view node editor, which allows the user to edit the text of a
+ * tree node in a <tt>TextInput</tt>. It is only intended to work with
+ * {@link TreeNode} data and {@link TreeViewNodeRenderer} renderers.
+ *
+ * @author tvolkert
+ */
+public class TreeViewNodeEditor implements TreeView.NodeEditor {
+    /**
+     * Responsible for "edit initialization" and "edit finalization" tasks when
+     * the edit popup is opened and closed, respectively.
+     *
+     * @author tvolkert
+     */
+    private WindowStateListener popupStateHandler = new WindowStateListener() {
+        public Vote previewWindowOpen(Window window, Display display) {
+            return Vote.APPROVE;
+        }
+
+        public void windowOpenVetoed(Window window, Vote reason) {
+        }
+
+        public void windowOpened(Window window) {
+            Display display = window.getDisplay();
+            display.getContainerMouseListeners().add(displayMouseHandler);
+
+            treeView.getTreeViewListeners().add(treeViewHandler);
+            treeView.getTreeViewNodeListeners().add(treeViewHandler);
+        }
+
+        public Vote previewWindowClose(Window window) {
+            return Vote.APPROVE;
+        }
+
+        public void windowCloseVetoed(Window window, Vote reason) {
+        }
+
+        public void windowClosed(Window window, Display display) {
+            // Clean up
+            display.getContainerMouseListeners().remove(displayMouseHandler);
+
+            treeView.getTreeViewListeners().remove(treeViewHandler);
+            treeView.getTreeViewNodeListeners().remove(treeViewHandler);
+
+            // Restore focus to the tree view
+            treeView.requestFocus();
+
+            // Free memory
+            treeView = null;
+            path = null;
+            textInput = null;
+            popup = null;
+        }
+    };
+
+    /**
+     * Responsible for saving or cancelling the edit based on the user pressing
+     * the <tt>ENTER</tt> key or the <tt>ESCAPE</tt> key, respectively.
+     *
+     * @author tvolkert
+     */
+    private ComponentKeyListener textInputKeyHandler = new ComponentKeyListener() {
+        public boolean keyPressed(Component component, int keyCode, Keyboard.KeyLocation keyLocation) {
+            if (keyCode == Keyboard.KeyCode.ENTER) {
+                save();
+            } else if (keyCode == Keyboard.KeyCode.ESCAPE) {
+                cancel();
+            }
+
+            return false;
+        }
+
+        public boolean keyReleased(Component component, int keyCode, Keyboard.KeyLocation keyLocation) {
+            return false;
+        }
+
+        public boolean keyTyped(Component component, char character) {
+            return false;
+        }
+    };
+
+    /**
+     * Responsible for closing the popup whenever the user clicks outside the
+     * bounds of the popup.
+     *
+     * @author tvolkert
+     */
+    private ContainerMouseListener displayMouseHandler = new ContainerMouseListener() {
+        public boolean mouseMove(Container container, int x, int y) {
+            return false;
+        }
+
+        public boolean mouseDown(Container container, Mouse.Button button, int x, int y) {
+            // If the event did not occur within a window that is owned by
+            // this popup, close the popup
+            Display display = (Display)container;
+            Window window = (Window)display.getComponentAt(x, y);
+
+            if (popup != window) {
+                save();
+            }
+
+            return false;
+        }
+
+        public boolean mouseUp(Container container, Mouse.Button button, int x, int y) {
+            return false;
+        }
+
+        public boolean mouseWheel(Container container, Mouse.ScrollType scrollType,
+            int scrollAmount, int wheelRotation, int x, int y) {
+            return true;
+        }
+    };
+
+    /**
+     * Responsible for cancelling the edit if any relevant changes are made to
+     * the tree view while we're editing.
+     */
+    private class TreeViewHandler implements TreeViewListener, TreeViewNodeListener {
+        public void treeDataChanged(TreeView treeView, List<?> previousTreeData) {
+            cancel();
+        }
+
+        public void nodeRendererChanged(TreeView treeView, TreeView.NodeRenderer previousNodeRenderer) {
+        }
+
+        public void nodeEditorChanged(TreeView treeView, TreeView.NodeEditor previousNodeEditor) {
+            cancel();
+        }
+
+        public void selectModeChanged(TreeView treeView, TreeView.SelectMode previousSelectMode) {
+        }
+
+        public void checkmarksEnabledChanged(TreeView treeView) {
+        }
+
+        public void showMixedCheckmarkStateChanged(TreeView treeView) {
+        }
+
+        public void nodeInserted(TreeView treeView, Sequence<Integer> path, int index) {
+            cancel();
+        }
+
+        public void nodesRemoved(TreeView treeView, Sequence<Integer> path, int index, int count) {
+            cancel();
+        }
+
+        public void nodeUpdated(TreeView treeView, Sequence<Integer> path, int index) {
+            cancel();
+        }
+
+        public void nodesSorted(TreeView treeView, Sequence<Integer> path) {
+            cancel();
+        }
+    }
+
+    private TreeView treeView = null;
+    private Sequence<Integer> path = null;
+
+    private Window popup = null;
+    private TextInput textInput = null;
+
+    private TreeViewHandler treeViewHandler = new TreeViewHandler();
+
+    public void edit(TreeView treeView, Sequence<Integer> path) {
+        if (isEditing()) {
+            throw new IllegalStateException();
+        }
+
+        this.treeView = treeView;
+        this.path = path;
+
+        // Get the data being edited
+        List<?> treeData = treeView.getTreeData();
+        TreeNode nodeData = (TreeNode)Sequence.Tree.get(treeData, path);
+
+        // Get the node bounds
+        Bounds nodeBounds = treeView.getNodeBounds(path);
+        int nodeIndent = treeView.getNodeIndent(path.getLength());
+        nodeBounds.x += nodeIndent;
+        nodeBounds.width -= nodeIndent;
+
+        // Render the node data
+        TreeViewNodeRenderer nodeRenderer = (TreeViewNodeRenderer)treeView.getNodeRenderer();
+        nodeRenderer.render(nodeData, treeView, false, false,
+            TreeView.NodeCheckState.UNCHECKED, false, false);
+        nodeRenderer.setSize(nodeBounds.width, nodeBounds.height);
+
+        // Get the text bounds
+        Bounds textBounds = nodeRenderer.getTextBounds();
+
+        if (textBounds != null) {
+            textInput = new TextInput();
+            Insets padding = (Insets)textInput.getStyles().get("padding");
+
+            // Calculate the bounds of what we're editing
+            Bounds editBounds = new Bounds(nodeBounds);
+            editBounds.x += textBounds.x - (padding.left + 1);
+            editBounds.width -= textBounds.x;
+            editBounds.width += (padding.left + 1);
+
+            // Scroll to make the text as visible as possible
+            treeView.scrollAreaToVisible(editBounds.x, editBounds.y,
+                textBounds.width + padding.left + 1, editBounds.height);
+
+            // Constrain the bounds by what is visible through Viewport ancestors
+            editBounds = treeView.getVisibleArea(editBounds.x, editBounds.y,
+                editBounds.width, editBounds.height);
+
+            textInput.setText(nodeData.getText());
+            textInput.setPreferredWidth(editBounds.width);
+            textInput.getComponentKeyListeners().add(textInputKeyHandler);
+
+            popup = new Window(textInput);
+            popup.getWindowStateListeners().add(popupStateHandler);
+
+            popup.setLocation(editBounds.x, editBounds.y
+                + (editBounds.height - textInput.getPreferredHeight(-1)) / 2);
+            popup.open(treeView.getWindow());
+
+            textInput.requestFocus();
+        }
+    }
+
+    public boolean isEditing() {
+        return (treeView != null);
+    }
+
+    @SuppressWarnings("unchecked")
+    public void save() {
+        if (!isEditing()) {
+            throw new IllegalStateException();
+        }
+
+        List<?> treeData = treeView.getTreeData();
+        TreeNode nodeData = (TreeNode)Sequence.Tree.get(treeData, path);
+
+        // Update the node data
+        String text = textInput.getText();
+        nodeData.setText(text);
+
+        // Notifying the parent will close the popup
+        int n = path.getLength();
+        if (n == 1) {
+            // Base case
+            int index = path.get(0);
+            ((List<TreeNode>)treeData).update(index, nodeData);
+        } else {
+            Sequence<Integer> parentPath = new ArrayList<Integer>(path, 0, n - 1);
+            TreeBranch parentData = (TreeBranch)Sequence.Tree.get(treeData, parentPath);
+            int index = path.get(n - 1);
+            parentData.update(index, nodeData);
+        }
+    }
+
+    public void cancel() {
+        if (!isEditing()) {
+            throw new IllegalStateException();
+        }
+
+        popup.close();
+    }
+}

Added: incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TreeViewNodeRenderer.java
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TreeViewNodeRenderer.java?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TreeViewNodeRenderer.java (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/TreeViewNodeRenderer.java Wed Mar 25 23:08:38 2009
@@ -0,0 +1,180 @@
+/*
+ * 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.Bounds;
+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, which knows how to render instances of
+ * {@link TreeNode} and {@link Image}. Anything else will be rendered as a
+ * string (by calling <tt>node.toString()</tt>.
+ *
+ * @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);
+    }
+
+    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 node, TreeView treeView, boolean expanded,
+        boolean selected, TreeView.NodeCheckState checkState,
+        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);
+    }
+
+    /**
+     * Gets the bounds of the text that is rendered by this renderer.
+     *
+     * @return
+     * The bounds of the rendered text, or <tt>null</tt> if this renderer did
+     * not render any text.
+     */
+    public Bounds getTextBounds() {
+        return (label.isVisible() ? label.getBounds() : null);
+    }
+}

Added: incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/folder.png
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/folder.png?rev=758461&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/folder.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/package.html
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/package.html?rev=758461&view=auto
==============================================================================
--- incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/package.html (added)
+++ incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/package.html Wed Mar 25 23:08:38 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/branches/1.1/wtk/src/pivot/wtk/content/page_white.png
URL: http://svn.apache.org/viewvc/incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/page_white.png?rev=758461&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/pivot/branches/1.1/wtk/src/pivot/wtk/content/page_white.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream