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 [21/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/TableViewHeader.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TableViewHeader.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TableViewHeader.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TableViewHeader.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk;
+
+import pivot.util.ListenerList;
+import pivot.wtk.content.TableViewHeaderDataRenderer;
+
+/**
+ * Component representing a table view header.
+ *
+ * @author gbrown
+ */
+public class TableViewHeader extends Component {
+    /**
+     * Table view header data renderer interface.
+     *
+     * @author gbrown
+     */
+    public interface DataRenderer extends Renderer {
+        public void render(Object data, TableViewHeader tableViewHeader, boolean highlighted);
+    }
+
+    /**
+     * Table view header skin interface. Table view header skins must
+     * implement this.
+     *
+     * @author gbrown
+     */
+    public interface Skin {
+        public int getHeaderAt(int x);
+        public Bounds getHeaderBounds(int index);
+    }
+
+    private static class TableViewHeaderListenerList extends ListenerList<TableViewHeaderListener>
+        implements TableViewHeaderListener {
+        public void tableViewChanged(TableViewHeader tableViewHeader,
+            TableView previousTableView) {
+            for (TableViewHeaderListener listener : this) {
+                listener.tableViewChanged(tableViewHeader, previousTableView);
+            }
+        }
+
+        public void dataRendererChanged(TableViewHeader tableViewHeader,
+            TableViewHeader.DataRenderer previousDataRenderer) {
+            for (TableViewHeaderListener listener : this) {
+                listener.dataRendererChanged(tableViewHeader, previousDataRenderer);
+            }
+        }
+    }
+
+    private static class TableViewHeaderPressListenerList extends ListenerList<TableViewHeaderPressListener>
+        implements TableViewHeaderPressListener {
+        public void headerPressed(TableViewHeader tableViewHeader, int index) {
+            for (TableViewHeaderPressListener listener : this) {
+                listener.headerPressed(tableViewHeader, index);
+            }
+        }
+    }
+
+    private TableView tableView = null;
+    private DataRenderer dataRenderer = null;
+
+    private TableViewHeaderListenerList tableViewHeaderListeners = new TableViewHeaderListenerList();
+    private TableViewHeaderPressListenerList tableViewHeaderPressListeners = new TableViewHeaderPressListenerList();
+
+    public TableViewHeader() {
+        this(null);
+    }
+
+    public TableViewHeader(TableView tableView) {
+        setDataRenderer(new TableViewHeaderDataRenderer());
+        installSkin(TableViewHeader.class);
+
+        setTableView(tableView);
+    }
+
+    @Override
+    protected void setSkin(pivot.wtk.Skin skin) {
+        if (!(skin instanceof TableViewHeader.Skin)) {
+            throw new IllegalArgumentException("Skin class must implement "
+                + TableViewHeader.Skin.class.getName());
+        }
+
+        super.setSkin(skin);
+    }
+
+    public TableView getTableView() {
+        return tableView;
+    }
+
+    public void setTableView(TableView tableView) {
+        TableView previousTableView = this.tableView;
+
+        if (previousTableView != tableView) {
+            this.tableView = tableView;
+            tableViewHeaderListeners.tableViewChanged(this, previousTableView);
+        }
+    }
+
+    public DataRenderer getDataRenderer() {
+        return dataRenderer;
+    }
+
+    public void setDataRenderer(DataRenderer dataRenderer) {
+        if (dataRenderer == null) {
+            throw new IllegalArgumentException("dataRenderer is null.");
+        }
+
+        DataRenderer previousDataRenderer = this.dataRenderer;
+        if (previousDataRenderer != dataRenderer) {
+            this.dataRenderer = dataRenderer;
+            tableViewHeaderListeners.dataRendererChanged(this, previousDataRenderer);
+        }
+    }
+
+    public void pressHeader(int index) {
+        tableViewHeaderPressListeners.headerPressed(this, index);
+    }
+
+    /**
+     * Returns the index of the header at a given location.
+     *
+     * @param x
+     * The x-coordinate of the header to identify.
+     *
+     * @return
+     * The column index, or <tt>-1</tt> if there is no column at the given
+     * x-coordinate.
+     */
+    public int getHeaderAt(int x) {
+        TableViewHeader.Skin tableViewHeaderSkin = (TableViewHeader.Skin)getSkin();
+        return tableViewHeaderSkin.getHeaderAt(x);
+    }
+
+    /**
+     * Returns the bounding area of a given header.
+     *
+     * @param index
+     * The index of the header.
+     *
+     * @return
+     * The bounding area of the header.
+     */
+    public Bounds getHeaderBounds(int index) {
+        TableViewHeader.Skin tableViewHeaderSkin = (TableViewHeader.Skin)getSkin();
+        return tableViewHeaderSkin.getHeaderBounds(index);
+    }
+
+    public ListenerList<TableViewHeaderListener> getTableViewHeaderListeners() {
+        return tableViewHeaderListeners;
+    }
+
+    public ListenerList<TableViewHeaderPressListener> getTableViewHeaderPressListeners() {
+        return tableViewHeaderPressListeners;
+    }
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TableViewHeaderListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TableViewHeaderListener.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TableViewHeaderListener.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TableViewHeaderListener.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,41 @@
+/*
+ * 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;
+
+/**
+ * Table view header listener interface.
+ *
+ * @author gbrown
+ */
+public interface TableViewHeaderListener {
+    /**
+     * Called when a table view header's table view has changed.
+     *
+     * @param tableViewHeader
+     * @param previousTableView
+     */
+    public void tableViewChanged(TableViewHeader tableViewHeader,
+        TableView previousTableView);
+
+    /**
+     * Called when a table view header's data renderer has changed.
+     *
+     * @param tableViewHeader
+     * @param previousDataRenderer
+     */
+    public void dataRendererChanged(TableViewHeader tableViewHeader,
+        TableViewHeader.DataRenderer previousDataRenderer);
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TableViewHeaderPressListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TableViewHeaderPressListener.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TableViewHeaderPressListener.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TableViewHeaderPressListener.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,31 @@
+/*
+ * 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;
+
+/**
+ * Table view header press listener.
+ *
+ * @author gbrown
+ */
+public interface TableViewHeaderPressListener {
+    /**
+     * Called when a table view header has been pressed.
+     *
+     * @param tableViewHeader
+     * @param index
+     */
+    public void headerPressed(TableViewHeader tableViewHeader, int index);
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TableViewListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TableViewListener.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TableViewListener.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TableViewListener.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk;
+
+import pivot.collections.List;
+
+/**
+ * Table view listener interface.
+ *
+ * @author gbrown
+ */
+public interface TableViewListener {
+    /**
+     * Called when a table view's table data has changed.
+     *
+     * @param tableView
+     * @param previousTableData
+     */
+    public void tableDataChanged(TableView tableView, List<?> previousTableData);
+
+    /**
+     * Called when a table view's select mode has changed.
+     *
+     * @param tableView
+     * @param previousSelectMode
+     */
+    public void selectModeChanged(TableView tableView, TableView.SelectMode previousSelectMode);
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TableViewRowListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TableViewRowListener.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TableViewRowListener.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TableViewRowListener.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,68 @@
+/*
+ * 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;
+
+/**
+ * Table view row listener interface.
+ *
+ * @author gbrown
+ */
+public interface TableViewRowListener {
+    /**
+     * Called when a row has been inserted into the table view.
+     *
+     * @param tableView
+     * The source of the event.
+     *
+     * @param index
+     * The index of the row that was inserted.
+     */
+    public void rowInserted(TableView tableView, int index);
+
+    /**
+     * Called when rows have been removed from the table view.
+     *
+     * @param tableView
+     * The source of the event.
+     *
+     * @param index
+     * The first index affected by the event.
+     *
+     * @param count
+     * The number of rows that were removed, or <tt>-1</tt> if all rows
+     * were removed.
+     */
+    public void rowsRemoved(TableView tableView, int index, int count);
+
+    /**
+     * Called when an row in the table view has been updated.
+     *
+     * @param tableView
+     * The source of the event.
+     *
+     * @param index
+     * The first index affected by the event.
+     */
+    public void rowUpdated(TableView tableView, int index);
+
+    /**
+     * Called when the rows in a table have been sorted.
+     *
+     * @param tableView
+     * The source of the event.
+     */
+    public void rowsSorted(TableView tableView);
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TableViewRowStateListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TableViewRowStateListener.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TableViewRowStateListener.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TableViewRowStateListener.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk;
+
+import pivot.util.Vote;
+
+/**
+ * Table view row state listener interface.
+ *
+ * @author gbrown
+ * @author tvolkert
+ */
+public interface TableViewRowStateListener {
+    /**
+     * Called to preview a row disabled change event.
+     *
+     * @param tableView
+     * @param index
+     */
+    public Vote previewRowDisabledChange(TableView tableView, int index);
+
+    /**
+     * Called when a row disabled change event has been vetoed.
+     *
+     * @param tableView
+     * @param index
+     * @param reason
+     */
+    public void rowDisabledChangeVetoed(TableView tableView, int index, Vote reason);
+
+    /**
+     * Called when a row's disabled state has changed.
+     *
+     * @param tableView
+     * @param index
+     */
+    public void rowDisabledChanged(TableView tableView, int index);
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TableViewSelectionDetailListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TableViewSelectionDetailListener.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TableViewSelectionDetailListener.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TableViewSelectionDetailListener.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk;
+
+import pivot.collections.Sequence;
+
+/**
+ * Table view selection detail listener interface.
+ *
+ * @author gbrown
+ */
+public interface TableViewSelectionDetailListener {
+    /**
+     * Called when a range has been added to a table view's selection.
+     *
+     * @param tableView
+     * @param rangeStart
+     * @param rangeEnd
+     */
+    public void selectedRangeAdded(TableView tableView, int rangeStart, int rangeEnd);
+
+    /**
+     * Called when a range has been removed from a table view's selection.
+     *
+     * @param tableView
+     * @param rangeStart
+     * @param rangeEnd
+     */
+    public void selectedRangeRemoved(TableView tableView, int rangeStart, int rangeEnd);
+
+    /**
+     * Called when a table view's selection state has been reset.
+     *
+     * @param tableView
+     * @param previousSelectedRanges
+     */
+    public void selectionReset(TableView tableView, Sequence<Span> previousSelectedRanges);
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TableViewSelectionListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TableViewSelectionListener.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TableViewSelectionListener.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TableViewSelectionListener.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk;
+
+/**
+ * Table view selection listener.
+ *
+ * @author gbrown
+ */
+public interface TableViewSelectionListener {
+    /**
+     * Called when a table view's selection state has changed.
+     *
+     * @param tableView
+     */
+    public void selectionChanged(TableView tableView);
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TaskAdapter.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TaskAdapter.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TaskAdapter.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TaskAdapter.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk;
+
+import pivot.util.concurrent.Task;
+import pivot.util.concurrent.TaskListener;
+
+/**
+ * Class that forwards task events to the UI thread.
+ *
+ * @author tvolkert
+ */
+public class TaskAdapter<T> implements TaskListener<T> {
+    /**
+     * Callback that gets posted to the UI thread when our task has been
+     * executed.
+     */
+    private class TaskExecutedCallback implements Runnable {
+        private Task<T> task;
+
+        public TaskExecutedCallback(Task<T> task) {
+            this.task = task;
+        }
+
+        public void run() {
+            taskListener.taskExecuted(task);
+        }
+    }
+
+    /**
+     * Callback that gets posted to the UI thread when our task execution has
+     * failed.
+     */
+    private class ExecuteFailedCallback implements Runnable {
+        private Task<T> task;
+
+        public ExecuteFailedCallback(Task<T> task) {
+            this.task = task;
+        }
+
+        public void run() {
+            taskListener.executeFailed(task);
+        }
+    }
+
+
+    // The TaskListener that we're adapting
+    private TaskListener<T> taskListener;
+
+
+    /**
+     * Creates a new <tt>TaskAdapter</tt> that wraps the specified task
+     * listener.
+     *
+     * @param taskListener
+     * The task listener that will be notified on the UI thread
+     */
+    public TaskAdapter(TaskListener<T> taskListener) {
+        if (taskListener == null) {
+            throw new IllegalArgumentException("taskListener cannot be null");
+        }
+
+        this.taskListener = taskListener;
+    }
+
+    // TaskListener methods
+
+    public void taskExecuted(Task<T> task) {
+        ApplicationContext.queueCallback(new TaskExecutedCallback(task));
+    }
+
+    public void executeFailed(Task<T> task) {
+        ApplicationContext.queueCallback(new ExecuteFailedCallback(task));
+    }
+}

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

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

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TextDecoration.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TextDecoration.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TextDecoration.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TextDecoration.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk;
+
+/**
+ * Enumeration representing text decoration styles.
+ *
+ * @author gbrown
+ */
+public enum TextDecoration {
+    UNDERLINE,
+    STRIKETHROUGH;
+
+    public static TextDecoration decode(String value) {
+        return valueOf(value.toUpperCase());
+    }
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TextInput.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TextInput.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TextInput.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TextInput.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,580 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk;
+
+import pivot.collections.Dictionary;
+import pivot.util.ListenerList;
+
+/**
+ * A component that allows a user to enter a single line of unformatted text.
+ *
+ * @author gbrown
+ */
+@ComponentInfo(icon="TextInput.png")
+public class TextInput extends Component {
+    /**
+     * Text input listener list.
+     *
+     * @author gbrown
+     */
+    private static class TextInputListenerList extends ListenerList<TextInputListener>
+        implements TextInputListener {
+        public void textKeyChanged(TextInput textInput, String previousTextKey) {
+            for (TextInputListener listener : this) {
+                listener.textKeyChanged(textInput, previousTextKey);
+            }
+        }
+
+        public void textSizeChanged(TextInput textInput, int previousTextSize) {
+            for (TextInputListener listener : this) {
+                listener.textSizeChanged(textInput, previousTextSize);
+            }
+        }
+
+        public void maximumLengthChanged(TextInput textInput, int previousMaximumLength) {
+            for (TextInputListener listener : this) {
+                listener.maximumLengthChanged(textInput, previousMaximumLength);
+            }
+        }
+
+        public void passwordChanged(TextInput textInput) {
+            for (TextInputListener listener : this) {
+                listener.passwordChanged(textInput);
+            }
+        }
+    }
+
+    /**
+     * Text input text listener list.
+     *
+     * @author gbrown
+     */
+    private static class TextInputTextListenerList extends ListenerList<TextInputTextListener>
+        implements TextInputTextListener {
+        public void textChanged(TextInput textInput) {
+            for (TextInputTextListener listener : this) {
+                listener.textChanged(textInput);
+            }
+        }
+    }
+
+    /**
+     * Text input character listener list.
+     *
+     * @author gbrown
+     */
+    private static class TextInputCharacterListenerList extends ListenerList<TextInputCharacterListener>
+        implements TextInputCharacterListener {
+        public void charactersInserted(TextInput textInput, int index, int count) {
+            for (TextInputCharacterListener listener : this) {
+                listener.charactersInserted(textInput, index, count);
+            }
+        }
+
+        public void charactersRemoved(TextInput textInput, int index, int count) {
+            for (TextInputCharacterListener listener : this) {
+                listener.charactersRemoved(textInput, index, count);
+            }
+        }
+
+        public void charactersReset(TextInput textInput) {
+            for (TextInputCharacterListener listener : this) {
+                listener.charactersReset(textInput);
+            }
+        }
+    }
+
+    /**
+     * Text input selection listener list.
+     *
+     * @author gbrown
+     */
+    private static class TextInputSelectionListenerList extends ListenerList<TextInputSelectionListener>
+        implements TextInputSelectionListener {
+        public void selectionChanged(TextInput textInput,
+            int previousSelectionStart, int previousSelectionEnd) {
+            for (TextInputSelectionListener listener : this) {
+                listener.selectionChanged(textInput,
+                    previousSelectionStart, previousSelectionEnd);
+            }
+        }
+    }
+
+    private StringBuilder textBuilder = new StringBuilder();
+    private int selectionStart = 0;
+    private int selectionLength = 0;
+    private int textSize = DEFAULT_TEXT_SIZE;
+    private int maximumLength = Integer.MAX_VALUE;
+    private boolean password = false;
+    private String textKey = null;
+
+    private TextInputListenerList textInputListeners = new TextInputListenerList();
+    private TextInputTextListenerList textInputTextListeners = new TextInputTextListenerList();
+    private TextInputCharacterListenerList textInputCharacterListeners = new TextInputCharacterListenerList();
+    private TextInputSelectionListenerList textInputSelectionListeners = new TextInputSelectionListenerList();
+
+    private static final int DEFAULT_TEXT_SIZE = 20;
+
+    /**
+     * Creates a text input that is initially empty.
+     */
+    public TextInput() {
+        this("");
+    }
+
+    /**
+     * Creates a text input that is initialized with the given text.
+     *
+     * @param text
+     * The initial text content of the text input.
+     */
+    public TextInput(String text) {
+        setText(text);
+        installSkin(TextInput.class);
+    }
+
+    /**
+     * Returns the text content of the text input.
+     *
+     * @return
+     * A new string containing a copy of the text input's content.
+     */
+    public String getText() {
+        return textBuilder.toString();
+    }
+
+    /**
+     * Sets the text content of the text input. Clears any existing selection.
+     *
+     * param text
+     * The new content of the text input.
+     */
+    public void setText(String text) {
+        if (text == null) {
+            throw new IllegalArgumentException("text is null.");
+        }
+
+        if (text.length() > maximumLength) {
+            throw new IllegalArgumentException("text length is greater than maximum length.");
+        }
+
+        setSelection(0, 0);
+
+        textBuilder = new StringBuilder(text);
+
+        textInputCharacterListeners.charactersReset(this);
+        textInputTextListeners.textChanged(this);
+    }
+
+    /**
+     * Inserts a single character into the text input's content.
+     *
+     * @param character
+     * The character to insert.
+     *
+     * @param index
+     * The index of the insertion point within the existing text. If equal to
+     * the current character count, the new text is appended to the existing
+     * content.
+     */
+    public void insertText(char character, int index) {
+        insertText(Character.toString(character), index);
+    }
+
+    /**
+     * Inserts text into the text input's content.
+     *
+     * @param text
+     * The text to insert.
+     *
+     * @param index
+     * The index of the insertion point within the existing text. If equal to
+     * the current character count, the new text is appended to the existing
+     * content.
+     */
+    public void insertText(String text, int index) {
+        if (index < 0
+            || index > textBuilder.length()) {
+            throw new IndexOutOfBoundsException();
+        }
+
+        if (textBuilder.length() + text.length() > maximumLength) {
+            throw new IllegalArgumentException("Insertion of text would exceed maximum length.");
+        }
+
+        // Insert the text
+        textBuilder.insert(index, text);
+
+        // Update the selection
+        int previousSelectionStart = this.selectionStart;
+        int previousSelectionLength = this.selectionLength;
+
+        int count = text.length();
+
+        if (selectionStart + selectionLength >= index) {
+            if (selectionStart >= index) {
+                selectionStart += count;
+            } else {
+                selectionLength += count;
+            }
+        }
+
+        // Notify listeners
+        textInputCharacterListeners.charactersInserted(this, index, count);
+        textInputTextListeners.textChanged(this);
+
+        if (previousSelectionStart != selectionStart
+            || previousSelectionLength != selectionLength) {
+            textInputSelectionListeners.selectionChanged(this,
+                previousSelectionStart, previousSelectionLength);
+        }
+    }
+
+    /**
+     * Removes a range of characters from the text input's content.
+     *
+     * @param index
+     * The index of the first character to remove.
+     *
+     * @param count
+     * The number of characters to remove.
+     *
+     * @return
+     * A string containing the text that was removed.
+     */
+    public String removeText(int index, int count) {
+        if (index < 0
+            || index + count > textBuilder.length()) {
+            throw new IndexOutOfBoundsException();
+        }
+
+        // Determine the range of indexes to remove; the interval is defined
+        // as [start, end)
+        int start = index;
+        int end = index + count;
+
+        String text = textBuilder.substring(start, end);
+        textBuilder.delete(start, end);
+
+        // Update selection
+        int previousSelectionStart = this.selectionStart;
+        int previousSelectionLength = this.selectionLength;
+
+        // The selection interval is defined as [selectionStart, selectionEnd]
+        int selectionEnd = selectionStart + selectionLength - 1;
+
+        if (selectionEnd >= start) {
+            selectionStart = Math.min(start, selectionStart);
+            selectionEnd = Math.max(end - 1, selectionEnd) - count;
+
+            selectionLength = selectionEnd - selectionStart + 1;
+        }
+
+        textInputCharacterListeners.charactersRemoved(this, index, count);
+        textInputTextListeners.textChanged(this);
+
+        if (previousSelectionStart != selectionStart
+            || previousSelectionLength != selectionLength) {
+            textInputSelectionListeners.selectionChanged(this,
+                previousSelectionStart, previousSelectionLength);
+        }
+
+        return text;
+    }
+
+    /**
+     * Returns the character at the given index.
+     *
+     * @param index
+     * The index of the character to return.
+     *
+     * @return
+     * The character at the given index.
+     */
+    public char getCharacter(int index) {
+        if (index < 0
+            || index >= textBuilder.length()) {
+            throw new IndexOutOfBoundsException();
+        }
+
+        return textBuilder.charAt(index);
+    }
+
+    /**
+     * Returns the total number of characters in the text input's text
+     * content.
+     *
+     * @return
+     * The length of the text input's content.
+     */
+    public int getCharacterCount() {
+        return textBuilder.length();
+    }
+
+    /**
+     * Returns the starting index of the selection.
+     *
+     * @return
+     * The starting index of the selection.
+     */
+    public int getSelectionStart() {
+        return selectionStart;
+    }
+
+    /**
+     * Returns the length of the selection.
+     *
+     * @return
+     * The length of the selection; may be <tt>0</tt>.
+     */
+    public int getSelectionLength() {
+        return selectionLength;
+    }
+
+    /**
+     * Sets the selection. The sum of the selection start and length must be
+     * less than the length of the text input's content.
+     *
+     * @param selectionStart
+     * The starting index of the selection.
+     *
+     * @param selectionLength
+     * The length of the selection.
+     */
+    public void setSelection(int selectionStart, int selectionLength) {
+        if (selectionStart < 0
+            || selectionStart + selectionLength > textBuilder.length()) {
+            throw new IndexOutOfBoundsException();
+        }
+
+        int previousSelectionStart = this.selectionStart;
+        int previousSelectionLength = this.selectionLength;
+
+        if (previousSelectionStart != selectionStart
+            || previousSelectionLength != selectionLength) {
+            this.selectionStart = selectionStart;
+            this.selectionLength = selectionLength;
+
+            textInputSelectionListeners.selectionChanged(this,
+                previousSelectionStart, previousSelectionLength);
+        }
+    }
+
+    /**
+     * Returns a span representing the current selection.
+     *
+     * @return
+     * A span containing the current selection. Both start and end points are
+     * inclusive. Returns <tt>null</tt> if the selection is empty.
+     */
+    public Span getSelectionRange() {
+        return (selectionLength == 0) ? null : new Span(selectionStart,
+            selectionStart + selectionLength - 1);
+    }
+
+    /**
+     * Returns the currently selected text.
+     *
+     * @return
+     * A new string containing a copy of the text in the selected range, or
+     * <tt>null</tt> if nothing is selected.
+     */
+    public String getSelectedText() {
+        String selectedText = null;
+
+        if (selectionLength > 0) {
+            selectedText = textBuilder.substring(selectionStart,
+                selectionStart + selectionLength);
+        }
+
+        return selectedText;
+    }
+
+    /**
+     * Returns the text size.
+     *
+     * @return
+     * The number of characters to display in the text input.
+     */
+    public int getTextSize() {
+        return textSize;
+    }
+
+    /**
+     * Sets the text size.
+     *
+     * @param textSize
+     * The number of characters to display in the text input.
+     */
+    public void setTextSize(int textSize) {
+        if (textSize < 0) {
+            throw new IllegalArgumentException("textSize is negative.");
+        }
+
+        int previousTextSize = this.textSize;
+
+        if (previousTextSize != textSize) {
+            this.textSize = textSize;
+            textInputListeners.textSizeChanged(this, previousTextSize);
+        }
+    }
+
+    /**
+     * Returns the maximum length of the text input's text content.
+     *
+     * @return
+     * The maximum length of the text input's text content.
+     */
+    public int getMaximumLength() {
+        return maximumLength;
+    }
+
+    /**
+     * Sets the maximum length of the text input's text content.
+     *
+     * @param maximumLength
+     * The maximum length of the text input's text content.
+     */
+    public void setMaximumLength(int maximumLength) {
+        if (maximumLength < 0) {
+            throw new IllegalArgumentException("maximumLength is negative.");
+        }
+
+        int previousMaximumLength = this.maximumLength;
+
+        if (previousMaximumLength != maximumLength) {
+            // Truncate the text, if necessary
+            if (textBuilder.length() > maximumLength) {
+                removeText(maximumLength, textBuilder.length() - maximumLength);
+            }
+
+            this.maximumLength = maximumLength;
+            textInputListeners.maximumLengthChanged(this, previousMaximumLength);
+        }
+    }
+
+    /**
+     * Returns the password flag.
+     *
+     * @return
+     * <tt>true</tt> if this is a password text input; <tt>false</tt>,
+     * otherwise.
+     */
+    public boolean isPassword() {
+        return password;
+    }
+
+    /**
+     * Sets or clears the password flag. If the password flag is set, the text
+     * input will visually mask its contents.
+     *
+     * @param password
+     * <tt>true</tt> if this is a password text input; <tt>false</tt>,
+     * otherwise.
+     */
+    public void setPassword(boolean password) {
+        if (this.password != password) {
+            this.password = password;
+            textInputListeners.passwordChanged(this);
+        }
+    }
+
+    /**
+     * Returns the text input's text key.
+     *
+     * @return
+     * The text key, or <tt>null</tt> if no text key is set.
+     */
+    public String getTextKey() {
+        return textKey;
+    }
+
+    /**
+     * Sets the text input's text key.
+     *
+     * @param textKey
+     * The text key, or <tt>null</tt> to clear the binding.
+     */
+    public void setTextKey(String textKey) {
+        String previousTextKey = this.textKey;
+
+        if ((previousTextKey != null
+            && textKey != null
+            && !previousTextKey.equals(textKey))
+            || previousTextKey != textKey) {
+            this.textKey = textKey;
+            textInputListeners.textKeyChanged(this, previousTextKey);
+        }
+    }
+
+    @Override
+    public void load(Dictionary<String, Object> context) {
+        if (textKey != null
+            && context.containsKey(textKey)) {
+            Object value = context.get(textKey);
+            if (value != null) {
+                setText(value.toString());
+            }
+        }
+    }
+
+    @Override
+    public void store(Dictionary<String, Object> context) {
+        if (textKey != null) {
+            context.put(textKey, getText());
+        }
+    }
+
+    /**
+     * Returns the text input listener list.
+     *
+     * @return
+     * The text input listener list.
+     */
+    public ListenerList<TextInputListener> getTextInputListeners() {
+        return textInputListeners;
+    }
+
+    /**
+     * Returns the text input text listener list.
+     *
+     * @return
+     * The text input text listener list.
+     */
+    public ListenerList<TextInputTextListener> getTextInputTextListeners() {
+        return textInputTextListeners;
+    }
+
+    /**
+     * Returns the text input selection listener list.
+     *
+     * @return
+     * The text input selection listener list.
+     */
+    public ListenerList<TextInputSelectionListener> getTextInputSelectionListeners() {
+        return textInputSelectionListeners;
+    }
+
+    /**
+     * Returns the text input character listener list.
+     *
+     * @return
+     * The text input character listener list.
+     */
+    public ListenerList<TextInputCharacterListener> getTextInputCharacterListeners() {
+        return textInputCharacterListeners;
+    }
+}

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

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

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TextInputCharacterListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TextInputCharacterListener.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TextInputCharacterListener.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TextInputCharacterListener.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;
+
+/**
+ * Text input character listener interface.
+ *
+ * @author gbrown
+ */
+public interface TextInputCharacterListener {
+    /**
+     * Called when characters have been inserted into a text input.
+     *
+     * @param textInput
+     * @param index
+     * @param count
+     */
+    public void charactersInserted(TextInput textInput, int index, int count);
+
+    /**
+     * Called when characters have been removed from a text input.
+     *
+     * @param textInput
+     * @param index
+     * @param count
+     */
+    public void charactersRemoved(TextInput textInput, int index, int count);
+
+    /**
+     * Called when a text input's character state has been reset.
+     *
+     * @param textInput
+     */
+    public void charactersReset(TextInput textInput);
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TextInputListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TextInputListener.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TextInputListener.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TextInputListener.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,54 @@
+/*
+ * 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;
+
+/**
+ * Text input listener interface.
+ *
+ * @author gbrown
+ */
+public interface TextInputListener {
+    /**
+     * Called when a text input's text key has changed.
+     *
+     * @param textInput
+     * @param previousTextKey
+     */
+    public void textKeyChanged(TextInput textInput, String previousTextKey);
+
+    /**
+     * Called when a text input's text size has changed.
+     *
+     * @param textInput
+     * @param previousTextSize
+     */
+    public void textSizeChanged(TextInput textInput, int previousTextSize);
+
+    /**
+     * Called when a text input's maximum length has changed.
+     *
+     * @param textInput
+     * @param previousMaximumLength
+     */
+    public void maximumLengthChanged(TextInput textInput, int previousMaximumLength);
+
+    /**
+     * Called when a text input's password flag has changed.
+     *
+     * @param textInput
+     */
+    public void passwordChanged(TextInput textInput);
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TextInputSelectionListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TextInputSelectionListener.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TextInputSelectionListener.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TextInputSelectionListener.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,33 @@
+/*
+ * 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;
+
+/**
+ * Text input selection listener interface.
+ *
+ * @author gbrown
+ */
+public interface TextInputSelectionListener {
+    /**
+     * Called when a text input's selection state has changed.
+     *
+     * @param textInput
+     * @param previousSelectionStart
+     * @param previousSelectionLength
+     */
+    public void selectionChanged(TextInput textInput,
+        int previousSelectionStart, int previousSelectionLength);
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TextInputTextListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TextInputTextListener.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TextInputTextListener.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TextInputTextListener.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk;
+
+/**
+ * Text input text listener.
+ *
+ * @author gbrown
+ */
+public interface TextInputTextListener {
+    /**
+     * Called when a text input's text has changed.
+     *
+     * @param textInput
+     */
+    public void textChanged(TextInput textInput);
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/Theme.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/Theme.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/Theme.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/Theme.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk;
+
+import java.awt.Font;
+import java.lang.reflect.Modifier;
+
+import pivot.collections.ArrayList;
+import pivot.collections.HashMap;
+import pivot.wtk.skin.BorderSkin;
+import pivot.wtk.skin.CardPaneSkin;
+import pivot.wtk.skin.FlowPaneSkin;
+import pivot.wtk.skin.ImageViewSkin;
+import pivot.wtk.skin.LabelSkin;
+import pivot.wtk.skin.PopupSkin;
+import pivot.wtk.skin.ScrollPaneSkin;
+import pivot.wtk.skin.SeparatorSkin;
+import pivot.wtk.skin.StackPaneSkin;
+import pivot.wtk.skin.TablePaneSkin;
+import pivot.wtk.skin.WindowSkin;
+
+/**
+ * Base class for Pivot themes. A theme defines a complete "look and feel"
+ * for a Pivot application.
+ * <p>
+ * Note that concrete Theme implementations should be declared as final. If
+ * multiple third-party libraries attempted to extend a theme, it would cause a
+ * conflict, as only one could be used in any given application.
+ * <p>
+ * IMPORTANT All skin mappings must be added to the map, even non-static inner
+ * classes. Otherwise, the component's base class will attempt to install its
+ * own skin, which will result in the addition of duplicate listeners.
+ */
+public abstract class Theme {
+    protected HashMap<Class<? extends Component>, Class<? extends Skin>> componentSkinMap =
+        new HashMap<Class<? extends Component>, Class<? extends Skin>>();
+
+    private static Theme theme = null;
+    private static final Package DEFAULT_SKIN_PACKAGE;
+
+    static {
+        DEFAULT_SKIN_PACKAGE = Package.getPackage("pivot.wtk.skin");
+        assert (DEFAULT_SKIN_PACKAGE != null) : "Default skin package not found.";
+    }
+
+    public Theme() {
+        componentSkinMap.put(Border.class, BorderSkin.class);
+        componentSkinMap.put(CardPane.class, CardPaneSkin.class);
+        componentSkinMap.put(FlowPane.class, FlowPaneSkin.class);
+        componentSkinMap.put(ImageView.class, ImageViewSkin.class);
+        componentSkinMap.put(Label.class, LabelSkin.class);
+        componentSkinMap.put(Popup.class, PopupSkin.class);
+        componentSkinMap.put(ScrollPane.class, ScrollPaneSkin.class);
+        componentSkinMap.put(Separator.class, SeparatorSkin.class);
+        componentSkinMap.put(StackPane.class, StackPaneSkin.class);
+        componentSkinMap.put(TablePane.class, TablePaneSkin.class);
+        componentSkinMap.put(Window.class, WindowSkin.class);
+    }
+
+    public final Class<? extends Skin> getSkinClass(Class<? extends Component> componentClass) {
+        return componentSkinMap.get(componentClass);
+    }
+
+    public abstract void install();
+    public abstract void uninstall();
+
+    public abstract Font getFont();
+
+    public static Theme getTheme() {
+        if (theme == null) {
+            throw new IllegalStateException("No installed theme.");
+        }
+
+        return theme;
+    }
+
+    public static void setTheme(Theme theme) {
+        if (theme == null) {
+            throw new IllegalArgumentException("theme is null.");
+        }
+
+        Theme previousTheme = Theme.theme;
+        if (previousTheme != null) {
+            previousTheme.uninstall();
+        }
+
+        theme.install();
+        Theme.theme = theme;
+
+        if (previousTheme != null) {
+            Component.ComponentDictionary components = Component.getComponents();
+            ArrayList<Integer> componentHandles = new ArrayList<Integer>();
+
+            for (Integer handle : components) {
+                componentHandles.add(handle);
+            }
+
+            for (Integer handle : componentHandles) {
+                Component component = components.get(handle);
+                Class<? extends Component> componentClass =
+                    (Class<? extends Component>)component.getClass();
+
+                if (theme.componentSkinMap.containsKey(componentClass)
+                    && (componentClass.getEnclosingClass() == null
+                        || (componentClass.getModifiers() & Modifier.STATIC) == Modifier.STATIC)) {
+                    component.installSkin(componentClass);
+                }
+            }
+        }
+    }
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/Tooltip.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/Tooltip.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/Tooltip.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/Tooltip.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;
+
+import pivot.util.ListenerList;
+
+/**
+ * Window representing a "tooltip". Tooltips are used to provide additional
+ * context information to a user. A tooltip generally appears after a certain
+ * amount of time has passed and closes when the user moves the mouse.
+ *
+ * @author gbrown
+ */
+public class Tooltip extends Window {
+    private static class TooltipListenerList extends ListenerList<TooltipListener>
+        implements TooltipListener {
+        public void textChanged(Tooltip tooltip, String previousText) {
+            for (TooltipListener listener : this) {
+                listener.textChanged(tooltip, previousText);
+            }
+        }
+    }
+
+    private String text = null;
+
+    private TooltipListenerList tooltipListeners = new TooltipListenerList();
+
+    public Tooltip(String text) {
+        setText(text);
+        installSkin(Tooltip.class);
+    }
+
+    public String getText() {
+        return text;
+    }
+
+    public void setText(String text) {
+        String previousText = this.text;
+
+        if (previousText != text) {
+            this.text = text;
+            tooltipListeners.textChanged(this, previousText);
+        }
+    }
+
+    /**
+     * @return
+     * <tt>true</tt>; by default, tooltips are auxilliary windows.
+     */
+    @Override
+    public boolean isAuxilliary() {
+        return true;
+    }
+
+    public ListenerList<TooltipListener> getTooltipListeners() {
+        return tooltipListeners;
+    }
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TooltipListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TooltipListener.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TooltipListener.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TooltipListener.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,31 @@
+/*
+ * 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;
+
+/**
+ * Tooltip listener interface.
+ *
+ * @author gbrown
+ */
+public interface TooltipListener {
+    /**
+     * Called when a tooltip's text property has changed.
+     *
+     * @param tooltip
+     * @param previousText
+     */
+    public void textChanged(Tooltip tooltip, String previousText);
+}

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TreeView.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TreeView.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TreeView.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TreeView.java Mon Mar 16 16:16:40 2009
@@ -0,0 +1,844 @@
+/*
+ * Copyright (c) 2008 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pivot.wtk;
+
+import java.util.Comparator;
+
+import pivot.collections.ArrayList;
+import pivot.collections.List;
+import pivot.collections.ListListener;
+import pivot.collections.Sequence;
+import pivot.util.ListenerList;
+import pivot.util.Vote;
+import pivot.wtk.content.TreeViewNodeRenderer;
+
+/**
+ * Class that displays a hierarchical data structure, allowing a user to select
+ * one or more paths.
+ * <p>
+ * TODO Add is/setNodeChecked(); is/setNodeDisabled() methods; add events to
+ * TreeViewNodeListener
+ *
+ * @author gbrown
+ * @author tvolkert
+ */
+@ComponentInfo(icon="TreeView.png")
+public class TreeView extends Component {
+    /**
+     * Enumeration defining supported selection modes.
+     */
+    public enum SelectMode {
+        /**
+         * Selection is disabled.
+         */
+        NONE,
+
+        /**
+         * A single path may be selected at a time.
+         */
+        SINGLE,
+
+        /**
+         * Multiple paths may be concurrently selected.
+         */
+        MULTI;
+
+        public static SelectMode decode(String value) {
+            return valueOf(value.toUpperCase());
+        }
+    }
+
+    /**
+     * Enumeration defining node check states.
+     */
+    public enum NodeCheckState {
+        /**
+         * The node is checked, meaning that all of its descendants are
+         * also checked.
+         */
+        CHECKED,
+
+        /**
+         * The node is unchecked, meaning that all of its descendants are also
+         * unchecked.
+         */
+        UNCHECKED,
+
+        /**
+         * The node's check state is mixed, meaning that some of its
+         * descendants are checked and some are not.
+         */
+        MIXED;
+
+        public static NodeCheckState decode(String value) {
+            return valueOf(value.toUpperCase());
+        }
+    }
+
+    /**
+     * Tree view node renderer interface.
+     *
+     * @author tvolkert
+     */
+    public interface NodeRenderer extends Renderer {
+        public void render(Object node, TreeView treeView, boolean expanded,
+            boolean selected, boolean highlighted, boolean disabled);
+    }
+
+    /**
+     * Tree view skin interface. Tree view skins must implement this.
+     *
+     * @author tvolkert
+     */
+    public interface Skin {
+        public Sequence<Integer> getNodeAt(int y);
+        public Bounds getNodeBounds(Sequence<Integer> path);
+        public int getNodeOffset(Sequence<Integer> path);
+    }
+
+    /**
+     * Tree view listener list.
+     *
+     * @author tvolkert
+     */
+    private static class TreeViewListenerList extends ListenerList<TreeViewListener>
+        implements TreeViewListener {
+
+        public void treeDataChanged(TreeView treeView, List<?> previousTreeData) {
+            for (TreeViewListener listener : this) {
+                listener.treeDataChanged(treeView, previousTreeData);
+            }
+        }
+
+        public void nodeRendererChanged(TreeView treeView,
+            NodeRenderer previousNodeRenderer) {
+            for (TreeViewListener listener : this) {
+                listener.nodeRendererChanged(treeView, previousNodeRenderer);
+            }
+        }
+
+        public void selectModeChanged(TreeView treeView, SelectMode previousSelectMode) {
+            for (TreeViewListener listener : this) {
+                listener.selectModeChanged(treeView, previousSelectMode);
+            }
+        }
+
+        public void checkEnabledChanged(TreeView treeView) {
+            for (TreeViewListener listener : this) {
+                listener.checkEnabledChanged(treeView);
+            }
+        }
+    }
+
+    /**
+     * Tree view branch listener list.
+     *
+     * @author tvolkert
+     */
+    private static class TreeViewBranchListenerList extends ListenerList<TreeViewBranchListener>
+        implements TreeViewBranchListener {
+        public void branchExpanded(TreeView treeView, Sequence<Integer> path) {
+            for (TreeViewBranchListener listener : this) {
+                listener.branchExpanded(treeView, path);
+            }
+        }
+
+        public void branchCollapsed(TreeView treeView, Sequence<Integer> path) {
+            for (TreeViewBranchListener listener : this) {
+                listener.branchCollapsed(treeView, path);
+            }
+        }
+    }
+
+    /**
+     * Tree view node listener list.
+     *
+     * @author tvolkert
+     */
+    private static class TreeViewNodeListenerList extends ListenerList<TreeViewNodeListener>
+        implements TreeViewNodeListener {
+        public void nodeInserted(TreeView treeView, Sequence<Integer> path, int index) {
+            for (TreeViewNodeListener listener : this) {
+                listener.nodeInserted(treeView, path, index);
+            }
+        }
+
+        public void nodesRemoved(TreeView treeView, Sequence<Integer> path, int index,
+            int count) {
+            for (TreeViewNodeListener listener : this) {
+                listener.nodesRemoved(treeView, path, index, count);
+            }
+        }
+
+        public void nodeUpdated(TreeView treeView, Sequence<Integer> path, int index) {
+            for (TreeViewNodeListener listener : this) {
+                listener.nodeUpdated(treeView, path, index);
+            }
+        }
+
+        public void nodesSorted(TreeView treeView, Sequence<Integer> path) {
+            for (TreeViewNodeListener listener : this) {
+                listener.nodesSorted(treeView, path);
+            }
+        }
+    }
+
+    /**
+     * Tree view node state listener list.
+     *
+     * @author tvolkert
+     */
+    private static class TreeViewNodeStateListenerList
+        extends ListenerList<TreeViewNodeStateListener>
+        implements TreeViewNodeStateListener {
+        public Vote previewNodeDisabledChange(TreeView treeView, Sequence<Integer> path) {
+            Vote vote = Vote.APPROVE;
+
+            for (TreeViewNodeStateListener listener : this) {
+                vote = vote.tally(listener.previewNodeDisabledChange(treeView, path));
+            }
+
+            return vote;
+        }
+
+        public void nodeDisabledChangeVetoed(TreeView treeView, Sequence<Integer> path, Vote reason) {
+            for (TreeViewNodeStateListener listener : this) {
+                listener.nodeDisabledChangeVetoed(treeView, path, reason);
+            }
+        }
+
+        public void nodeDisabledChanged(TreeView treeView, Sequence<Integer> path) {
+            for (TreeViewNodeStateListener listener : this) {
+                listener.nodeDisabledChanged(treeView, path);
+            }
+        }
+    }
+
+    /**
+     * Tree view selection listener list.
+     *
+     * @author tvolkert
+     */
+    private static class TreeViewSelectionListenerList
+        extends ListenerList<TreeViewSelectionListener>
+        implements TreeViewSelectionListener {
+        public void selectionChanged(TreeView treeView) {
+            for (TreeViewSelectionListener listener : this) {
+                listener.selectionChanged(treeView);
+            }
+        }
+    }
+
+    /**
+     * Tree view selection detail listener list.
+     *
+     * @author tvolkert
+     */
+    private static class TreeViewSelectionDetailListenerList
+        extends ListenerList<TreeViewSelectionDetailListener>
+        implements TreeViewSelectionDetailListener {
+        public void selectedPathAdded(TreeView treeView, Sequence<Integer> path) {
+            for (TreeViewSelectionDetailListener listener : this) {
+                listener.selectedPathAdded(treeView, path);
+            }
+        }
+
+        public void selectedPathRemoved(TreeView treeView, Sequence<Integer> path) {
+            for (TreeViewSelectionDetailListener listener : this) {
+                listener.selectedPathRemoved(treeView, path);
+            }
+        }
+
+        public void selectionReset(TreeView treeView,
+            Sequence<Sequence<Integer>> previousSelectedPaths) {
+            for (TreeViewSelectionDetailListener listener : this) {
+                listener.selectionReset(treeView, previousSelectedPaths);
+            }
+        }
+    }
+
+    /**
+     * A comparator that sorts paths by the order in which they would visually
+     * appear in a fully expanded tree.
+     *
+     * @author tvolkert
+     */
+    private static class TreeViewPathComparator
+        implements Comparator<Sequence<Integer>> {
+        public int compare(Sequence<Integer> path1, Sequence<Integer> path2) {
+            int path1Length = path1.getLength();
+            int path2Length = path2.getLength();
+
+            for (int i = 0, n = Math.min(path1Length, path2Length); i < n; i++) {
+                int pathElement1 = path1.get(i);
+                int pathElement2 = path2.get(i);
+
+                if (pathElement1 != pathElement2) {
+                    return pathElement1 - pathElement2;
+                }
+            }
+
+            return path1Length - path2Length;
+        }
+    }
+
+    /**
+     * Nested class that tracks node check state and notifies the tree of
+     * nested <tt>ListListener</tt> events that occur on the tree data.
+     *
+     * @author tvolkert
+     */
+    private class BranchInfo implements ListListener<Object> {
+        private BranchInfo parent;
+        private List<BranchInfo> childBranches = new ArrayList<BranchInfo>();
+        private List<?> branchData;
+        // TODO Add check state data structure
+
+        @SuppressWarnings("unchecked")
+        public BranchInfo(BranchInfo parent, List<?> branchData) {
+            this.parent = parent;
+            this.branchData = branchData;
+
+            ((List<Object>)branchData).getListListeners().add(this);
+
+            for (int i = 0, n = branchData.getLength(); i < n; i++) {
+                Object childData = branchData.get(i);
+
+                BranchInfo branchInfo = null;
+
+                if (childData instanceof List) {
+                    branchInfo = new BranchInfo(this, (List<?>)childData);
+                }
+
+                childBranches.add(branchInfo);
+            }
+        }
+
+        @SuppressWarnings("unchecked")
+        public Sequence<Integer> getPath() {
+            Sequence<Integer> path = new ArrayList<Integer>();
+
+            BranchInfo branch = this;
+
+            while (branch.parent != null) {
+                int index = ((List<Object>)branch.parent.branchData).indexOf(branch.branchData);
+                path.insert(index, 0);
+
+                branch = branch.parent;
+            }
+
+            return path;
+        }
+
+        public Object getBranchData(int index) {
+            return branchData.get(index);
+        }
+
+        /**
+         * Unregisters this branch info's interest in ListListener events. This
+         * must be done to release references from the tree data to our
+         * internal BranchInfo data structures. Failure to do so would mean
+         * that our BranchInfo objects would remain in scope as long as the
+         * tree data remained in scope, even if  we were no longer using the
+         * BranchInfo objects.
+         */
+        @SuppressWarnings("unchecked")
+        private void unregisterListListeners() {
+            ((List<Object>)branchData).getListListeners().remove(this);
+
+            // Recursively have all child branches unregister interest
+            for (int i = 0, n = childBranches.getLength(); i < n; i++) {
+                BranchInfo branchInfo = childBranches.get(i);
+                if (branchInfo != null) {
+                    branchInfo.unregisterListListeners();
+                }
+            }
+        }
+
+        public void comparatorChanged(List<Object> list,
+            Comparator<Object> previousComparator) {
+            // TODO Remove selected child nodes
+
+            treeViewNodeListeners.nodesSorted(TreeView.this, getPath());
+        }
+
+        @SuppressWarnings("unchecked")
+        public void itemInserted(List<Object> list, int index) {
+            Object childData = list.get(index);
+
+            BranchInfo branchInfo = null;
+
+            if (childData instanceof List) {
+                branchInfo = new BranchInfo(this, (List<Object>)childData);
+            }
+
+            childBranches.insert(branchInfo, index);
+
+            insertNode(getPath(), index);
+        }
+
+        public void itemsRemoved(List<Object> list, int index, Sequence<Object> items) {
+            assert(index == 0 || items != null) : "";
+
+            int n = (items == null) ? childBranches.getLength() : items.getLength();
+            for (int i = 0; i < n; i++) {
+                BranchInfo branchInfo = childBranches.update(index + i, null);
+
+                if (branchInfo != null) {
+                    branchInfo.unregisterListListeners();
+                }
+            }
+
+            removeNodes(getPath(), index, (items == null) ? -1 : items.getLength());
+        }
+
+        public void itemUpdated(List<Object> list, int index, Object previousItem) {
+            invalidateNode(getPath(), index);
+        }
+    }
+
+    private static final Comparator<Sequence<Integer>> PATH_COMPARATOR =
+        new TreeViewPathComparator();
+
+    /**
+     * Tree data.
+     */
+    private List<?> treeData = null;
+
+    private List<Sequence<Integer>> expandedPaths =
+        new ArrayList<Sequence<Integer>>(PATH_COMPARATOR);
+    private List<Sequence<Integer>> selectedPaths =
+        new ArrayList<Sequence<Integer>>(PATH_COMPARATOR);
+    private List<Sequence<Integer>> disabledPaths =
+        new ArrayList<Sequence<Integer>>(PATH_COMPARATOR);
+
+    private SelectMode selectMode = SelectMode.SINGLE;
+    private boolean checkEnabled = false;
+
+    private BranchInfo rootBranchInfo;
+
+    private NodeRenderer nodeRenderer = DEFAULT_NODE_RENDERER;
+
+    private TreeViewListenerList treeViewListeners = new TreeViewListenerList();
+    private TreeViewBranchListenerList treeViewBranchListeners =
+        new TreeViewBranchListenerList();
+    private TreeViewNodeListenerList treeViewNodeListeners =
+        new TreeViewNodeListenerList();
+    private TreeViewNodeStateListenerList treeViewNodeStateListeners =
+        new TreeViewNodeStateListenerList();
+    private TreeViewSelectionListenerList treeViewSelectionListeners =
+        new TreeViewSelectionListenerList();
+    private TreeViewSelectionDetailListenerList treeViewSelectionDetailListeners =
+        new TreeViewSelectionDetailListenerList();
+
+    private static final NodeRenderer DEFAULT_NODE_RENDERER = new TreeViewNodeRenderer();
+
+    public TreeView() {
+        this(new ArrayList<Object>());
+    }
+
+    /**
+     * TreeView constructor.
+     *
+     * @param treeData
+     * Default data set to be used with the tree. This list represents the root
+     * set of items displayed by the tree. Sub-items that also implement the
+     * <tt>List</tt> interface are considered branches; other items are
+     * considered leaves.
+     *
+     * @see #setTreeData(List)
+     */
+    public TreeView(List<?> treeData) {
+        setTreeData(treeData);
+        installSkin(TreeView.class);
+    }
+
+    @Override
+    protected void setSkin(pivot.wtk.Skin skin) {
+        if (!(skin instanceof TreeView.Skin)) {
+            throw new IllegalArgumentException("Skin class must implement "
+                + TreeView.Skin.class.getName());
+        }
+
+        super.setSkin(skin);
+    }
+
+    /**
+     * Returns the tree data.
+     */
+    public List<?> getTreeData() {
+        return this.treeData;
+    }
+
+    /**
+     * Sets the tree data.
+     *
+     * @param treeData
+     * The data to be presented by the tree. It is the responsibility of the
+     * caller to ensure that the current tree node renderer is capable of
+     * displaying the contents of the tree structure.
+     */
+    public void setTreeData(List<?> treeData) {
+        if (treeData == null) {
+            throw new IllegalArgumentException("treeData is null.");
+        }
+
+        List<?> previousTreeData = this.treeData;
+
+        if (previousTreeData != treeData) {
+            if (previousTreeData != null) {
+                // Clear any existing selection
+                clearSelection();
+
+                rootBranchInfo.unregisterListListeners();
+            }
+
+            rootBranchInfo = new BranchInfo(null, treeData);
+
+            // Update the tree data and fire change event
+            this.treeData = treeData;
+            treeViewListeners.treeDataChanged(this, previousTreeData);
+        }
+    }
+
+    public NodeRenderer getNodeRenderer() {
+        return nodeRenderer;
+    }
+
+    public void setNodeRenderer(NodeRenderer nodeRenderer) {
+        if (nodeRenderer == null) {
+            throw new IllegalArgumentException("nodeRenderer is null.");
+        }
+
+        NodeRenderer previousNodeRenderer = this.nodeRenderer;
+
+        if (previousNodeRenderer != nodeRenderer) {
+            this.nodeRenderer = nodeRenderer;
+
+            treeViewListeners.nodeRendererChanged(this, previousNodeRenderer);
+        }
+    }
+
+    /**
+     * Returns the current selection mode.
+     */
+    public SelectMode getSelectMode() {
+        return selectMode;
+    }
+
+    /**
+     * Sets the selection mode. Clears the selection if the mode has changed.
+     *
+     * @param selectMode
+     * The new selection mode.
+     */
+    public void setSelectMode(SelectMode selectMode) {
+        if (selectMode == null) {
+            throw new IllegalArgumentException("selectMode is null");
+        }
+
+        SelectMode previousSelectMode = this.selectMode;
+
+        if (selectMode != previousSelectMode) {
+            // Clear any current selection
+            clearSelection();
+
+            // Update the selection mode
+            this.selectMode = selectMode;
+
+            // Fire select mode change event
+            treeViewListeners.selectModeChanged(this, previousSelectMode);
+        }
+    }
+
+    public void setSelectMode(String selectMode) {
+        if (selectMode == null) {
+            throw new IllegalArgumentException("selectMode is null.");
+        }
+
+        setSelectMode(SelectMode.decode(selectMode));
+    }
+
+    public Sequence<Sequence<Integer>> getSelectedPaths() {
+        Sequence<Sequence<Integer>> selectedPaths = new ArrayList<Sequence<Integer>>();
+
+        // Deep copy the selected paths into a new list
+        for (int i = 0, n = this.selectedPaths.getLength(); i < n; i++) {
+            Sequence<Integer> selectedPath = new ArrayList<Integer>(this.selectedPaths.get(i));
+            selectedPaths.add(selectedPath);
+        }
+
+        return selectedPaths;
+    }
+
+    public void setSelectedPaths(Sequence<Sequence<Integer>> selectedPaths) {
+        if (selectedPaths == null) {
+            throw new IllegalArgumentException("selectedPaths is null.");
+        }
+
+        if (selectMode == SelectMode.NONE) {
+            throw new IllegalArgumentException("Selection is not enabled.");
+        }
+
+        if (selectMode == SelectMode.SINGLE
+            && selectedPaths.getLength() > 1) {
+            throw new IllegalArgumentException("Selection length is greater than 1.");
+        }
+
+        Sequence<Sequence<Integer>> previousSelectedPaths = this.selectedPaths;
+
+        // Update the selection
+        this.selectedPaths = new ArrayList<Sequence<Integer>>(PATH_COMPARATOR);
+
+        for (int i = 0, n = selectedPaths.getLength(); i < n; i++) {
+            Sequence<Integer> selectedPath = new ArrayList<Integer>(selectedPaths.get(i));
+            this.selectedPaths.add(selectedPath);
+        }
+
+        // Notify listeners
+        treeViewSelectionDetailListeners.selectionReset(this, previousSelectedPaths);
+        treeViewSelectionListeners.selectionChanged(this);
+    }
+
+    /**
+     * Returns the first selected path, as it would appear in a fully expanded
+     * tree.
+     *
+     * @return
+     * The first selected path, or <tt>null</tt> if nothing is selected.
+     */
+    public Sequence<Integer> getFirstSelectedPath() {
+        Sequence<Integer> selectedPath = null;
+
+        if (selectedPaths.getLength() > 0) {
+            selectedPath = new ArrayList<Integer>(selectedPaths.get(0));
+        }
+
+        return selectedPath;
+    }
+
+    /**
+     * Returns the last selected path, as it would appear in a fully expanded
+     * tree.
+     *
+     * @return
+     * The last selected path, or <tt>null</tt> if nothing is selected.
+     */
+    public Sequence<Integer> getLastSelectedPath() {
+        Sequence<Integer> selectedPath = null;
+
+        if (selectedPaths.getLength() > 0) {
+            selectedPath = new ArrayList<Integer>
+                (selectedPaths.get(selectedPaths.getLength() - 1));
+        }
+
+        return selectedPath;
+    }
+
+    public Sequence<Integer> getSelectedPath() {
+        if (selectMode != SelectMode.SINGLE) {
+            throw new IllegalStateException("Tree view is not in single-select mode.");
+        }
+
+        Sequence<Integer> selectedPath = null;
+
+        if (selectedPaths.getLength() > 0) {
+            selectedPath = new ArrayList<Integer>(selectedPaths.get(0));
+        }
+
+        return selectedPath;
+    }
+
+    public void setSelectedPath(Sequence<Integer> path) {
+        Sequence<Sequence<Integer>> selectedPaths = new ArrayList<Sequence<Integer>>(0);
+        selectedPaths.add(path);
+
+        setSelectedPaths(selectedPaths);
+    }
+
+    public void addSelectedPath(Sequence<Integer> path) {
+        if (selectMode != SelectMode.MULTI) {
+            throw new IllegalStateException("Tree view is not in multi-select mode.");
+        }
+
+        selectedPaths.add(new ArrayList<Integer>(path));
+
+        treeViewSelectionDetailListeners.selectedPathAdded(this, path);
+    }
+
+    public void removeSelectedPath(Sequence<Integer> path) {
+        if (selectMode != SelectMode.MULTI) {
+            throw new IllegalStateException("Tree view is not in multi-select mode.");
+        }
+
+        selectedPaths.remove(path);
+
+        treeViewSelectionDetailListeners.selectedPathRemoved(this, path);
+    }
+
+    public void clearSelection() {
+        if (selectedPaths.getLength() > 0) {
+            Sequence<Sequence<Integer>> previousSelectedPaths = selectedPaths;
+
+            selectedPaths = new ArrayList<Sequence<Integer>>(PATH_COMPARATOR);
+
+            treeViewSelectionDetailListeners.selectionReset(this, previousSelectedPaths);
+            treeViewSelectionListeners.selectionChanged(this);
+        }
+    }
+
+    public boolean isPathSelected(Sequence<Integer> path) {
+        return (selectedPaths.indexOf(path) >= 0);
+    }
+
+    /**
+     * Returns the disabled state of a given node.
+     *
+     * @param path
+     * The path to the node whose disabled state is to be tested
+     *
+     * @return
+     * <tt>true</tt> if the node is disabled; <tt>false</tt>,
+     * otherwise
+     */
+    public boolean isNodeDisabled(Sequence<Integer> path) {
+        return (disabledPaths.indexOf(path) >= 0);
+    }
+
+    /**
+     * Sets the disabled state of a node.
+     *
+     * @param path
+     * The path to the node whose disabled state is to be set
+     *
+     * @param disabled
+     * <tt>true</tt> to disable the node; <tt>false</tt>, otherwise
+     */
+    public void setNodeDisabled(Sequence<Integer> path, boolean disabled) {
+        int index = disabledPaths.indexOf(path);
+
+        if ((index < 0 && disabled)
+            || (index >= 0 && !disabled)) {
+            Vote vote = treeViewNodeStateListeners.previewNodeDisabledChange(this, path);
+            if (vote.isApproved()) {
+                if (disabled) {
+                    disabledPaths.add(path);
+                } else {
+                    disabledPaths.remove(index, 1);
+                }
+
+                treeViewNodeStateListeners.nodeDisabledChanged(this, path);
+            } else {
+                treeViewNodeStateListeners.nodeDisabledChangeVetoed(this, path, vote);
+            }
+        }
+    }
+
+    public Sequence<Sequence<Integer>> getDisabledPaths() {
+        Sequence<Sequence<Integer>> disabledPaths = new ArrayList<Sequence<Integer>>();
+
+        // Deep copy the disabled paths into a new list
+        for (int i = 0, n = this.disabledPaths.getLength(); i < n; i++) {
+            Sequence<Integer> disabledPath = new ArrayList<Integer>(this.disabledPaths.get(i));
+            disabledPaths.add(disabledPath);
+        }
+
+        return disabledPaths;
+    }
+
+    public boolean isCheckEnabled() {
+        return checkEnabled;
+    }
+
+    public void setBranchExpanded(Sequence<Integer> path, boolean expanded) {
+        int index = expandedPaths.indexOf(path);
+
+        if (expanded) {
+            if (index < 0) {
+                expandedPaths.add(new ArrayList<Integer>(path));
+                treeViewBranchListeners.branchExpanded(this, path);
+            }
+        } else {
+            if (index >= 0) {
+                expandedPaths.remove(index, 1);
+                treeViewBranchListeners.branchCollapsed(this, path);
+            }
+        }
+    }
+
+    public boolean isBranchExpanded(Sequence<Integer> path) {
+        return (expandedPaths.indexOf(path) >= 0);
+    }
+
+    public void expandBranch(Sequence<Integer> path) {
+        setBranchExpanded(path, true);
+    }
+
+    public void collapseBranch(Sequence<Integer> path) {
+        setBranchExpanded(path, false);
+    }
+
+    public Sequence<Integer> getNodeAt(int y) {
+        TreeView.Skin treeViewSkin = (TreeView.Skin)getSkin();
+        return treeViewSkin.getNodeAt(y);
+    }
+
+    public Bounds getNodeBounds(Sequence<Integer> path) {
+        TreeView.Skin treeViewSkin = (TreeView.Skin)getSkin();
+        return treeViewSkin.getNodeBounds(path);
+    }
+
+    public int getNodeOffset(Sequence<Integer> path) {
+        TreeView.Skin treeViewSkin = (TreeView.Skin)getSkin();
+        return treeViewSkin.getNodeOffset(path);
+    }
+
+    protected void insertNode(Sequence<Integer> path, int index) {
+        treeViewNodeListeners.nodeInserted(this, path, index);
+    }
+
+    protected void removeNodes(Sequence<Integer> path, int index, int count) {
+        treeViewNodeListeners.nodesRemoved(this, path, index, count);
+    }
+
+    protected void invalidateNode(Sequence<Integer> path, int index) {
+        treeViewNodeListeners.nodeUpdated(this, path, index);
+    }
+
+    public ListenerList<TreeViewListener> getTreeViewListeners() {
+        return treeViewListeners;
+    }
+
+    public ListenerList<TreeViewBranchListener> getTreeViewBranchListeners() {
+        return treeViewBranchListeners;
+    }
+
+    public ListenerList<TreeViewNodeListener> getTreeViewNodeListeners() {
+        return treeViewNodeListeners;
+    }
+
+    public ListenerList<TreeViewNodeStateListener> getTreeViewNodeStateListeners() {
+        return treeViewNodeStateListeners;
+    }
+
+    public ListenerList<TreeViewSelectionListener> getTreeViewSelectionListeners() {
+        return treeViewSelectionListeners;
+    }
+
+    public ListenerList<TreeViewSelectionDetailListener> getTreeViewSelectionDetailListeners() {
+        return treeViewSelectionDetailListeners;
+    }
+}

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

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

Added: incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TreeViewBranchListener.java
URL: http://svn.apache.org/viewvc/incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TreeViewBranchListener.java?rev=754926&view=auto
==============================================================================
--- incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TreeViewBranchListener.java (added)
+++ incubator/pivot/tags/v1.0/wtk/src/pivot/wtk/TreeViewBranchListener.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;
+
+import pivot.collections.Sequence;
+
+/**
+ * Tree view branch listener interface.
+ *
+ * @author gbrown
+ */
+public interface TreeViewBranchListener {
+    /**
+     * Called when a tree node is expanded. This event can be used to perform
+     * lazy loading of tree node data.
+     *
+     * @param treeView
+     * The source of the event.
+     *
+     * @param path
+     * The path of the node that was shown.
+     */
+    public void branchExpanded(TreeView treeView, Sequence<Integer> path);
+
+    /**
+     * Called when a tree node is collapsed.
+     *
+     * @param treeView
+     * The source of the event.
+     *
+     * @param path
+     * The path of the node that was collapsed.
+     */
+    public void branchCollapsed(TreeView treeView, Sequence<Integer> path);
+}