changeset 7902:4756dd1cca2c

RT-37632: ListView may not return the selected item (Regression)
author jgiles
date Fri, 29 Aug 2014 13:44:39 +1200
parents 5e4ce148e333
children acefdf6c9fd2
files modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/CellBehaviorBase.java modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/ListViewBehavior.java modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/TableCellBehaviorBase.java modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/TableViewBehaviorBase.java modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/TreeViewBehavior.java modules/controls/src/main/java/com/sun/javafx/scene/control/skin/ComboBoxListViewSkin.java modules/controls/src/main/java/javafx/scene/control/ListView.java modules/controls/src/main/java/javafx/scene/control/TablePosition.java modules/controls/src/main/java/javafx/scene/control/TableView.java modules/controls/src/main/java/javafx/scene/control/TreeTableView.java modules/controls/src/main/java/javafx/scene/control/TreeView.java modules/controls/src/test/java/javafx/scene/control/ListViewTest.java modules/controls/src/test/java/javafx/scene/control/TableViewTest.java modules/controls/src/test/java/javafx/scene/control/TreeTableViewKeyInputTest.java modules/controls/src/test/java/javafx/scene/control/TreeTableViewMouseInputTest.java modules/controls/src/test/java/javafx/scene/control/TreeTableViewSelectionModelImplTest.java modules/controls/src/test/java/javafx/scene/control/TreeTableViewTest.java modules/controls/src/test/java/javafx/scene/control/TreeViewKeyInputTest.java modules/controls/src/test/java/javafx/scene/control/TreeViewTest.java
diffstat 19 files changed, 357 insertions(+), 101 deletions(-) [+]
line wrap: on
line diff
--- a/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/CellBehaviorBase.java	Thu Aug 28 11:16:55 2014 +1200
+++ b/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/CellBehaviorBase.java	Fri Aug 29 13:44:39 2014 +1200
@@ -53,26 +53,44 @@
 
     private static final String ANCHOR_PROPERTY_KEY = "anchor";
 
+    // The virtualised controls all start with selection on row 0 by default.
+    // This means that we have a default anchor, but it should be removed if
+    // a different anchor could be set - and normally we ignore the default
+    // anchor anyway.
+    private static final String IS_DEFAULT_ANCHOR_KEY = "isDefaultAnchor";
+
     public static <T> T getAnchor(Control control, T defaultResponse) {
-        return hasAnchor(control) ?
+        return hasNonDefaultAnchor(control) ?
                 (T) control.getProperties().get(ANCHOR_PROPERTY_KEY) :
                 defaultResponse;
     }
 
-    public static <T> void setAnchor(Control control, T anchor) {
+    public static <T> void setAnchor(Control control, T anchor, boolean isDefaultAnchor) {
         if (control != null && anchor == null) {
             removeAnchor(control);
         } else {
             control.getProperties().put(ANCHOR_PROPERTY_KEY, anchor);
+            control.getProperties().put(IS_DEFAULT_ANCHOR_KEY, isDefaultAnchor);
         }
     }
 
-    public static boolean hasAnchor(Control control) {
+    public static boolean hasNonDefaultAnchor(Control control) {
+        Boolean isDefaultAnchor = (Boolean) control.getProperties().remove(IS_DEFAULT_ANCHOR_KEY);
+        return (isDefaultAnchor == null || isDefaultAnchor == false) && hasAnchor(control);
+    }
+
+    public static boolean hasDefaultAnchor(Control control) {
+        Boolean isDefaultAnchor = (Boolean) control.getProperties().remove(IS_DEFAULT_ANCHOR_KEY);
+        return isDefaultAnchor != null && isDefaultAnchor == true && hasAnchor(control);
+    }
+
+    private static boolean hasAnchor(Control control) {
         return control.getProperties().get(ANCHOR_PROPERTY_KEY) != null;
     }
 
     public static void removeAnchor(Control control) {
         control.getProperties().remove(ANCHOR_PROPERTY_KEY);
+        control.getProperties().remove(IS_DEFAULT_ANCHOR_KEY);
     }
 
 
@@ -194,8 +212,8 @@
         // result in the correct selection occuring (whilst the focus index moves
         // about).
         if (shiftDown) {
-            if (! hasAnchor(cellContainer)) {
-                setAnchor(cellContainer, fm.getFocusedIndex());
+            if (! hasNonDefaultAnchor(cellContainer)) {
+                setAnchor(cellContainer, fm.getFocusedIndex(), false);
             }
         } else {
             removeAnchor(cellContainer);
--- a/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/ListViewBehavior.java	Thu Aug 28 11:16:55 2014 +1200
+++ b/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/ListViewBehavior.java	Fri Aug 29 13:44:39 2014 +1200
@@ -242,13 +242,19 @@
     
     private final ListChangeListener<Integer> selectedIndicesListener = c -> {
         while (c.next()) {
+            if (c.wasReplaced()) {
+                if (ListCellBehavior.hasDefaultAnchor(getControl())) {
+                    ListCellBehavior.removeAnchor(getControl());
+                }
+            }
+
             MultipleSelectionModel<T> sm = getControl().getSelectionModel();
 
             // there are no selected items, so lets clear out the anchor
             if (! selectionChanging) {
                 if (sm.isEmpty()) {
                     setAnchor(-1);
-                } else if (! sm.isSelected(getAnchor())) {
+                } else if (hasAnchor() && ! sm.isSelected(getAnchor())) {
                     setAnchor(-1);
                 }
             }
@@ -337,7 +343,7 @@
     }
 
     private void setAnchor(int anchor) {
-        ListCellBehavior.setAnchor(getControl(), anchor < 0 ? null : anchor);
+        ListCellBehavior.setAnchor(getControl(), anchor < 0 ? null : anchor, false);
     }
     
     private int getAnchor() {
@@ -345,7 +351,7 @@
     }
     
     private boolean hasAnchor() {
-        return ListCellBehavior.hasAnchor(getControl());
+        return ListCellBehavior.hasNonDefaultAnchor(getControl());
     }
 
     @Override public void mousePressed(MouseEvent e) {
--- a/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/TableCellBehaviorBase.java	Thu Aug 28 11:16:55 2014 +1200
+++ b/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/TableCellBehaviorBase.java	Fri Aug 29 13:44:39 2014 +1200
@@ -134,8 +134,8 @@
         // result in the correct selection occuring (whilst the focus index moves
         // about).
         if (shiftDown) {
-            if (! hasAnchor(tableView)) {
-                setAnchor(tableView, focusedCell);
+            if (! hasNonDefaultAnchor(tableView)) {
+                setAnchor(tableView, focusedCell, false);
             }
         } else {
             removeAnchor(tableView);
--- a/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/TableViewBehaviorBase.java	Thu Aug 28 11:16:55 2014 +1200
+++ b/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/TableViewBehaviorBase.java	Fri Aug 29 13:44:39 2014 +1200
@@ -225,6 +225,12 @@
 
     protected final ListChangeListener<TablePositionBase> selectedCellsListener = c -> {
         while (c.next()) {
+            if (c.wasReplaced()) {
+                if (TreeTableCellBehavior.hasDefaultAnchor(getControl())) {
+                    TreeTableCellBehavior.removeAnchor(getControl());
+                }
+            }
+
             if (! c.wasAdded()) {
                 continue;
             }
@@ -295,7 +301,7 @@
      * Call to record the current anchor position
      */
     protected void setAnchor(TablePositionBase tp) {
-        TableCellBehaviorBase.setAnchor(getControl(), tp);
+        TableCellBehaviorBase.setAnchor(getControl(), tp, false);
         setSelectionPathDeviated(false);
     }
     
@@ -310,7 +316,7 @@
      * Returns true if there is an anchor set, and false if not anchor is set.
      */
     protected boolean hasAnchor() {
-        return TableCellBehaviorBase.hasAnchor(getControl());
+        return TableCellBehaviorBase.hasNonDefaultAnchor(getControl());
     }
     
     /**
--- a/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/TreeViewBehavior.java	Thu Aug 28 11:16:55 2014 +1200
+++ b/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/TreeViewBehavior.java	Fri Aug 29 13:44:39 2014 +1200
@@ -232,13 +232,19 @@
     
     private final ListChangeListener<Integer> selectedIndicesListener = c -> {
         while (c.next()) {
+            if (c.wasReplaced()) {
+                if (TreeCellBehavior.hasDefaultAnchor(getControl())) {
+                    TreeCellBehavior.removeAnchor(getControl());
+                }
+            }
+
             MultipleSelectionModel<TreeItem<T>> sm = getControl().getSelectionModel();
 
             // there are no selected items, so lets clear out the anchor
             if (! selectionChanging) {
                 if (sm.isEmpty()) {
                     setAnchor(-1);
-                } else if (! sm.isSelected(getAnchor())) {
+                } else if (hasAnchor() && ! sm.isSelected(getAnchor())) {
                     setAnchor(-1);
                 }
             }
@@ -287,7 +293,7 @@
     }
     
     private void setAnchor(int anchor) {
-        TreeCellBehavior.setAnchor(getControl(), anchor < 0 ? null : anchor);
+        TreeCellBehavior.setAnchor(getControl(), anchor < 0 ? null : anchor, false);
     }
     
     private int getAnchor() {
@@ -295,7 +301,7 @@
     }
     
     private boolean hasAnchor() {
-        return TreeCellBehavior.hasAnchor(getControl());
+        return TreeCellBehavior.hasNonDefaultAnchor(getControl());
     }
 
     @Override public void mousePressed(MouseEvent e) {
--- a/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/ComboBoxListViewSkin.java	Thu Aug 28 11:16:55 2014 +1200
+++ b/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/ComboBoxListViewSkin.java	Fri Aug 29 13:44:39 2014 +1200
@@ -609,6 +609,8 @@
                 // not what is expected in the ComboBox control (unlike the
                 // ListView control, which does this).
                 getProperties().put("selectOnFocusGain", false);
+
+                getProperties().put("selectFirstRowByDefault", false);
             }
 
             @Override protected double computeMinHeight(double width) {
--- a/modules/controls/src/main/java/javafx/scene/control/ListView.java	Thu Aug 28 11:16:55 2014 +1200
+++ b/modules/controls/src/main/java/javafx/scene/control/ListView.java	Fri Aug 29 13:44:39 2014 +1200
@@ -30,6 +30,7 @@
 import java.util.HashMap;
 import java.util.List;
 
+import com.sun.javafx.scene.control.behavior.ListCellBehavior;
 import javafx.beans.InvalidationListener;
 import javafx.beans.property.BooleanProperty;
 import javafx.beans.property.DoubleProperty;
@@ -276,7 +277,20 @@
     }
     private static final EventType<?> EDIT_COMMIT_EVENT =
             new EventType<>(editAnyEvent(), "EDIT_COMMIT");
-    
+
+
+
+    /***************************************************************************
+     *                                                                         *
+     * Fields                                                                  *
+     *                                                                         *
+     **************************************************************************/
+
+    // by default we always select the first row in the ListView, and when the
+    // items list changes, we also reselect the first row. In some cases, such as
+    // for the ComboBox, this is not desirable, so it can be disabled here.
+    private boolean selectFirstRowByDefault = true;
+
     
 
     /***************************************************************************
@@ -343,6 +357,12 @@
                     focusedProperty().removeListener(focusedListener);
                 }
             }
+
+            if (change.wasAdded() && "selectFirstRowByDefault".equals(change.getKey())) {
+                Boolean _selectFirstRowByDefault = (Boolean) change.getValueAdded();
+                if (_selectFirstRowByDefault == null) return;
+                selectFirstRowByDefault = _selectFirstRowByDefault;
+            }
         });
     }
     
@@ -1276,10 +1296,15 @@
                 if (selectedItem != null) {
                     newValueIndex = newList.indexOf(selectedItem);
                 }
+
+                // we put selection onto the first item, if there is at least
+                // one item in the list
+                if (listView.selectFirstRowByDefault && newValueIndex == -1) {
+                    newValueIndex = newList.size() > 0 ? 0 : -1;
+                }
             }
 
-            setSelectedIndex(newValueIndex);
-            focus(newValueIndex);
+            select(newValueIndex);
         }
 
 
@@ -1410,6 +1435,12 @@
          **********************************************************************/
 
         /** {@inheritDoc} */
+        @Override public void clearAndSelect(int row) {
+            ListCellBehavior.setAnchor(listView, row, false);
+            super.clearAndSelect(row);
+        }
+
+        /** {@inheritDoc} */
         @Override protected void focus(int row) {
             if (listView.getFocusModel() == null) return;
             listView.getFocusModel().focus(row);
--- a/modules/controls/src/main/java/javafx/scene/control/TablePosition.java	Thu Aug 28 11:16:55 2014 +1200
+++ b/modules/controls/src/main/java/javafx/scene/control/TablePosition.java	Fri Aug 29 13:44:39 2014 +1200
@@ -26,6 +26,8 @@
 package javafx.scene.control;
 
 import java.lang.ref.WeakReference;
+import java.util.List;
+
 import javafx.beans.NamedArg;
 
 /**
@@ -67,8 +69,10 @@
     public TablePosition(@NamedArg("tableView") TableView<S> tableView, @NamedArg("row") int row, @NamedArg("tableColumn") TableColumn<S,T> tableColumn) {
         super(row, tableColumn);
         this.controlRef = new WeakReference<>(tableView);
+
+        List<S> items = tableView.getItems();
         this.itemRef = new WeakReference<>(
-                row >= 0 && row < tableView.getItems().size() ? tableView.getItems().get(row) : null);
+                items != null && row >= 0 && row < items.size() ? items.get(row) : null);
     }
     
     
--- a/modules/controls/src/main/java/javafx/scene/control/TableView.java	Thu Aug 28 11:16:55 2014 +1200
+++ b/modules/controls/src/main/java/javafx/scene/control/TableView.java	Fri Aug 29 13:44:39 2014 +1200
@@ -30,6 +30,7 @@
 
 import com.sun.javafx.scene.control.Logging;
 import com.sun.javafx.scene.control.SelectedCellsMap;
+import com.sun.javafx.scene.control.behavior.TableCellBehavior;
 import javafx.beans.DefaultProperty;
 import javafx.beans.InvalidationListener;
 import javafx.beans.WeakInvalidationListener;
@@ -2066,10 +2067,16 @@
                 if (selectedItem != null) {
                     newValueIndex = newList.indexOf(selectedItem);
                 }
+
+                // we put selection onto the first item, if there is at least
+                // one item in the list
+                if (newValueIndex == -1) {
+                    newValueIndex = newList.size() > 0 ? 0 : -1;
+                }
             }
 
-            setSelectedIndex(newValueIndex);
-            focus(newValueIndex);
+            TableColumn<S,?> firstColumn = getTableColumn(0);
+            select(newValueIndex, isCellSelectionEnabled() ? firstColumn : null);
         }
         
 
@@ -2252,6 +2259,11 @@
         @Override public void clearAndSelect(int row, TableColumn<S,?> column) {
             if (row < 0 || row >= getItemCount()) return;
 
+            final TablePosition<S,?> newTablePosition = new TablePosition<>(getTableView(), row, column);
+
+            // replace the anchor
+            TableCellBehavior.setAnchor(tableView, newTablePosition, false);
+
             // RT-33558 if this method has been called with a given row/column
             // intersection, and that row/column intersection is the only
             // selection currently, then this method becomes a no-op.
@@ -2285,9 +2297,9 @@
 
             // fire off a single add/remove/replace notification (rather than
             // individual remove and add notifications) - see RT-33324
-            int changeIndex = selectedCellsSeq.indexOf(new TablePosition<>(getTableView(), row, column));
-            ListChangeListener.Change change = new NonIterableChange.GenericAddRemoveChange<TablePosition<S,?>>(
-                    changeIndex, changeIndex+1, previousSelection, selectedCellsSeq);
+            int changeIndex = selectedCellsSeq.indexOf(newTablePosition);
+            ListChangeListener.Change change = new NonIterableChange.GenericAddRemoveChange<>(
+                    changeIndex, changeIndex + 1, previousSelection, selectedCellsSeq);
             handleSelectedCellsListChangeEvent(change);
         }
 
@@ -2306,7 +2318,13 @@
             TablePosition<S,?> pos = new TablePosition<>(getTableView(), row, column);
             
             if (getSelectionMode() == SelectionMode.SINGLE) {
+                startAtomic();
                 quietClearSelection();
+                stopAtomic();
+            }
+
+            if (TableCellBehavior.hasDefaultAnchor(tableView)) {
+                TableCellBehavior.removeAnchor(tableView);
             }
 
             selectedCellsMap.add(pos);
--- a/modules/controls/src/main/java/javafx/scene/control/TreeTableView.java	Thu Aug 28 11:16:55 2014 +1200
+++ b/modules/controls/src/main/java/javafx/scene/control/TreeTableView.java	Fri Aug 29 13:44:39 2014 +1200
@@ -30,6 +30,7 @@
 import com.sun.javafx.collections.annotations.ReturnsUnmodifiableCollection;
 import com.sun.javafx.scene.control.SelectedCellsMap;
 
+import com.sun.javafx.scene.control.behavior.TreeTableCellBehavior;
 import javafx.beans.property.DoubleProperty;
 import javafx.css.CssMetaData;
 import javafx.css.PseudoClass;
@@ -2076,7 +2077,6 @@
         private final TreeTableView<S> treeTableView;
 
 
-
         /***********************************************************************
          *                                                                     *
          * Constructors                                                        *
@@ -2204,6 +2204,8 @@
 
         private final MappingChange.Map<TreeTablePosition<S,?>,Integer> cellToIndicesMap = f -> f.getRow();
 
+        private TreeTableView<S> treeTableView = null;
+
         /***********************************************************************
          *                                                                     *
          * Constructors                                                        *
@@ -2240,8 +2242,6 @@
             };
         }
         
-        private final TreeTableView<S> treeTableView;
-        
         private void updateTreeEventListener(TreeItem<S> oldRoot, TreeItem<S> newRoot) {
             if (oldRoot != null && weakTreeItemListener != null) {
                 oldRoot.removeEventHandler(TreeItem.<S>expandedItemCountChangeEvent(), weakTreeItemListener);
@@ -2255,6 +2255,11 @@
         
         private ChangeListener<TreeItem<S>> rootPropertyListener = (observable, oldValue, newValue) -> {
             clearSelection();
+
+            int newValueIndex = getItemCount() > 0 ? 0 : -1;
+            TreeTableColumn<S,?> firstColumn = getTableColumn(0);
+            select(newValueIndex, isCellSelectionEnabled() ? firstColumn : null);
+
             updateTreeEventListener(oldValue, newValue);
         };
         
@@ -2467,6 +2472,11 @@
         @Override public void clearAndSelect(int row, TableColumnBase<TreeItem<S>,?> column) {
             if (row < 0 || row >= getItemCount()) return;
 
+            final TreeTablePosition<S,?> newTablePosition = new TreeTablePosition<>(getTreeTableView(), row, (TreeTableColumn<S,?>)column);
+
+            // replace the anchor
+            TreeTableCellBehavior.setAnchor(treeTableView, newTablePosition, false);
+
             // RT-33558 if this method has been called with a given row/column
             // intersection, and that row/column intersection is the only
             // selection currently, then this method becomes a no-op.
@@ -2500,9 +2510,9 @@
 
             // fire off a single add/remove/replace notification (rather than
             // individual remove and add notifications) - see RT-33324
-            int changeIndex = selectedCellsSeq.indexOf(new TreeTablePosition<>(getTreeTableView(), row, (TreeTableColumn<S,?>)column));
+            int changeIndex = selectedCellsSeq.indexOf(newTablePosition);
             ListChangeListener.Change<TreeTablePosition<S,?>> change = new NonIterableChange.GenericAddRemoveChange<>(
-                    changeIndex, changeIndex+1, previousSelection, selectedCellsSeq);
+                    changeIndex, changeIndex + 1, previousSelection, selectedCellsSeq);
             handleSelectedCellsListChangeEvent(change);
         }
 
@@ -2521,7 +2531,13 @@
             TreeTablePosition<S,?> pos = new TreeTablePosition<>(getTreeTableView(), row, (TreeTableColumn<S,?>)column);
             
             if (getSelectionMode() == SelectionMode.SINGLE) {
+                startAtomic();
                 quietClearSelection();
+                stopAtomic();
+            }
+
+            if (TreeTableCellBehavior.hasDefaultAnchor(treeTableView)) {
+                TreeTableCellBehavior.removeAnchor(treeTableView);
             }
 
             selectedCellsMap.add(pos);
@@ -3030,7 +3046,7 @@
                         TreeTablePosition<S,?> added = c.getAddedSubList().get(j);
                         TreeItem<S> addedTreeItem = added.getTreeItem();
 
-                        if (removedTreeItem.equals(addedTreeItem)) {
+                        if (removedTreeItem != null && removedTreeItem.equals(addedTreeItem)) {
                             matchFound = true;
                             break;
                         }
--- a/modules/controls/src/main/java/javafx/scene/control/TreeView.java	Thu Aug 28 11:16:55 2014 +1200
+++ b/modules/controls/src/main/java/javafx/scene/control/TreeView.java	Fri Aug 29 13:44:39 2014 +1200
@@ -26,6 +26,7 @@
 package javafx.scene.control;
 
 import com.sun.javafx.css.converters.SizeConverter;
+import com.sun.javafx.scene.control.behavior.TreeCellBehavior;
 import com.sun.javafx.scene.control.skin.TreeViewSkin;
 
 import javafx.application.Platform;
@@ -1218,6 +1219,16 @@
 
         /***********************************************************************
          *                                                                     *
+         * Internal fields                                                     *
+         *                                                                     *
+         **********************************************************************/
+
+        private TreeView<T> treeView = null;
+
+
+
+        /***********************************************************************
+         *                                                                     *
          * Constructors                                                        *
          *                                                                     *
          **********************************************************************/
@@ -1231,6 +1242,8 @@
             this.treeView.rootProperty().addListener(weakRootPropertyListener);
                     
             updateTreeEventListener(null, treeView.getRoot());
+
+            TreeCellBehavior.setAnchor(treeView, 0, true);
         }
         
         private void updateTreeEventListener(TreeItem<T> oldRoot, TreeItem<T> newRoot) {
@@ -1246,6 +1259,11 @@
         
         private ChangeListener<TreeItem<T>> rootPropertyListener = (observable, oldValue, newValue) -> {
             clearSelection();
+
+            // if we can, we put selection onto the first row
+            int newValueIndex = getItemCount() > 0 ? 0 : -1;
+            select(newValueIndex);
+
             updateTreeEventListener(oldValue, newValue);
         };
         
@@ -1356,16 +1374,7 @@
         private WeakEventHandler<TreeModificationEvent<T>> weakTreeItemListener;
 
 
-        /***********************************************************************
-         *                                                                     *
-         * Internal properties                                                 *
-         *                                                                     *
-         **********************************************************************/
 
-        private final TreeView<T> treeView;
-
-
-        
         /***********************************************************************
          *                                                                     *
          * Public selection API                                                *
@@ -1414,6 +1423,11 @@
             }
         }
 
+        /** {@inheritDoc} */
+        @Override public void clearAndSelect(int row) {
+            TreeCellBehavior.setAnchor(treeView, row, false);
+            super.clearAndSelect(row);
+        }
 
 
         /***********************************************************************
--- a/modules/controls/src/test/java/javafx/scene/control/ListViewTest.java	Thu Aug 28 11:16:55 2014 +1200
+++ b/modules/controls/src/test/java/javafx/scene/control/ListViewTest.java	Fri Aug 29 13:44:39 2014 +1200
@@ -52,6 +52,7 @@
 import javafx.event.ActionEvent;
 import javafx.event.Event;
 import javafx.event.EventHandler;
+import javafx.scene.Scene;
 import javafx.scene.control.cell.CheckBoxListCell;
 import javafx.scene.control.cell.ComboBoxListCell;
 import javafx.scene.control.cell.TextFieldListCell;
@@ -267,8 +268,8 @@
         assertEquals("Item 1", sm.getSelectedItem());
 
         listView.setItems(FXCollections.observableArrayList("Item 2"));
-        assertEquals(-1, sm.getSelectedIndex());
-        assertEquals(null, sm.getSelectedItem());
+        assertEquals(0, sm.getSelectedIndex());
+        assertEquals("Item 2", sm.getSelectedItem());
     }
 
     @Test public void test_rt15793() {
@@ -793,8 +794,8 @@
 
         StageLoader sl = new StageLoader(listView);
 
-        // everything should be null to start with
-        assertNull(listView.getSelectionModel().getSelectedItem());
+        // selection starts off on row 0
+        assertEquals("aabbaa", listView.getSelectionModel().getSelectedItem());
 
         // select "bbc" and ensure everything is set to that
         listView.getSelectionModel().select(1);
@@ -868,8 +869,8 @@
         // test initial state
         assertEquals(sl.getStage().getScene().getFocusOwner(), focusBtn);
         assertTrue(focusBtn.isFocused());
-        assertEquals(-1, sm.getSelectedIndex());
-        assertNull(sm.getSelectedItem());
+        assertEquals(0, sm.getSelectedIndex());
+        assertEquals("A", sm.getSelectedItem());
 
         // move focus to the listview
         listView.requestFocus();
@@ -1032,4 +1033,30 @@
             });
         });
     }
+
+    @Test public void test_rt_37632() {
+        final ObservableList<String> listOne = FXCollections.observableArrayList("A", "B", "C");
+        final ObservableList<String> listTwo = FXCollections.observableArrayList("C");
+
+        final ListView<String> listView = new ListView<>();
+        MultipleSelectionModel<String> sm = listView.getSelectionModel();
+        listView.setItems(listOne);
+        listView.getSelectionModel().selectFirst();
+
+        assertEquals(0, sm.getSelectedIndex());
+        assertEquals("A", sm.getSelectedItem());
+        assertEquals(1, sm.getSelectedIndices().size());
+        assertEquals(0, (int) sm.getSelectedIndices().get(0));
+        assertEquals(1, sm.getSelectedItems().size());
+        assertEquals("A", sm.getSelectedItems().get(0));
+
+        listView.setItems(listTwo);
+
+        assertEquals(0, sm.getSelectedIndex());
+        assertEquals("C", sm.getSelectedItem());
+        assertEquals(1, sm.getSelectedIndices().size());
+        assertEquals(0, (int) sm.getSelectedIndices().get(0));
+        assertEquals(1, sm.getSelectedItems().size());
+        assertEquals("C", sm.getSelectedItems().get(0));
+    }
 }
\ No newline at end of file
--- a/modules/controls/src/test/java/javafx/scene/control/TableViewTest.java	Thu Aug 28 11:16:55 2014 +1200
+++ b/modules/controls/src/test/java/javafx/scene/control/TableViewTest.java	Fri Aug 29 13:44:39 2014 +1200
@@ -284,8 +284,8 @@
         assertEquals("Item 1", sm.getSelectedItem());
         
         table.setItems(FXCollections.observableArrayList("Item 2"));
-        assertEquals(-1, sm.getSelectedIndex());
-        assertEquals(null, sm.getSelectedItem());
+        assertEquals(0, sm.getSelectedIndex());
+        assertEquals("Item 2", sm.getSelectedItem());
     }
 
     /*********************************************************************
@@ -1525,10 +1525,12 @@
                 ccc = new Person("CCC", "Giles", "jim.bob@example.com")
         ));
 
-        final TableSelectionModel sm = table.getSelectionModel();
+        final TableView.TableViewSelectionModel sm = table.getSelectionModel();
 
         // test pre-conditions
-        assertTrue(sm.isEmpty());
+        assertEquals(1, sm.getSelectedCells().size());
+        assertEquals(1, sm.getSelectedItems().size());
+        assertEquals(1, sm.getSelectedIndices().size());
 
         // select the 3rd row (that is, CCC)
         sm.select(2);
@@ -2569,8 +2571,8 @@
 
         StageLoader sl = new StageLoader(tableView);
 
-        // everything should be null to start with
-        assertNull(tableView.getSelectionModel().getSelectedItem());
+        // selection starts off at row 0
+        assertEquals("aabbaa", tableView.getSelectionModel().getSelectedItem());
 
         // select "bbc" and ensure everything is set to that
         tableView.getSelectionModel().select(1);
@@ -3809,4 +3811,34 @@
             });
         });
     }
+
+    @Test public void test_rt_37632() {
+        final ObservableList<String> listOne = FXCollections.observableArrayList("A", "B", "C");
+        final ObservableList<String> listTwo = FXCollections.observableArrayList("C");
+
+        TableColumn<String,String> tableColumn = new TableColumn("column");
+        tableColumn.setCellValueFactory(c -> new ReadOnlyStringWrapper(c.getValue()));
+
+        final TableView<String> tableView = new TableView<>();
+        tableView.getColumns().add(tableColumn);
+        MultipleSelectionModel<String> sm = tableView.getSelectionModel();
+        tableView.setItems(listOne);
+        tableView.getSelectionModel().selectFirst();
+
+        assertEquals(0, sm.getSelectedIndex());
+        assertEquals("A", sm.getSelectedItem());
+        assertEquals(1, sm.getSelectedIndices().size());
+        assertEquals(0, (int) sm.getSelectedIndices().get(0));
+        assertEquals(1, sm.getSelectedItems().size());
+        assertEquals("A", sm.getSelectedItems().get(0));
+
+        tableView.setItems(listTwo);
+
+        assertEquals(0, sm.getSelectedIndex());
+        assertEquals("C", sm.getSelectedItem());
+        assertEquals(1, sm.getSelectedIndices().size());
+        assertEquals(0, (int) sm.getSelectedIndices().get(0));
+        assertEquals(1, sm.getSelectedItems().size());
+        assertEquals("C", sm.getSelectedItems().get(0));
+    }
 }
--- a/modules/controls/src/test/java/javafx/scene/control/TreeTableViewKeyInputTest.java	Thu Aug 28 11:16:55 2014 +1200
+++ b/modules/controls/src/test/java/javafx/scene/control/TreeTableViewKeyInputTest.java	Fri Aug 29 13:44:39 2014 +1200
@@ -218,9 +218,15 @@
      **************************************************************************/    
     
     @Test public void testInitialState() {
-        assertTrue(sm.getSelectedCells().isEmpty());
-        assertTrue(sm.getSelectedIndices().isEmpty());
-        assertTrue(sm.getSelectedItems().isEmpty());
+        assertEquals(0, sm.getSelectedIndex());
+
+        assertEquals(1, sm.getSelectedCells().size());
+
+        assertEquals(1, sm.getSelectedIndices().size());
+        assertEquals(0, (int) sm.getSelectedIndices().get(0));
+
+        assertEquals(1, sm.getSelectedItems().size());
+        assertEquals(root, sm.getSelectedItems().get(0));
     }
     
     
@@ -444,9 +450,8 @@
         keyboard.doDownArrowPress(KeyModifier.SHIFT);
         keyboard.doDownArrowPress(KeyModifier.SHIFT);
         keyboard.doUpArrowPress(KeyModifier.SHIFT);
-        assertTrue(debug(), sm.isSelected(0));
-        assertTrue(sm.isSelected(1));
-        assertFalse(sm.isSelected(2));
+        assertTrue(debug(), isSelected(0, 1));
+        assertTrue(debug(), isNotSelected(2));
     }
     
     @Test public void testShiftUpTwiceThenShiftDownFrom0Index() {
@@ -1423,7 +1428,7 @@
         for (int i = 0; i <= 5; i++) {
             assertTrue(sm.isSelected(i,col1));
         }
-        assertTrue(isAnchor(5,1));
+        assertTrue(debug(), isAnchor(5,1));
         
         keyboard.doKeyPress(KeyCode.END, KeyModifier.SHIFT, KeyModifier.getShortcutKey());
         for (int i = 0; i < tableView.getExpandedItemCount() - 1; i++) {
@@ -2196,7 +2201,7 @@
         sm.clearAndSelect(5);                          
 
         keyboard.doKeyPress(KeyCode.HOME, KeyModifier.SHIFT); 
-        assertTrue(isSelected(0,1,2,3,4,5));
+        assertTrue(debug(), isSelected(0,1,2,3,4,5));
         assertTrue(isNotSelected(6,7,8,9));
         
         keyboard.doKeyPress(KeyCode.END, KeyModifier.SHIFT); 
@@ -3307,7 +3312,7 @@
         keyboard.doKeyPress(KeyCode.RIGHT, KeyModifier.SHIFT); // col 3
         keyboard.doKeyPress(KeyCode.RIGHT, KeyModifier.SHIFT); // col 4
         assertEquals(0, getAnchor().getRow());
-        assertEquals(0, getAnchor().getColumn());              // anchor does not move
+        assertEquals(debug(), 0, getAnchor().getColumn());              // anchor does not move
         assertTrue(fm.isFocused(0, col4));
         assertTrue(sm.isSelected(0, col0));
         assertTrue(sm.isSelected(0, col1));
@@ -4003,7 +4008,10 @@
         // get the current exception handler before replacing with our own,
         // as ListListenerHelp intercepts the exception otherwise
         final Thread.UncaughtExceptionHandler exceptionHandler = Thread.currentThread().getUncaughtExceptionHandler();
-        Thread.currentThread().setUncaughtExceptionHandler((t, e) -> fail("We don't expect any exceptions in this test!"));
+        Thread.currentThread().setUncaughtExceptionHandler((t, e) -> {
+            e.printStackTrace();
+            fail("We don't expect any exceptions in this test!");
+        });
 
         final int items = 10;
         root.getChildren().clear();
--- a/modules/controls/src/test/java/javafx/scene/control/TreeTableViewMouseInputTest.java	Thu Aug 28 11:16:55 2014 +1200
+++ b/modules/controls/src/test/java/javafx/scene/control/TreeTableViewMouseInputTest.java	Fri Aug 29 13:44:39 2014 +1200
@@ -432,7 +432,7 @@
             root.getChildren().add(new TreeItem<>("Row " + i));
         }
 
-        StageLoader sl = new StageLoader(tableView);
+//        StageLoader sl = new StageLoader(tableView);
 
         tableView.setShowRoot(true);
         final MultipleSelectionModel sm = tableView.getSelectionModel();
@@ -451,9 +451,9 @@
         VirtualFlowTestUtils.clickOnRow(tableView, 0, true, KeyModifier.SHIFT);
         assertEquals(0, sm.getSelectedIndex());
         assertEquals(0, fm.getFocusedIndex());
-        assertEquals(1, sm.getSelectedItems().size());
+        assertEquals(debug(), 1, sm.getSelectedItems().size());
 
-        sl.dispose();
+//        sl.dispose();
     }
 
     @Test public void test_rt_32963() {
--- a/modules/controls/src/test/java/javafx/scene/control/TreeTableViewSelectionModelImplTest.java	Thu Aug 28 11:16:55 2014 +1200
+++ b/modules/controls/src/test/java/javafx/scene/control/TreeTableViewSelectionModelImplTest.java	Fri Aug 29 13:44:39 2014 +1200
@@ -737,6 +737,7 @@
         assertEquals("item - 0", item0.getValue());
         item0.setExpanded(true);
 
+        model.clearSelection();
         model.selectIndices(1,2,3);
         assertEquals(3, model.getSelectedCells().size());
 
--- a/modules/controls/src/test/java/javafx/scene/control/TreeTableViewTest.java	Thu Aug 28 11:16:55 2014 +1200
+++ b/modules/controls/src/test/java/javafx/scene/control/TreeTableViewTest.java	Fri Aug 29 13:44:39 2014 +1200
@@ -885,7 +885,7 @@
         installChildren();
         TreeItem<String> element = new TreeItem<String>("I AM A CRAZY RANDOM STRING");
         treeTableView.getSelectionModel().select(element);
-        assertEquals(-1, treeTableView.getSelectionModel().getSelectedIndex());
+        assertEquals(0, treeTableView.getSelectionModel().getSelectedIndex());
         assertSame(element, treeTableView.getSelectionModel().getSelectedItem());
     }
 
@@ -946,10 +946,11 @@
         installChildren();
         treeTableView.getSelectionModel().select(0);
         assertEquals(root, treeTableView.getSelectionModel().getSelectedItem());
-        
-        treeTableView.setRoot(new TreeItem<String>("New Root"));
-        assertEquals(-1, treeTableView.getSelectionModel().getSelectedIndex());
-        assertEquals(null, treeTableView.getSelectionModel().getSelectedItem());
+
+        TreeItem newRoot = new TreeItem<String>("New Root");
+        treeTableView.setRoot(newRoot);
+        assertEquals(0, treeTableView.getSelectionModel().getSelectedIndex());
+        assertEquals(newRoot, treeTableView.getSelectionModel().getSelectedItem());
     }
     
     @Test public void ensureSelectionRemainsOnBranchWhenExpanded() {
@@ -1222,8 +1223,8 @@
         root.setExpanded(true);
         root.getChildren().setAll(child1, child2, child3);
         treeTableView.setRoot(root);
-        assertEquals(-1, treeTableView.getSelectionModel().getSelectedIndex());
-        assertNull(treeTableView.getSelectionModel().getSelectedItem());
+        assertEquals(0, treeTableView.getSelectionModel().getSelectedIndex());
+        assertEquals(root, treeTableView.getSelectionModel().getSelectedItem());
     }
     
     @Test public void test_rt27181() {
@@ -1491,13 +1492,8 @@
         assertEquals(p4, root.getChildren().get(4));
         
         // set a new comparator
-        firstNameCol.setComparator(new Comparator() {
-            Random r =  new Random();
-            @Override public int compare(Object t, Object t1) {
-                return t.toString().compareTo(t1.toString());
-            }
-        });
-        
+        firstNameCol.setComparator((t, t1) -> t.toString().compareTo(t1.toString()));
+
         // ensure the new order is as expected
         assertEquals(p0, root.getChildren().get(0));
         assertEquals(p1, root.getChildren().get(1));
@@ -1970,13 +1966,14 @@
         myCompanyRootNode.setExpanded(true);
         salesDepartment.setExpanded(true);
         itSupport.setExpanded(true);
+        sm.clearSelection();
         sm.selectIndices(8, 9, 10);     // itSupport, and two people
         assertFalse(sm.isSelected(1));  // salesDepartment
         assertTrue(sm.isSelected(8));   // itSupport
         assertTrue(sm.isSelected(9));   // mikeGraham
         assertTrue(sm.isSelected(10));  // judyMayer
         assertTrue(treeTableView.getFocusModel().isFocused(10));
-        assertEquals(3, sm.getSelectedIndices().size());
+        assertEquals(debug(), 3, sm.getSelectedIndices().size());
         
         salesDepartment.setExpanded(false);
         assertTrue(debug(), sm.isSelected(2));   // itSupport
@@ -2014,6 +2011,7 @@
         myCompanyRootNode.setExpanded(true);
         salesDepartment.setExpanded(false);
         itSupport.setExpanded(true);
+        sm.clearSelection();
         sm.selectIndices(2,3,4);     // itSupport, and two people
         assertFalse(sm.isSelected(1));  // salesDepartment
         assertTrue(sm.isSelected(2));   // itSupport
@@ -2303,7 +2301,9 @@
         treeTableView.getColumns().add(col);
 
         // test pre-conditions
-        assertTrue(sm.isEmpty());
+        assertEquals(1, sm.getSelectedCells().size());
+        assertEquals(1, sm.getSelectedItems().size());
+        assertEquals(1, sm.getSelectedIndices().size());
 
         // select the 4th row (that is, the third child of the root)
         sm.select(3);
@@ -3108,19 +3108,20 @@
     }
 
     @Test public void test_rt35039_setRoot() {
+        TreeItem aabbaa = new TreeItem("aabbaa");
+        TreeItem bbc = new TreeItem("bbc");
+
         TreeItem<String> root = new TreeItem<>("Root");
         root.setExpanded(true);
-        root.getChildren().addAll(
-                new TreeItem("aabbaa"),
-                new TreeItem("bbc"));
+        root.getChildren().setAll(aabbaa, bbc);
 
         final TreeTableView<String> treeView = new TreeTableView<>();
         treeView.setRoot(root);
 
         StageLoader sl = new StageLoader(treeView);
 
-        // everything should be null to start with
-        assertNull(treeView.getSelectionModel().getSelectedItem());
+        // Selection starts in row 0
+        assertEquals(root, treeView.getSelectionModel().getSelectedItem());
 
         // select "bbc" and ensure everything is set to that
         treeView.getSelectionModel().select(2);
@@ -3147,8 +3148,8 @@
 
         StageLoader sl = new StageLoader(treeView);
 
-        // everything should be null to start with
-        assertNull(treeView.getSelectionModel().getSelectedItem());
+        // Selection starts in row 0
+        assertEquals(root, treeView.getSelectionModel().getSelectedItem());
 
         // select "bbc" and ensure everything is set to that
         treeView.getSelectionModel().select(2);
@@ -3900,4 +3901,34 @@
             });
         });
     }
+
+    @Test public void test_rt_37632() {
+        final TreeItem<String> rootOne = new TreeItem<>("Root 1");
+        final TreeItem<String> rootTwo = new TreeItem<>("Root 2");
+
+        TreeTableColumn<String,String> tableColumn = new TreeTableColumn("column");
+        tableColumn.setCellValueFactory(c -> new ReadOnlyStringWrapper(c.getValue().getValue()));
+
+        final TreeTableView<String> treeTableView = new TreeTableView<>();
+        treeTableView.getColumns().addAll(tableColumn);
+        MultipleSelectionModel<TreeItem<String>> sm = treeTableView.getSelectionModel();
+        treeTableView.setRoot(rootOne);
+        treeTableView.getSelectionModel().selectFirst();
+
+        assertEquals(0, sm.getSelectedIndex());
+        assertEquals(rootOne, sm.getSelectedItem());
+        assertEquals(1, sm.getSelectedIndices().size());
+        assertEquals(0, (int) sm.getSelectedIndices().get(0));
+        assertEquals(1, sm.getSelectedItems().size());
+        assertEquals(rootOne, sm.getSelectedItems().get(0));
+
+        treeTableView.setRoot(rootTwo);
+
+        assertEquals(0, sm.getSelectedIndex());
+        assertEquals(rootTwo, sm.getSelectedItem());
+        assertEquals(1, sm.getSelectedIndices().size());
+        assertEquals(0, (int) sm.getSelectedIndices().get(0));
+        assertEquals(1, sm.getSelectedItems().size());
+        assertEquals(rootTwo, sm.getSelectedItems().get(0));
+    }
 }
--- a/modules/controls/src/test/java/javafx/scene/control/TreeViewKeyInputTest.java	Thu Aug 28 11:16:55 2014 +1200
+++ b/modules/controls/src/test/java/javafx/scene/control/TreeViewKeyInputTest.java	Fri Aug 29 13:44:39 2014 +1200
@@ -177,8 +177,11 @@
      **************************************************************************/    
     
     @Test public void testInitialState() {
-        assertTrue(sm.getSelectedIndices().isEmpty());
-        assertTrue(sm.getSelectedItems().isEmpty());
+        assertEquals(0, sm.getSelectedIndex());
+        assertEquals(1, sm.getSelectedIndices().size());
+        assertEquals(0, (int) sm.getSelectedIndices().get(0));
+        assertEquals(1, sm.getSelectedItems().size());
+        assertEquals(root, sm.getSelectedItems().get(0));
     }
     
     /***************************************************************************
@@ -1867,6 +1870,7 @@
         final MultipleSelectionModel sm = treeView.getSelectionModel();
 
         sm.clearAndSelect(0);
+        assertEquals(0, fm.getFocusedIndex());
         assertEquals(0, getAnchor());
 
         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.getShortcutKey());
@@ -1880,7 +1884,7 @@
 
         keyboard.doKeyPress(KeyCode.SPACE,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
         Toolkit.getToolkit().firePulse();
-        assertTrue(isSelected(0,1,2,3));
+        assertTrue(debug(), isSelected(0,1,2,3));
         assertEquals(4, sm.getSelectedItems().size());
         assertTrue(fm.isFocused(3));
     }
--- a/modules/controls/src/test/java/javafx/scene/control/TreeViewTest.java	Thu Aug 28 11:16:55 2014 +1200
+++ b/modules/controls/src/test/java/javafx/scene/control/TreeViewTest.java	Fri Aug 29 13:44:39 2014 +1200
@@ -250,7 +250,7 @@
         installChildren();
         TreeItem<String> element = new TreeItem<String>("I AM A CRAZY RANDOM STRING");
         treeView.getSelectionModel().select(element);
-        assertEquals(-1, treeView.getSelectionModel().getSelectedIndex());
+        assertEquals(0, treeView.getSelectionModel().getSelectedIndex());
         assertSame(element, treeView.getSelectionModel().getSelectedItem());
     }
 
@@ -311,10 +311,11 @@
         installChildren();
         treeView.getSelectionModel().select(0);
         assertEquals(root, treeView.getSelectionModel().getSelectedItem());
-        
-        treeView.setRoot(new TreeItem<String>("New Root"));
-        assertEquals(-1, treeView.getSelectionModel().getSelectedIndex());
-        assertEquals(null, treeView.getSelectionModel().getSelectedItem());
+
+        TreeItem newRoot = new TreeItem<String>("New Root");
+        treeView.setRoot(newRoot);
+        assertEquals(0, treeView.getSelectionModel().getSelectedIndex());
+        assertEquals(newRoot, treeView.getSelectionModel().getSelectedItem());
     }
     
     @Test public void ensureSelectionRemainsOnBranchWhenExpanded() {
@@ -563,8 +564,8 @@
         root.setExpanded(true);
         root.getChildren().setAll(child1, child2, child3);
         treeView.setRoot(root);
-        assertEquals(-1, treeView.getSelectionModel().getSelectedIndex());
-        assertNull(treeView.getSelectionModel().getSelectedItem());
+        assertEquals(0, treeView.getSelectionModel().getSelectedIndex());
+        assertEquals(root, treeView.getSelectionModel().getSelectedItem());
     }
     
     @Test public void test_rt27181() {
@@ -943,6 +944,8 @@
         sm.setSelectionMode(SelectionMode.MULTIPLE);
         
         treeView.setRoot(myCompanyRootNode);
+        treeView.getSelectionModel().clearSelection();
+
         myCompanyRootNode.setExpanded(true);
         salesDepartment.setExpanded(true);
         itSupport.setExpanded(true);
@@ -985,6 +988,8 @@
         sm.setSelectionMode(SelectionMode.MULTIPLE);
         
         treeView.setRoot(myCompanyRootNode);
+        treeView.getSelectionModel().clearSelection();
+
         myCompanyRootNode.setExpanded(true);
         salesDepartment.setExpanded(false);
         itSupport.setExpanded(true);
@@ -1220,6 +1225,7 @@
         assertEquals("item - 0", item0.getValue());
         item0.setExpanded(true);
 
+        treeView.getSelectionModel().clearSelection();
         treeView.getSelectionModel().selectIndices(1,2,3);
         assertEquals(3, treeView.getSelectionModel().getSelectedIndices().size());
 
@@ -1590,8 +1596,8 @@
 
         StageLoader sl = new StageLoader(treeView);
 
-        // everything should be null to start with
-        assertNull(treeView.getSelectionModel().getSelectedItem());
+        // We start with selection on row 0
+        assertEquals(root, treeView.getSelectionModel().getSelectedItem());
 
         // select "bbc" and ensure everything is set to that
         treeView.getSelectionModel().select(2);
@@ -1618,8 +1624,8 @@
 
         StageLoader sl = new StageLoader(treeView);
 
-        // everything should be null to start with
-        assertNull(treeView.getSelectionModel().getSelectedItem());
+        // We start with selection on row 0
+        assertEquals(root, treeView.getSelectionModel().getSelectedItem());
 
         // select "bbc" and ensure everything is set to that
         treeView.getSelectionModel().select(2);
@@ -2109,4 +2115,30 @@
             });
         });
     }
+
+    @Test public void test_rt_37632() {
+        final TreeItem<String> rootOne = new TreeItem<>("Root 1");
+        final TreeItem<String> rootTwo = new TreeItem<>("Root 2");
+
+        final TreeView<String> treeView = new TreeView<>();
+        MultipleSelectionModel<TreeItem<String>> sm = treeView.getSelectionModel();
+        treeView.setRoot(rootOne);
+        treeView.getSelectionModel().selectFirst();
+
+        assertEquals(0, sm.getSelectedIndex());
+        assertEquals(rootOne, sm.getSelectedItem());
+        assertEquals(1, sm.getSelectedIndices().size());
+        assertEquals(0, (int) sm.getSelectedIndices().get(0));
+        assertEquals(1, sm.getSelectedItems().size());
+        assertEquals(rootOne, sm.getSelectedItems().get(0));
+
+        treeView.setRoot(rootTwo);
+
+        assertEquals(0, sm.getSelectedIndex());
+        assertEquals(rootTwo, sm.getSelectedItem());
+        assertEquals(1, sm.getSelectedIndices().size());
+        assertEquals(0, (int) sm.getSelectedIndices().get(0));
+        assertEquals(1, sm.getSelectedItems().size());
+        assertEquals(rootTwo, sm.getSelectedItems().get(0));
+    }
 }