You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pivot.apache.org by gb...@apache.org on 2010/02/15 02:57:51 UTC

svn commit: r910155 - in /pivot/trunk: tests/src/org/apache/pivot/tests/ wtk-terra/src/org/apache/pivot/wtk/skin/terra/ wtk/src/org/apache/pivot/wtk/ wtk/src/org/apache/pivot/wtk/skin/

Author: gbrown
Date: Mon Feb 15 01:57:50 2010
New Revision: 910155

URL: http://svn.apache.org/viewvc?rev=910155&view=rev
Log:
Resolve PIVOT-414.

Added:
    pivot/trunk/tests/src/org/apache/pivot/tests/DataBindingTest.java
    pivot/trunk/tests/src/org/apache/pivot/tests/data_binding_test.wtkx
Modified:
    pivot/trunk/wtk-terra/src/org/apache/pivot/wtk/skin/terra/TerraListViewSkin.java
    pivot/trunk/wtk-terra/src/org/apache/pivot/wtk/skin/terra/TerraSpinnerSkin.java
    pivot/trunk/wtk/src/org/apache/pivot/wtk/ListButton.java
    pivot/trunk/wtk/src/org/apache/pivot/wtk/ListButtonListener.java
    pivot/trunk/wtk/src/org/apache/pivot/wtk/ListView.java
    pivot/trunk/wtk/src/org/apache/pivot/wtk/ListViewListener.java
    pivot/trunk/wtk/src/org/apache/pivot/wtk/Spinner.java
    pivot/trunk/wtk/src/org/apache/pivot/wtk/SpinnerListener.java
    pivot/trunk/wtk/src/org/apache/pivot/wtk/skin/ListButtonSkin.java

Added: pivot/trunk/tests/src/org/apache/pivot/tests/DataBindingTest.java
URL: http://svn.apache.org/viewvc/pivot/trunk/tests/src/org/apache/pivot/tests/DataBindingTest.java?rev=910155&view=auto
==============================================================================
--- pivot/trunk/tests/src/org/apache/pivot/tests/DataBindingTest.java (added)
+++ pivot/trunk/tests/src/org/apache/pivot/tests/DataBindingTest.java Mon Feb 15 01:57:50 2010
@@ -0,0 +1,154 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.pivot.tests;
+
+import org.apache.pivot.collections.HashMap;
+import org.apache.pivot.collections.List;
+import org.apache.pivot.collections.Map;
+import org.apache.pivot.serialization.JSONSerializer;
+import org.apache.pivot.wtk.Application;
+import org.apache.pivot.wtk.Button;
+import org.apache.pivot.wtk.DesktopApplicationContext;
+import org.apache.pivot.wtk.Display;
+import org.apache.pivot.wtk.ListView;
+import org.apache.pivot.wtk.Spinner;
+import org.apache.pivot.wtk.Window;
+import org.apache.pivot.wtk.content.ListButtonDataRenderer;
+import org.apache.pivot.wtk.content.ListViewItemRenderer;
+import org.apache.pivot.wtk.content.SpinnerItemRenderer;
+import org.apache.pivot.wtkx.WTKXSerializer;
+
+public class DataBindingTest implements Application {
+    public static class TestListButtonDataRenderer extends ListButtonDataRenderer {
+        @Override
+        public void render(Object data, Button button, boolean highlighted) {
+            if (data != null) {
+                data = JSONSerializer.getString(data, "text");
+            }
+
+            super.render(data, button, highlighted);
+        }
+
+        @Override
+        public String toString(Object data) {
+            return JSONSerializer.getString(data, "text");
+        }
+    }
+
+    public static class TestListViewItemRenderer extends ListViewItemRenderer {
+        @Override
+        public void render(Object item, int index, ListView listView, boolean selected,
+            boolean checked, boolean highlighted, boolean disabled) {
+            if (item != null) {
+                item = JSONSerializer.getString(item, "text");
+            }
+
+            super.render(item, index, listView, selected, checked, highlighted, disabled);
+        }
+
+        @Override
+        public String toString(Object item) {
+            return JSONSerializer.getString(item, "text");
+        }
+    }
+
+    public static class TestSpinnerItemRenderer extends SpinnerItemRenderer {
+        @Override
+        public void render(Object item, Spinner spinner) {
+            if (item != null) {
+                item = JSONSerializer.getString(item, "text");
+            }
+
+            super.render(item, spinner);
+        }
+
+        @Override
+        public String toString(Object item) {
+            return JSONSerializer.getString(item, "text");
+        }
+    }
+
+    public static class TestBindMapping implements ListView.BindMapping, Spinner.BindMapping {
+        @SuppressWarnings("unchecked")
+        public int indexOf(List<?> list, Object item) {
+            int i = 0;
+            int n = list.getLength();
+            while (i < n) {
+                Map<String, ?> map = (Map<String, ?>)list.get(i);
+                if (map.get("id").equals(item)) {
+                    break;
+                }
+
+                i++;
+            }
+
+            if (i == n) {
+                i = -1;
+            }
+
+            return i;
+        }
+
+        @SuppressWarnings("unchecked")
+        public Object get(List<?> list, int index) {
+            Map<String, ?> map = (Map<String, ?>)list.get(index);
+            return map.get("id");
+        }
+    }
+
+    private Window window = null;
+
+    @Override
+    public void startup(Display display, Map<String, String> properties) throws Exception {
+        WTKXSerializer wtkxSerializer = new WTKXSerializer();
+        window = (Window)wtkxSerializer.readObject(this, "data_binding_test.wtkx");
+        window.open(display);
+
+        HashMap<String, Object> context = new HashMap<String, Object>();
+        context.put("id1", "1");
+        context.put("id2", "2");
+        context.put("id3", "3");
+
+        window.getContent().load(context);
+
+        context = new HashMap<String, Object>();
+        window.getContent().store(context);
+
+        System.out.println(JSONSerializer.toString(context));
+    }
+
+    @Override
+    public boolean shutdown(boolean optional) throws Exception {
+        if (window != null) {
+            window.close();
+        }
+
+        return false;
+    }
+
+    @Override
+    public void suspend() {
+    }
+
+    @Override
+    public void resume() {
+    }
+
+    public static void main(String[] args) {
+        DesktopApplicationContext.main(DataBindingTest.class, args);
+    }
+}

Added: pivot/trunk/tests/src/org/apache/pivot/tests/data_binding_test.wtkx
URL: http://svn.apache.org/viewvc/pivot/trunk/tests/src/org/apache/pivot/tests/data_binding_test.wtkx?rev=910155&view=auto
==============================================================================
--- pivot/trunk/tests/src/org/apache/pivot/tests/data_binding_test.wtkx (added)
+++ pivot/trunk/tests/src/org/apache/pivot/tests/data_binding_test.wtkx Mon Feb 15 01:57:50 2010
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to you under the Apache License,
+Version 2.0 (the "License"); you may not use this file except in
+compliance with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+<Window title="Data Binding Test" maximized="true"
+    xmlns:wtkx="http://pivot.apache.org/wtkx"
+    xmlns:tests="org.apache.pivot.tests"
+    xmlns="org.apache.pivot.wtk">
+    <wtkx:define xmlns="org.apache.pivot.collections">
+        <ArrayList wtkx:id="list">
+            <HashMap id="1" text="A"/>
+            <HashMap id="2" text="B"/>
+            <HashMap id="3" text="C"/>
+            <HashMap id="4" text="D"/>
+        </ArrayList>
+    </wtkx:define>
+    <content>
+        <BoxPane orientation="vertical">
+            <ListView listData="$list" selectedItemKey="id1">
+                <itemRenderer>
+                    <tests:DataBindingTest.TestListViewItemRenderer/>
+                </itemRenderer>
+                <bindMapping>
+                    <tests:DataBindingTest.TestBindMapping/>
+                </bindMapping>
+            </ListView>
+
+            <ListButton listData="$list" selectedItemKey="id2">
+                <dataRenderer>
+                    <tests:DataBindingTest.TestListButtonDataRenderer/>
+                </dataRenderer>
+                <itemRenderer>
+                    <tests:DataBindingTest.TestListViewItemRenderer/>
+                </itemRenderer>
+                <bindMapping>
+                    <tests:DataBindingTest.TestBindMapping/>
+                </bindMapping>
+            </ListButton>
+
+            <Spinner spinnerData="$list" selectedItemKey="id3">
+                <itemRenderer>
+                    <tests:DataBindingTest.TestSpinnerItemRenderer/>
+                </itemRenderer>
+                <bindMapping>
+                    <tests:DataBindingTest.TestBindMapping/>
+                </bindMapping>
+            </Spinner>
+        </BoxPane>
+    </content>
+</Window>

Modified: pivot/trunk/wtk-terra/src/org/apache/pivot/wtk/skin/terra/TerraListViewSkin.java
URL: http://svn.apache.org/viewvc/pivot/trunk/wtk-terra/src/org/apache/pivot/wtk/skin/terra/TerraListViewSkin.java?rev=910155&r1=910154&r2=910155&view=diff
==============================================================================
--- pivot/trunk/wtk-terra/src/org/apache/pivot/wtk/skin/terra/TerraListViewSkin.java (original)
+++ pivot/trunk/wtk-terra/src/org/apache/pivot/wtk/skin/terra/TerraListViewSkin.java Mon Feb 15 01:57:50 2010
@@ -1074,6 +1074,11 @@
         // No-op
     }
 
+    @Override
+    public void bindMappingChanged(ListView listView, ListView.BindMapping previousBindMapping) {
+        // No-op
+    }
+
     // List view item events
     @Override
     public void itemInserted(ListView listView, int index) {

Modified: pivot/trunk/wtk-terra/src/org/apache/pivot/wtk/skin/terra/TerraSpinnerSkin.java
URL: http://svn.apache.org/viewvc/pivot/trunk/wtk-terra/src/org/apache/pivot/wtk/skin/terra/TerraSpinnerSkin.java?rev=910155&r1=910154&r2=910155&view=diff
==============================================================================
--- pivot/trunk/wtk-terra/src/org/apache/pivot/wtk/skin/terra/TerraSpinnerSkin.java (original)
+++ pivot/trunk/wtk-terra/src/org/apache/pivot/wtk/skin/terra/TerraSpinnerSkin.java Mon Feb 15 01:57:50 2010
@@ -860,6 +860,11 @@
         // No-op
     }
 
+    @Override
+    public void bindMappingChanged(Spinner spinner, Spinner.BindMapping previousBindMapping) {
+        // No-op
+    }
+
     // SpinnerSelectionListener methods
 
     @Override

Modified: pivot/trunk/wtk/src/org/apache/pivot/wtk/ListButton.java
URL: http://svn.apache.org/viewvc/pivot/trunk/wtk/src/org/apache/pivot/wtk/ListButton.java?rev=910155&r1=910154&r2=910155&view=diff
==============================================================================
--- pivot/trunk/wtk/src/org/apache/pivot/wtk/ListButton.java (original)
+++ pivot/trunk/wtk/src/org/apache/pivot/wtk/ListButton.java Mon Feb 15 01:57:50 2010
@@ -31,9 +31,6 @@
  * options are hidden until the user pushes the button.
  */
 public class ListButton extends Button {
-    /**
-     * List button listener list.
-     */
     private static class ListButtonListenerList extends ListenerList<ListButtonListener>
         implements ListButtonListener {
         @Override
@@ -63,11 +60,15 @@
                 listener.selectedItemKeyChanged(listButton, previousSelectedItemKey);
             }
         }
+
+        @Override
+        public void bindMappingChanged(ListButton listButton, ListView.BindMapping previousBindMapping) {
+            for (ListButtonListener listener : this) {
+                listener.bindMappingChanged(listButton, previousBindMapping);
+            }
+        }
     }
 
-    /**
-     * List button selection listener list.
-     */
     private static class ListButtonSelectionListenerList extends ListenerList<ListButtonSelectionListener>
         implements ListButtonSelectionListener {
         @Override
@@ -82,7 +83,9 @@
     private ListView.ItemRenderer itemRenderer;
     private int selectedIndex = -1;
     private Filter<?> disabledItemFilter = null;
+
     private String selectedItemKey = null;
+    private ListView.BindMapping bindMapping = null;
 
     private ListButtonListenerList listButtonListeners = new ListButtonListenerList();
     private ListButtonSelectionListenerList listButtonSelectionListeners = new ListButtonSelectionListenerList();
@@ -328,12 +331,34 @@
         }
     }
 
+    public ListView.BindMapping getBindMapping() {
+        return bindMapping;
+    }
+
+    public void setBindMapping(ListView.BindMapping bindMapping) {
+        ListView.BindMapping previousBindMapping = this.bindMapping;
+
+        if (previousBindMapping != bindMapping) {
+            this.bindMapping = bindMapping;
+            listButtonListeners.bindMappingChanged(this, previousBindMapping);
+        }
+    }
+
     @Override
+    @SuppressWarnings("unchecked")
     public void load(Dictionary<String, ?> context) {
         if (selectedItemKey != null
             && JSONSerializer.containsKey(context, selectedItemKey)) {
             Object item = JSONSerializer.get(context, selectedItemKey);
-            setSelectedItem(item);
+
+            int index;
+            if (bindMapping == null) {
+                index = ((List<Object>)listData).indexOf(item);
+            } else {
+                index = bindMapping.indexOf(listData, item);
+            }
+
+            setSelectedIndex(index);
         }
     }
 
@@ -341,7 +366,15 @@
     public void store(Dictionary<String, ?> context) {
         if (isEnabled()
             && selectedItemKey != null) {
-            Object item = getSelectedItem();
+            int selectedIndex = getSelectedIndex();
+
+            Object item;
+            if (bindMapping == null) {
+                item = listData.get(selectedIndex);
+            } else {
+                item = bindMapping.get(listData, selectedIndex);
+            }
+
             JSONSerializer.put(context, selectedItemKey, item);
         }
     }

Modified: pivot/trunk/wtk/src/org/apache/pivot/wtk/ListButtonListener.java
URL: http://svn.apache.org/viewvc/pivot/trunk/wtk/src/org/apache/pivot/wtk/ListButtonListener.java?rev=910155&r1=910154&r2=910155&view=diff
==============================================================================
--- pivot/trunk/wtk/src/org/apache/pivot/wtk/ListButtonListener.java (original)
+++ pivot/trunk/wtk/src/org/apache/pivot/wtk/ListButtonListener.java Mon Feb 15 01:57:50 2010
@@ -42,6 +42,10 @@
         @Override
         public void selectedItemKeyChanged(ListButton listButton, String previousSelectedItemKey) {
         }
+
+        @Override
+        public void bindMappingChanged(ListButton listButton, ListView.BindMapping previousBindMapping) {
+        }
     }
 
     /**
@@ -75,4 +79,12 @@
      * @param previousSelectedItemKey
      */
     public void selectedItemKeyChanged(ListButton listButton, String previousSelectedItemKey);
+
+    /**
+     * Called when a list button's bind mapping has changed.
+     *
+     * @param listButton
+     * @param previousBindMapping
+     */
+    public void bindMappingChanged(ListButton listButton, ListView.BindMapping previousBindMapping);
 }

Modified: pivot/trunk/wtk/src/org/apache/pivot/wtk/ListView.java
URL: http://svn.apache.org/viewvc/pivot/trunk/wtk/src/org/apache/pivot/wtk/ListView.java?rev=910155&r1=910154&r2=910155&view=diff
==============================================================================
--- pivot/trunk/wtk/src/org/apache/pivot/wtk/ListView.java (original)
+++ pivot/trunk/wtk/src/org/apache/pivot/wtk/ListView.java Mon Feb 15 01:57:50 2010
@@ -361,6 +361,37 @@
     }
 
     /**
+     * Translates between list and bind context data during data binding.
+     */
+    public interface BindMapping {
+        /**
+         * Returns the index of the item in the source list.
+         *
+         * @param listData
+         * The source list data.
+         *
+         * @param item
+         * The item to locate.
+         *
+         * @return
+         * The index of first occurrence of the item if it exists in the list;
+         * <tt>-1</tt>, otherwise.
+         */
+        public int indexOf(List<?> listData, Object item);
+
+        /**
+         * Retrieves the item at the given index.
+         *
+         * @param listData
+         * The source list data.
+         *
+         * @param index
+         * The index of the item to retrieve.
+         */
+        public Object get(List<?> listData, int index);
+    }
+
+    /**
      * List view listener list.
      */
     private static class ListViewListenerList extends ListenerList<ListViewListener> implements
@@ -432,6 +463,13 @@
                 listener.selectedItemsKeyChanged(listView, previousSelectedItemsKey);
             }
         }
+
+        @Override
+        public void bindMappingChanged(ListView listView, BindMapping previousBindMapping) {
+            for (ListViewListener listener : this) {
+                listener.bindMappingChanged(listView, previousBindMapping);
+            }
+        }
     }
 
     /**
@@ -614,6 +652,7 @@
 
     private String selectedItemKey = null;
     private String selectedItemsKey = null;
+    private BindMapping bindMapping = null;
 
     private ListViewListenerList listViewListeners = new ListViewListenerList();
     private ListViewItemListenerList listViewItemListeners = new ListViewItemListenerList();
@@ -1434,34 +1473,94 @@
         }
     }
 
+    public BindMapping getBindMapping() {
+        return bindMapping;
+    }
+
+    public void setBindMapping(BindMapping bindMapping) {
+        BindMapping previousBindMapping = this.bindMapping;
+
+        if (previousBindMapping != bindMapping) {
+            this.bindMapping = bindMapping;
+            listViewListeners.bindMappingChanged(this, previousBindMapping);
+        }
+    }
+
     @Override
     @SuppressWarnings("unchecked")
     public void load(Dictionary<String, ?> context) {
         if (selectedItemKey != null
             && JSONSerializer.containsKey(context, selectedItemKey)) {
             Object item = JSONSerializer.get(context, selectedItemKey);
-            setSelectedItem(item);
+
+            int index;
+            if (bindMapping == null) {
+                index = ((List<Object>)listData).indexOf(item);
+            } else {
+                index = bindMapping.indexOf(listData, item);
+            }
+
+            setSelectedIndex(index);
         }
 
         if (selectedItemsKey != null
             && JSONSerializer.containsKey(context, selectedItemsKey)) {
-            Sequence<Object> items = (Sequence<Object>)JSONSerializer.get(context,
-                selectedItemsKey);
-            setSelectedItems(items);
+            Sequence<Object> items = (Sequence<Object>)JSONSerializer.get(context, selectedItemsKey);
+
+            clearSelection();
+
+            for (int i = 0, n = items.getLength(); i < n; i++) {
+                Object item = items.get(i);
+
+                int index;
+                if (bindMapping == null) {
+                    index = ((List<Object>)listData).indexOf(item);
+                } else {
+                    index = bindMapping.indexOf(listData, item);
+                }
+
+                if (index != -1) {
+                    addSelectedIndex(index);
+                }
+            }
         }
     }
 
     @Override
-    @SuppressWarnings("unchecked")
     public void store(Dictionary<String, ?> context) {
         if (isEnabled()) {
             if (selectedItemKey != null) {
-                Object item = getSelectedItem();
+                int selectedIndex = getSelectedIndex();
+
+                Object item;
+                if (bindMapping == null) {
+                    item = listData.get(selectedIndex);
+                } else {
+                    item = bindMapping.get(listData, selectedIndex);
+                }
+
                 JSONSerializer.put(context, selectedItemKey, item);
             }
 
             if (selectedItemsKey != null) {
-                Sequence<Object> items = (Sequence<Object>)getSelectedItems();
+                ArrayList<Object> items = new ArrayList<Object>();
+
+                Sequence<Span> selectedRanges = getSelectedRanges();
+                for (int i = 0, n = selectedRanges.getLength(); i < n; i++) {
+                    Span range = selectedRanges.get(i);
+
+                    for (int index = range.start; index <= range.end; index++) {
+                        Object item;
+                        if (bindMapping == null) {
+                            item = listData.get(index);
+                        } else {
+                            item = bindMapping.get(listData, index);
+                        }
+
+                        items.add(item);
+                    }
+                }
+
                 JSONSerializer.put(context, selectedItemsKey, items);
             }
         }

Modified: pivot/trunk/wtk/src/org/apache/pivot/wtk/ListViewListener.java
URL: http://svn.apache.org/viewvc/pivot/trunk/wtk/src/org/apache/pivot/wtk/ListViewListener.java?rev=910155&r1=910154&r2=910155&view=diff
==============================================================================
--- pivot/trunk/wtk/src/org/apache/pivot/wtk/ListViewListener.java (original)
+++ pivot/trunk/wtk/src/org/apache/pivot/wtk/ListViewListener.java Mon Feb 15 01:57:50 2010
@@ -64,6 +64,10 @@
         @Override
         public void selectedItemsKeyChanged(ListView listView, String previousSelectedItemsKey) {
         }
+
+        @Override
+        public void bindMappingChanged(ListView listView, ListView.BindMapping previousBindMapping) {
+        }
     }
 
     /**
@@ -137,4 +141,12 @@
      * @param previousSelectedItemsKey
      */
     public void selectedItemsKeyChanged(ListView listView, String previousSelectedItemsKey);
+
+    /**
+     * Called when a list view's bind mapping has changed.
+     *
+     * @param listView
+     * @param previousBindMapping
+     */
+    public void bindMappingChanged(ListView listView, ListView.BindMapping previousBindMapping);
 }

Modified: pivot/trunk/wtk/src/org/apache/pivot/wtk/Spinner.java
URL: http://svn.apache.org/viewvc/pivot/trunk/wtk/src/org/apache/pivot/wtk/Spinner.java?rev=910155&r1=910154&r2=910155&view=diff
==============================================================================
--- pivot/trunk/wtk/src/org/apache/pivot/wtk/Spinner.java (original)
+++ pivot/trunk/wtk/src/org/apache/pivot/wtk/Spinner.java Mon Feb 15 01:57:50 2010
@@ -28,7 +28,6 @@
 import org.apache.pivot.util.ListenerList;
 import org.apache.pivot.wtk.content.SpinnerItemRenderer;
 
-
 /**
  * Component that presents a means of cycling through a list of items.
  */
@@ -73,6 +72,37 @@
     }
 
     /**
+     * Translates between spinner and bind context data during data binding.
+     */
+    public interface BindMapping {
+        /**
+         * Returns the index of the item in the source list.
+         *
+         * @param spinnerData
+         * The source spinner data.
+         *
+         * @param item
+         * The item to locate.
+         *
+         * @return
+         * The index of first occurrence of the item if it exists in the list;
+         * <tt>-1</tt>, otherwise.
+         */
+        public int indexOf(List<?> spinnerData, Object item);
+
+        /**
+         * Retrieves the item at the given index.
+         *
+         * @param listData
+         * The source spinner data.
+         *
+         * @param index
+         * The index of the item to retrieve.
+         */
+        public Object get(List<?> spinnerData, int index);
+    }
+
+    /**
      * List event handler.
      */
     private class ListHandler implements ListListener<Object> {
@@ -156,6 +186,13 @@
                 listener.selectedItemKeyChanged(spinner, previousSelectedItemKey);
             }
         }
+
+        @Override
+        public void bindMappingChanged(Spinner spinner, BindMapping previousBindMapping) {
+            for (SpinnerListener listener : this) {
+                listener.bindMappingChanged(spinner, previousBindMapping);
+            }
+        }
     }
 
     /**
@@ -220,8 +257,8 @@
 
     private boolean circular = false;
     private int selectedIndex = -1;
-
     private String selectedItemKey = null;
+    private BindMapping bindMapping = null;
 
     private SpinnerListenerList spinnerListeners = new SpinnerListenerList();
     private SpinnerItemListenerList spinnerItemListeners = new SpinnerItemListenerList();
@@ -410,12 +447,34 @@
         }
     }
 
+    public BindMapping getBindMapping() {
+        return bindMapping;
+    }
+
+    public void setBindMapping(BindMapping bindMapping) {
+        BindMapping previousBindMapping = this.bindMapping;
+
+        if (previousBindMapping != bindMapping) {
+            this.bindMapping = bindMapping;
+            spinnerListeners.bindMappingChanged(this, previousBindMapping);
+        }
+    }
+
     @Override
+    @SuppressWarnings("unchecked")
     public void load(Dictionary<String, ?> context) {
         if (selectedItemKey != null
             && JSONSerializer.containsKey(context, selectedItemKey)) {
             Object item = JSONSerializer.get(context, selectedItemKey);
-            setSelectedItem(item);
+
+            int index;
+            if (bindMapping == null) {
+                index = ((List<Object>)spinnerData).indexOf(item);
+            } else {
+                index = bindMapping.indexOf(spinnerData, item);
+            }
+
+            setSelectedIndex(index);
         }
     }
 
@@ -423,7 +482,15 @@
     public void store(Dictionary<String, ?> context) {
         if (isEnabled()
             && selectedItemKey != null) {
-            Object item = getSelectedItem();
+            int selectedIndex = getSelectedIndex();
+
+            Object item;
+            if (bindMapping == null) {
+                item = spinnerData.get(selectedIndex);
+            } else {
+                item = bindMapping.get(spinnerData, selectedIndex);
+            }
+
             JSONSerializer.put(context, selectedItemKey, item);
         }
     }

Modified: pivot/trunk/wtk/src/org/apache/pivot/wtk/SpinnerListener.java
URL: http://svn.apache.org/viewvc/pivot/trunk/wtk/src/org/apache/pivot/wtk/SpinnerListener.java?rev=910155&r1=910154&r2=910155&view=diff
==============================================================================
--- pivot/trunk/wtk/src/org/apache/pivot/wtk/SpinnerListener.java (original)
+++ pivot/trunk/wtk/src/org/apache/pivot/wtk/SpinnerListener.java Mon Feb 15 01:57:50 2010
@@ -41,6 +41,10 @@
         @Override
         public void selectedItemKeyChanged(Spinner spinner, String previousSelectedItemKey) {
         }
+
+        @Override
+        public void bindMappingChanged(Spinner spinner, Spinner.BindMapping previousBindMapping) {
+        }
     }
 
     /**
@@ -73,4 +77,12 @@
      * @param previousSelectedItemKey
      */
     public void selectedItemKeyChanged(Spinner spinner, String previousSelectedItemKey);
+
+    /**
+     * Called when a spinner's bind mapping has changed.
+     *
+     * @param spinner
+     * @param previousBindMapping
+     */
+    public void bindMappingChanged(Spinner spinner, Spinner.BindMapping previousBindMapping);
 }

Modified: pivot/trunk/wtk/src/org/apache/pivot/wtk/skin/ListButtonSkin.java
URL: http://svn.apache.org/viewvc/pivot/trunk/wtk/src/org/apache/pivot/wtk/skin/ListButtonSkin.java?rev=910155&r1=910154&r2=910155&view=diff
==============================================================================
--- pivot/trunk/wtk/src/org/apache/pivot/wtk/skin/ListButtonSkin.java (original)
+++ pivot/trunk/wtk/src/org/apache/pivot/wtk/skin/ListButtonSkin.java Mon Feb 15 01:57:50 2010
@@ -349,6 +349,11 @@
         // No-op
     }
 
+    @Override
+    public void bindMappingChanged(ListButton listButton, ListView.BindMapping previousBindMapping) {
+        // No-op
+    }
+
     // List button selection events
     @Override
     public void selectedIndexChanged(ListButton listButton, int previousSelectedIndex) {