changeset 7949:258d08a27dc0

RT-38464: [TableView] Regression TableView: cannot start editing via keyboard
author jgiles
date Wed, 03 Sep 2014 12:12:43 +1200
parents e118f2891b38
children d702e4ad5227
files apps/toys/Hello/src/main/java/hello/HelloTableView.java modules/controls/src/main/java/com/sun/javafx/scene/control/SelectedCellsMap.java modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/TableCellBehaviorBase.java modules/controls/src/main/java/javafx/scene/control/ListCell.java modules/controls/src/main/java/javafx/scene/control/ListView.java modules/controls/src/main/java/javafx/scene/control/MultipleSelectionModelBase.java modules/controls/src/main/java/javafx/scene/control/TableCell.java modules/controls/src/main/java/javafx/scene/control/TableView.java modules/controls/src/main/java/javafx/scene/control/TreeCell.java modules/controls/src/main/java/javafx/scene/control/TreeTableCell.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/com/sun/javafx/scene/control/infrastructure/VirtualFlowTestUtils.java modules/controls/src/test/java/javafx/scene/control/ListCellTest.java modules/controls/src/test/java/javafx/scene/control/ListViewTest.java modules/controls/src/test/java/javafx/scene/control/MultipleSelectionModelImplTest.java modules/controls/src/test/java/javafx/scene/control/SelectionModelImplTest.java modules/controls/src/test/java/javafx/scene/control/TableViewKeyInputTest.java modules/controls/src/test/java/javafx/scene/control/TableViewMouseInputTest.java modules/controls/src/test/java/javafx/scene/control/TableViewSelectionModelImplTest.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/TreeViewTest.java
diffstat 26 files changed, 2479 insertions(+), 1050 deletions(-) [+]
line wrap: on
line diff
--- a/apps/toys/Hello/src/main/java/hello/HelloTableView.java	Tue Sep 02 15:32:15 2014 +1200
+++ b/apps/toys/Hello/src/main/java/hello/HelloTableView.java	Wed Sep 03 12:12:43 2014 +1200
@@ -22,10 +22,8 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
 package hello;
 
-
 import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.Comparator;
@@ -38,13 +36,12 @@
 import javafx.beans.InvalidationListener;
 import javafx.beans.binding.ObjectBinding;
 import javafx.beans.property.*;
-import javafx.beans.value.ObservableValue;
 import javafx.collections.FXCollections;
+import javafx.collections.ListChangeListener;
 import javafx.collections.ObservableList;
 import javafx.collections.transformation.SortedList;
 import javafx.collections.transformation.FilteredList;
 import javafx.geometry.Insets;
-import javafx.geometry.Pos;
 import javafx.scene.Group;
 import javafx.scene.Node;
 import javafx.scene.Scene;
@@ -63,15 +60,13 @@
 import javafx.scene.control.TableCell;
 import javafx.scene.control.TableColumn;
 import javafx.scene.control.TablePosition;
-import javafx.scene.control.TableRow;
 import javafx.scene.control.TableView;
 import javafx.scene.control.TextField;
 import javafx.scene.control.ToggleButton;
 import javafx.scene.control.ToggleGroup;
 import javafx.scene.control.cell.CheckBoxTableCell;
 import javafx.scene.control.cell.PropertyValueFactory;
-import javafx.scene.image.Image;
-import javafx.scene.image.ImageView;
+import javafx.scene.control.cell.TextFieldTableCell;
 import javafx.scene.input.KeyCode;
 import javafx.scene.layout.GridPane;
 import javafx.scene.layout.Priority;
@@ -213,104 +208,6 @@
         return data;
     }
 
-    private final static TableColumn<Person, String> firstNameCol;
-    private final static TableColumn<Person, String> lastNameCol;
-    private final static TableColumn<Person, String> nameCol;
-    private final static TableColumn<Person, String> emailCol;
-    private final static TableColumn<Person, String> countryCol;
-    private final static TableColumn<Person, Boolean> invitedCol;
-
-    static {
-
-        // Popup Menus
-//        emailMenu = new ContextMenu();
-//        MenuItem option1 = new MenuItem("Option 1");
-//        MenuItem option2 = new MenuItem("Option 2");
-//        emailMenu.getItems().addAll(option1, option2);
-        // -- Popup Menus
-
-
-        // Columns
-        // first name, last name, and wrapper parent column
-        firstNameCol = new TableColumn<>();
-        firstNameCol.setText("First");
-
-        Rectangle sortNode = new Rectangle(10, 10, Color.RED);
-        sortNode.fillProperty().bind(new ObjectBinding<Paint>() {
-            { bind(firstNameCol.sortTypeProperty()); }
-
-            @Override protected Paint computeValue() {
-                switch (firstNameCol.getSortType()) {
-                    case ASCENDING: return Color.GREEN;
-                    case DESCENDING: return Color.RED;
-                    default: return Color.BLACK;
-                }
-            }
-        });
-        firstNameCol.setSortNode(sortNode);
-//        firstNameCol.setMinWidth(300);
-//        firstNameCol.setProperty("firstName");
-//        firstNameCol.setCellFactory(TextFieldCellFactory.tableView());
-//        firstNameCol.setGetCellData(new Runnable2<Object, Integer, Integer>() {
-//            @Override public Object run(Integer row, Integer col) {
-//                return data.get(row).firstName;
-//            }
-//        });
-        firstNameCol.setCellValueFactory(new PropertyValueFactory<Person,String>("firstName"));
-//        firstNameCol.setCellValueFactory(new Callback<CellDataFeatures<Person,String>, ObservableValue<String>>() {
-//            public ObservableValue<String> call(CellDataFeatures<Person,String> p) {
-//                return p.getValue().firstName;
-//            }
-//        });
-        firstNameCol.setOnEditCommit(t -> System.out.println("Edit commit event: " + t.getNewValue()));
-
-//        final Node graphic1 = new ImageView(new Image("file:src/hello/about_16.png"));
-        lastNameCol = new TableColumn<Person, String>();
-//        lastNameCol.setGraphic(graphic1);
-        lastNameCol.setText("Last");
-//        lastNameCol.setResizable(false);
-//        lastNameCol.setProperty("lastName");
-        lastNameCol.setCellValueFactory(p -> p.getValue().lastNameProperty());
-
-        nameCol = new TableColumn<Person, String>();
-        nameCol.setText("Name");
-//        nameCol.setResizable(false);
-        nameCol.getColumns().addAll(firstNameCol, lastNameCol);
-        // -- end
-
-        emailCol = new TableColumn<Person, String>();
-        emailCol.setText("Email");
-//        emailCol.setContextMenu(emailMenu);
-        emailCol.setMinWidth(200);
-//        emailCol.setResizable(false);
-        emailCol.setCellValueFactory(p -> p.getValue().emailProperty());
-
-        countryCol = new TableColumn<Person, String>();
-        countryCol.setText("Country");
-        countryCol.setCellValueFactory(p -> new ReadOnlyObjectWrapper<String>("New Zealand"));
-//        countryCol.setProperty("country");
-
-        invitedCol = new TableColumn<Person, Boolean>();
-        invitedCol.setText("Invited");
-        invitedCol.setMaxWidth(50);
-        invitedCol.setCellValueFactory(new PropertyValueFactory("invited"));
-        invitedCol.setCellFactory(p -> new CheckBoxTableCell<Person, Boolean>());
-        invitedCol.setEditable(true);
-        /*
-        ContextMenu ctx = new ContextMenu();
-        final MenuItem cutMI    = new MenuItem("Cut");
-        final MenuItem copyMI   = new MenuItem("Copy");
-        final MenuItem pasteMI  = new MenuItem("Paste");
-        final MenuItem deleteMI = new MenuItem("DeleteSelection");
-        final MenuItem selectMI = new MenuItem("SelectAll");
-        final ContextMenu cm = new ContextMenu(cutMI, copyMI, pasteMI, deleteMI,
-                                               new SeparatorMenuItem(), selectMI);
-        invitedCol.setContextMenu(cm);
-        */
-        // -- Columns
-    }
-
-
     /**
      * @param args the command line arguments
      */
@@ -382,8 +279,56 @@
 
         ObservableList<Person> data = createTestData();
 
+        // build columns
+        // first name, last name, and wrapper parent column
+        TableColumn<Person, String> firstNameCol = new TableColumn<>();
+        firstNameCol.setText("First");
+
+        Rectangle sortNode = new Rectangle(10, 10, Color.RED);
+        sortNode.fillProperty().bind(new ObjectBinding<Paint>() {
+            { bind(firstNameCol.sortTypeProperty()); }
+
+            @Override protected Paint computeValue() {
+                switch (firstNameCol.getSortType()) {
+                    case ASCENDING: return Color.GREEN;
+                    case DESCENDING: return Color.RED;
+                    default: return Color.BLACK;
+                }
+            }
+        });
+        firstNameCol.setSortNode(sortNode);
+//        firstNameCol.setCellFactory(TextFieldCellFactory.tableView());
+        firstNameCol.setCellValueFactory(new PropertyValueFactory<>("firstName"));
+        firstNameCol.setOnEditCommit(t -> System.out.println("Edit commit event: " + t.getNewValue()));
+
+        TableColumn<Person, String> lastNameCol = new TableColumn<>();
+        lastNameCol.setText("Last");
+        lastNameCol.setCellValueFactory(p -> p.getValue().lastNameProperty());
+
+        TableColumn<Person, String> nameCol = new TableColumn<>();
+        nameCol.setText("Name");
+        nameCol.getColumns().addAll(firstNameCol, lastNameCol);
+        // -- end
+
+        TableColumn<Person, String> emailCol = new TableColumn<>();
+        emailCol.setText("Email");
+        emailCol.setMinWidth(200);
+        emailCol.setCellValueFactory(p -> p.getValue().emailProperty());
+
+        TableColumn<Person, String> countryCol = new TableColumn<>();
+        countryCol.setText("Country");
+        countryCol.setCellValueFactory(p -> new ReadOnlyObjectWrapper<>("New Zealand"));
+
+        TableColumn<Person, Boolean> invitedCol = new TableColumn<>();
+        invitedCol.setText("Invited");
+        invitedCol.setMaxWidth(50);
+        invitedCol.setCellValueFactory(new PropertyValueFactory("invited"));
+        invitedCol.setCellFactory(p -> new CheckBoxTableCell<>());
+        invitedCol.setEditable(true);
+        // -- Columns
+
         // simple table view
-        final TableView<Person> tableView = new TableView<Person>();
+        final TableView<Person> tableView = new TableView<>();
         tableView.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
         tableView.getSelectionModel().setCellSelectionEnabled(false);
         tableView.setTableMenuButtonVisible(false);
@@ -393,8 +338,6 @@
         tableView.setPrefSize(485, 300);
         tableView.setEditable(true);
 
-
-        ContextMenu ctx = new ContextMenu();
         final MenuItem cutMI    = new MenuItem("Cut");
         final MenuItem copyMI   = new MenuItem("Copy");
         final MenuItem pasteMI  = new MenuItem("Paste");
@@ -406,68 +349,15 @@
 
         tableView.setPlaceholder(new ProgressBar(-1));
 
-        tableView.setRowFactory(p -> new TableRow<Person>() {
-            @Override public void updateItem(Person item, boolean empty) {
-                super.updateItem(item, empty);
-
-                TableView.TableViewSelectionModel sm = tableView.getSelectionModel();
-
-                // get the row and column currently being editing
-                TablePosition editCell = tableView.getEditingCell();
-
-                // set the columns to only be shown if we aren't currently
-                // editing this row. If we are editing this row, we
-                // turn off the columns to show our custom node, which
-                // is set below.
-                boolean showColumns = sm == null ||
-                        sm.isCellSelectionEnabled() ||
-                        editCell == null ||
-                        editCell.getColumn() != -1 ||
-                        editCell.getRow() != getIndex();
-
-                if (showColumns) {
-                    setGraphic(null);
-                } else {
-                    Button stopEditingBtn = new Button("Stop editing");
-                    stopEditingBtn.setPrefSize(200, 50);
-                    stopEditingBtn.setOnAction(t -> tableView.edit(-1, null));
-                    setGraphic(stopEditingBtn);
-                }
-                setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
-            }
-        });
-
-//        tableView.setOnMouseClicked(new EventHandler<MouseEvent>() {
-//            @Override public void handle(MouseEvent event) {
-//                System.out.println("Clicked: " + ((TablePosition) tableView.getSelectionModel().getSelectedCells().get(0)).getTableColumn().getText());
-//                System.out.println("Clicked-2: " + tableView.getFocusModel().getFocusedCell().getTableColumn().getText());
-//            }
-//        });
-
-//        tableView.setOnEditStart(new EventHandler<EditEvent<Person>>() {
-//            @Override public void handle(EditEvent<Person> t) {
-//                System.out.println("Edit Start: " + t.getTablePosition());
-//            }
-//        });
-//        tableView.setOnEditCancel(new EventHandler<EditEvent<Person>>() {
-//            @Override public void handle(EditEvent<Person> t) {
-//                System.out.println("Edit Cancel: " + t.getTablePosition());
-//            }
-//        });
-//        tableView.setOnEditCommit(new EventHandler<EditEvent<Person>>() {
-//            @Override public void handle(EditEvent<Person> t) {
-//                System.out.println("Edit Commit: " + t);
-//            }
-//        });
-
-
         grid.getChildren().addAll(tableView);
         GridPane.setConstraints(tableView, 0, 0, 1, 12);
         GridPane.setVgrow(tableView, Priority.ALWAYS);
         GridPane.setHgrow(tableView, Priority.ALWAYS);
-        // --- simple listview
+        // --- simple tableview
 
 
+        firstNameCol.setCellFactory(TextFieldTableCell.forTableColumn());
+
 
 
         // add some controls to manipulate the table state
@@ -517,22 +407,6 @@
         // -- end of selection mode controls
 
         // toggles
-//        // nested columns Toggle
-//        final ToggleButton nestColumnsBtn = new ToggleButton("Nest Columns");
-//        nestColumnsBtn.setSelected(false);
-//        nestColumnsBtn.selectedProperty().addListener(new InvalidationListener() {
-//            public void invalidated(Observable ov) {
-//                if (nestColumnsBtn.isSelected()) {
-//                    tableView.getColumns().setAll(nameCol, emailCol, countryCol);
-//                } else {
-//                    tableView.getColumns().setAll(firstNameCol, lastNameCol, emailCol, countryCol);
-//                }
-////                firstNameCol.setVisible(! firstNameCol.isVisible());
-//            }
-//        });
-//        grid.getChildren().add(nestColumnsBtn);
-//        GridPane.setConstraints(nestColumnsBtn, 1, 4);
-//        // -- end of nested columns toggle
 
         // show/hide column control button
         final ToggleButton columnControlBtn = new ToggleButton("Column Control");
@@ -542,17 +416,6 @@
         GridPane.setConstraints(columnControlBtn, 1, 5);
         // -- end of show/hide column control button
 
-        // pannable button
-//        final ToggleButton pannableBtn = new ToggleButton("Pannable");
-//        pannableBtn.setSelected(true);
-//        pannableBtn.selectedProperty().addListener(new InvalidationListener() {
-//            public void invalidated(ObservableValue ov) {
-//                tableView.setPannable(pannableBtn.isSelected());
-//            }
-//        });
-//        grid.add(pannableBtn, 1, 6);
-        // -- end of pannable button
-
         // constrained resize button
         final ToggleButton constrainResizeBtn = new ToggleButton("Constrained Resize");
         constrainResizeBtn.setSelected(false);
@@ -613,13 +476,14 @@
 //            }
 //        });
 
-//        tableView.getSelectionModel().getSelectedCells().addListener(new ListChangeListener<TablePosition>() {
-//            public void onChanged(Change<? extends TablePosition> change) {
-//                System.out.println("SelectedIndices: " + change.getList() +
-//                        ", removed: " + change.getRemoved() +
-//                        ", addedFrom: " + change.getFrom() +
-//                        ", addedTo: " + change.getTo());
-//            }
+        tableView.getSelectionModel().getSelectedCells().addListener(new ListChangeListener<TablePosition>() {
+            public void onChanged(Change<? extends TablePosition> change) {
+                System.out.println(tableView.getSelectionModel().getSelectedCells() + "\n\n");
+            }
+        });
+
+//        tableView.getFocusModel().focusedCellProperty().addListener(o -> {
+//            System.out.println("Focused Cell: " + tableView.getFocusModel().getFocusedCell());
 //        });
     }
 
@@ -662,48 +526,6 @@
         return tableView;
     }
 
-
-//    private void buildCellsTab(Tab tab) {
-//        GridPane grid = new GridPane();
-//        grid.setPadding(new Insets(5, 5, 5, 5));
-//        grid.setHgap(5);
-//        grid.setVgap(5);
-//
-//        // add a complex listview (using pre-built cell factory)
-//        final ListView<Number> listView2 = new ListView<Number>();
-//        listView2.setItems(money);
-//        listView2.setCellFactory(MoneyFormatCellFactory.listView());
-//        grid.getChildren().add(listView2);
-//        GridPane.setVgrow(listView2, Priority.ALWAYS);
-//        GridPane.setConstraints(listView2, 0, 0);
-//        // --- complex listview
-//
-//        // add another complex listview (using pre-built cell factory)
-//        final ListView<Map<String, String>> listView3 = new ListView<Map<String, String>>();
-//        listView3.setItems(mapData);
-////        listView3.setCellFactory(Cells.ListView.mapProperty(FIRST_NAME));
-//        listView3.setCellFactory(MapValueCellFactory.listView("First Name: %1$s\r\nLast Name: %2$s", FIRST_NAME, LAST_NAME));
-//        grid.getChildren().add(listView3);
-//        GridPane.setVgrow(listView3, Priority.ALWAYS);
-//        GridPane.setConstraints(listView3, 1, 0);
-//        // --- complex listview
-//
-//        tab.setContent(grid);
-//    }
-//
-//
-//    private Comparator<String> alphabeticalComparator = new Comparator<String>() {
-//        @Override public int compare(String o1, String o2) {
-//            return o1.compareTo(o2);
-//        }
-//    };
-//
-//    private Comparator<String> reverseAlphabeticalComparator = new Comparator<String>() {
-//        @Override public int compare(String o1, String o2) {
-//            return o2.compareTo(o1);
-//        }
-//    };
-
     private void buildSortAndFilterTab(Tab tab) {
         // initially we match everything in the filter list
         Predicate<Person> NO_MATCHER = e -> true;
@@ -798,7 +620,7 @@
         // first name, last name, and wrapper parent column
         TableColumn<Person, String> firstNameCol = new TableColumn<>();
         firstNameCol.setText("First");
-        firstNameCol.setCellValueFactory(new PropertyValueFactory<Person,String>("firstName"));
+        firstNameCol.setCellValueFactory(new PropertyValueFactory<>("firstName"));
         firstNameCol.setOnEditCommit(t -> System.out.println("Edit commit event: " + t.getNewValue()));
 
         return firstNameCol;
@@ -811,10 +633,8 @@
         return lastNameCol;
     }
 
-
     private void buildPerformanceTestTab(Tab tab, boolean customCell) {
         GridPane grid = new GridPane();
-//        grid.setGridLinesVisible(true);
         grid.setPadding(new Insets(5, 5, 5, 5));
         grid.setHgap(5);
         grid.setVgap(5);
@@ -856,9 +676,8 @@
     }
 
     public void getLines(ObservableList<List<Double>> bigData) {
-//        List<List<Double>> data = new ArrayList<List<Double>>();
         for (int row = 0; row < NB_LINE; row++) {
-            List<Double> line = new ArrayList<Double>();
+            List<Double> line = new ArrayList<>();
             for (int col = 0; col <= NB_COL; col++) {
                 if(col == 0) line.add((double)row);
                 else line.add(Math.random() * 1000);
@@ -867,13 +686,12 @@
         }
     }
 
-
     public List<TableColumn<List<Double>,Double>> getColumns(boolean customCell) {
-        List<TableColumn<List<Double>,Double>> cols = new ArrayList<TableColumn<List<Double>,Double>>();
+        List<TableColumn<List<Double>,Double>> cols = new ArrayList<>();
         for (int i = 0; i <= NB_COL; i++) {
-            TableColumn<List<Double>,Double> col = new TableColumn<List<Double>,Double>("Col" + i);
+            TableColumn<List<Double>,Double> col = new TableColumn<>("Col" + i);
             final int coli = i;
-            col.setCellValueFactory(p -> new ReadOnlyObjectWrapper<Double>(((List<Double>) p.getValue()).get(coli)));
+            col.setCellValueFactory(p -> new ReadOnlyObjectWrapper<>((p.getValue()).get(coli)));
 
             if (customCell) {
                 col.setCellFactory(p -> new TableCell<List<Double>,Double>() {
--- a/modules/controls/src/main/java/com/sun/javafx/scene/control/SelectedCellsMap.java	Tue Sep 02 15:32:15 2014 +1200
+++ b/modules/controls/src/main/java/com/sun/javafx/scene/control/SelectedCellsMap.java	Wed Sep 03 12:12:43 2014 +1200
@@ -47,7 +47,7 @@
  * Refer to RT-33442 for more information on this issue.
  */
 // T == TablePosition<S,?>
-public class SelectedCellsMap<T extends TablePositionBase> {
+public abstract class SelectedCellsMap<T extends TablePositionBase> {
     private final ObservableList<T> selectedCells;
     private final ObservableList<T> sortedSelectedCells;
 
@@ -64,6 +64,8 @@
         selectedCellBitSetMap = new TreeMap<>((o1, o2) -> o1.compareTo(o2));
     }
 
+    public abstract boolean isCellSelectionEnabled();
+
     public int size() {
         return selectedCells.size();
     }
@@ -80,25 +82,39 @@
         final int columnIndex = tp.getColumn();
 
         // update the bitset map
+        boolean isNewBitSet = false;
         BitSet bitset;
         if (! selectedCellBitSetMap.containsKey(row)) {
             bitset = new BitSet();
             selectedCellBitSetMap.put(row, bitset);
+            isNewBitSet = true;
         } else {
             bitset = selectedCellBitSetMap.get(row);
         }
 
-        if (columnIndex >= 0) {
-            boolean isAlreadySet = bitset.get(columnIndex);
-            bitset.set(columnIndex);
+        final boolean cellSelectionModeEnabled = isCellSelectionEnabled();
 
-            if (! isAlreadySet) {
-                // add into the list
-                selectedCells.add(tp);
+        if (cellSelectionModeEnabled) {
+            if (columnIndex >= 0) {
+                boolean isAlreadySet = bitset.get(columnIndex);
+
+                if (!isAlreadySet) {
+                    bitset.set(columnIndex);
+
+                    // add into the list
+                    selectedCells.add(tp);
+                }
+            } else {
+                // FIXME slow path (for now)
+                if (!selectedCells.contains(tp)) {
+                    selectedCells.add(tp);
+                }
             }
         } else {
-            // FIXME slow path (for now)
-            if (! selectedCells.contains(tp)) {
+            if (isNewBitSet) {
+                if (columnIndex >= 0) {
+                    bitset.set(columnIndex);
+                }
                 selectedCells.add(tp);
             }
         }
--- a/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/TableCellBehaviorBase.java	Tue Sep 02 15:32:15 2014 +1200
+++ b/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/TableCellBehaviorBase.java	Wed Sep 03 12:12:43 2014 +1200
@@ -163,20 +163,26 @@
 
                     final int anchorRow = anchor.getRow();
 
-                    if (sm.isCellSelectionEnabled()) {
-                        // clear selection, but maintain the anchor
-                        sm.clearSelection();
+                    final boolean asc = anchorRow < row;
 
-                        // and then determine all row and columns which must be selected
-                        int minRow = Math.min(anchor.getRow(), row);
-                        int maxRow = Math.max(anchor.getRow(), row);
-                        TableColumnBase<S,T> minColumn = anchor.getColumn() < column ? anchor.getTableColumn() : tableColumn;
-                        TableColumnBase<S,T> maxColumn = anchor.getColumn() >= column ? anchor.getTableColumn() : tableColumn;
+                    // clear selection, but maintain the anchor
+                    sm.clearSelection();
 
-                        // and then perform the selection
+                    // and then determine all row and columns which must be selected
+                    int minRow = Math.min(anchorRow, row);
+                    int maxRow = Math.max(anchorRow, row);
+                    TableColumnBase<S,T> minColumn = anchor.getColumn() < column ? anchor.getTableColumn() : tableColumn;
+                    TableColumnBase<S,T> maxColumn = anchor.getColumn() >= column ? anchor.getTableColumn() : tableColumn;
+
+                    // and then perform the selection.
+                    // RT-21444: We need to put the range in the correct
+                    // order or else the last selected row will not be the
+                    // last item in the selectedItems list of the selection
+                    // model,
+                    if (asc) {
                         sm.selectRange(minRow, minColumn, maxRow, maxColumn);
                     } else {
-                        selectRows(anchorRow, row);
+                        sm.selectRange(maxRow, minColumn, minRow, maxColumn);
                     }
 
                     // This line of code below was disabled as a fix for RT-30394.
@@ -198,15 +204,15 @@
         final TableSelectionModel<S> sm = getSelectionModel();
         final int row = getControl().getIndex();
         final TableColumnBase<S,T> column = getTableColumn();
-        boolean isAlreadySelected = sm.isSelected(row, sm.isCellSelectionEnabled() ? column : null);
+        boolean isAlreadySelected = sm.isSelected(row, column);
 
         if (isAlreadySelected && shortcutDown) {
             sm.clearSelection(row, column);
-            getFocusModel().focus(row, (TC) (sm.isCellSelectionEnabled() ? column : null));
+            getFocusModel().focus(row, (TC) column);
             isAlreadySelected = false;
         } else {
             // we check if cell selection is enabled to fix RT-33897
-            sm.clearAndSelect(row, sm.isCellSelectionEnabled() ? column : null);
+            sm.clearAndSelect(row, column);
         }
 
         handleClicks(button, clickCount, isAlreadySelected);
--- a/modules/controls/src/main/java/javafx/scene/control/ListCell.java	Tue Sep 02 15:32:15 2014 +1200
+++ b/modules/controls/src/main/java/javafx/scene/control/ListCell.java	Wed Sep 03 12:12:43 2014 +1200
@@ -501,7 +501,10 @@
         if (index == -1 || listView == null) return;
         
         SelectionModel<T> sm = listView.getSelectionModel();
-        if (sm == null) return;
+        if (sm == null) {
+            updateSelected(false);
+            return;
+        }
         
         boolean isSelected = sm.isSelected(index);
         if (isSelected() == isSelected) return;
@@ -515,7 +518,10 @@
         if (index == -1 || listView == null) return;
         
         FocusModel<T> fm = listView.getFocusModel();
-        if (fm == null) return;
+        if (fm == null) {
+            setFocused(false);
+            return;
+        }
         
         setFocused(fm.isFocused(index));
     }
--- a/modules/controls/src/main/java/javafx/scene/control/ListView.java	Tue Sep 02 15:32:15 2014 +1200
+++ b/modules/controls/src/main/java/javafx/scene/control/ListView.java	Wed Sep 03 12:12:43 2014 +1200
@@ -31,6 +31,7 @@
 import java.util.List;
 
 import com.sun.javafx.scene.control.behavior.ListCellBehavior;
+import com.sun.javafx.scene.control.behavior.TableCellBehaviorBase;
 import javafx.beans.InvalidationListener;
 import javafx.beans.property.BooleanProperty;
 import javafx.beans.property.DoubleProperty;
@@ -1229,6 +1230,9 @@
             }
             
             updateItemCount();
+
+            updateDefaultSelection();
+            ListCellBehavior.setAnchor(listView, 0, true);
         }
         
         // watching for changes to the items list content
@@ -1277,36 +1281,6 @@
         private WeakChangeListener<ObservableList<T>> weakItemsObserver = 
                 new WeakChangeListener<ObservableList<T>>(itemsObserver);
         
-        private void updateItemsObserver(ObservableList<T> oldList, ObservableList<T> newList) {
-            // update listeners
-            if (oldList != null) {
-                oldList.removeListener(weakItemsContentObserver);
-            }
-            if (newList != null) {
-                newList.addListener(weakItemsContentObserver);
-            }
-            
-            updateItemCount();
-
-            // when the items list totally changes, we should clear out
-            // the selection and focus
-            int newValueIndex = -1;
-            if (newList != null) {
-                T selectedItem = getSelectedItem();
-                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;
-                }
-            }
-
-            select(newValueIndex);
-        }
-
 
 
         /***********************************************************************
@@ -1466,6 +1440,14 @@
             return items.get(index);
         }
 
+
+
+        /***********************************************************************
+         *                                                                     *
+         * Private implementation                                              *
+         *                                                                     *
+         **********************************************************************/
+
         private void updateItemCount() {
             if (listView == null) {
                 itemCount = -1;
@@ -1473,7 +1455,41 @@
                 List<T> items = listView.getItems();
                 itemCount = items == null ? -1 : items.size();
             }
-        } 
+        }
+
+        private void updateItemsObserver(ObservableList<T> oldList, ObservableList<T> newList) {
+            // update listeners
+            if (oldList != null) {
+                oldList.removeListener(weakItemsContentObserver);
+            }
+            if (newList != null) {
+                newList.addListener(weakItemsContentObserver);
+            }
+
+            updateItemCount();
+            updateDefaultSelection();
+        }
+
+        private void updateDefaultSelection() {
+            // when the items list totally changes, we should clear out
+            // the selection and focus
+            int newValueIndex = -1;
+            if (listView.getItems() != null) {
+                T selectedItem = getSelectedItem();
+                if (selectedItem != null) {
+                    newValueIndex = listView.getItems().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 = listView.getItems().size() > 0 ? 0 : -1;
+                }
+            }
+
+            clearSelection();
+            select(newValueIndex);
+        }
     }
 
 
@@ -1496,6 +1512,10 @@
             }
             
             updateItemCount();
+
+            if (itemCount > 0) {
+                focus(0);
+            }
         }
 
         private ChangeListener<ObservableList<T>> itemsListener = (observable, oldList, newList) -> {
@@ -1503,7 +1523,7 @@
         };
         
         private WeakChangeListener<ObservableList<T>> weakItemsListener = 
-                new WeakChangeListener<ObservableList<T>>(itemsListener);
+                new WeakChangeListener<>(itemsListener);
         
         private void updateItemsObserver(ObservableList<T> oldList, ObservableList<T> newList) {
             // the listview items list has changed, we need to observe
@@ -1516,34 +1536,32 @@
         
         // Listen to changes in the listview items list, such that when it
         // changes we can update the focused index to refer to the new indices.
-        private final ListChangeListener<T> itemsContentListener = new ListChangeListener<T>() {
-            @Override public void onChanged(Change<? extends T> c) {
-                updateItemCount();
-                
+        private final ListChangeListener<T> itemsContentListener = c -> {
+            updateItemCount();
+
+            while (c.next()) {
+                // looking at the first change
+                int from = c.getFrom();
+                if (getFocusedIndex() == -1 || from > getFocusedIndex()) {
+                    return;
+                }
+
+                c.reset();
+                boolean added = false;
+                boolean removed = false;
+                int addedSize = 0;
+                int removedSize = 0;
                 while (c.next()) {
-                    // looking at the first change
-                    int from = c.getFrom();
-                    if (getFocusedIndex() == -1 || from > getFocusedIndex()) {
-                        return;
-                    }
+                    added |= c.wasAdded();
+                    removed |= c.wasRemoved();
+                    addedSize += c.getAddedSize();
+                    removedSize += c.getRemovedSize();
+                }
 
-                    c.reset();
-                    boolean added = false;
-                    boolean removed = false;
-                    int addedSize = 0;
-                    int removedSize = 0;
-                    while (c.next()) {
-                        added |= c.wasAdded();
-                        removed |= c.wasRemoved();
-                        addedSize += c.getAddedSize();
-                        removedSize += c.getRemovedSize();
-                    }
-
-                    if (added && !removed) {
-                        focus(getFocusedIndex() + addedSize);
-                    } else if (!added && removed) {
-                        focus(getFocusedIndex() - removedSize);
-                    }
+                if (added && !removed) {
+                    focus(getFocusedIndex() + addedSize);
+                } else if (!added && removed) {
+                    focus(getFocusedIndex() - removedSize);
                 }
             }
         };
--- a/modules/controls/src/main/java/javafx/scene/control/MultipleSelectionModelBase.java	Tue Sep 02 15:32:15 2014 +1200
+++ b/modules/controls/src/main/java/javafx/scene/control/MultipleSelectionModelBase.java	Wed Sep 03 12:12:43 2014 +1200
@@ -402,6 +402,7 @@
         // We expect that in concrete subclasses of this class we observe the
         // data model such that we check to see if the given item exists in it,
         // whilst SelectedIndex == -1 && SelectedItem != null.
+        setSelectedIndex(-1);
         setSelectedItem(obj);
     }
 
--- a/modules/controls/src/main/java/javafx/scene/control/TableCell.java	Tue Sep 02 15:32:15 2014 +1200
+++ b/modules/controls/src/main/java/javafx/scene/control/TableCell.java	Wed Sep 03 12:12:43 2014 +1200
@@ -510,7 +510,10 @@
         if (getIndex() == -1 || tableView == null) return;
 
         TableSelectionModel<S> sm = tableView.getSelectionModel();
-        if (sm == null) return;
+        if (sm == null) {
+            updateSelected(false);
+            return;
+        }
 
         boolean isSelectedNow = sm.isSelected(getIndex(), getTableColumn());
         if (isSelected == isSelectedNow) return;
@@ -533,7 +536,10 @@
         if (index == -1 || tableView == null || tableRow == null) return;
 
         final TableViewFocusModel<S> fm = tableView.getFocusModel();
-        if (fm == null) return;
+        if (fm == null) {
+            setFocused(false);
+            return;
+        }
 
         boolean isFocusedNow = fm != null && fm.isFocused(index, getTableColumn());
 
--- a/modules/controls/src/main/java/javafx/scene/control/TableView.java	Tue Sep 02 15:32:15 2014 +1200
+++ b/modules/controls/src/main/java/javafx/scene/control/TableView.java	Wed Sep 03 12:12:43 2014 +1200
@@ -31,6 +31,7 @@
 import com.sun.javafx.scene.control.Logging;
 import com.sun.javafx.scene.control.SelectedCellsMap;
 import com.sun.javafx.scene.control.behavior.TableCellBehavior;
+import com.sun.javafx.scene.control.behavior.TableCellBehaviorBase;
 import javafx.beans.DefaultProperty;
 import javafx.beans.InvalidationListener;
 import javafx.beans.WeakInvalidationListener;
@@ -1960,14 +1961,11 @@
             super(tableView);
             this.tableView = tableView;
 
-            updateItemCount();
-            
-            cellSelectionEnabledProperty().addListener(o -> {
-                isCellSelectionEnabled();
-                clearSelection();
-            });
-
-            selectedCellsMap = new SelectedCellsMap<>(c -> handleSelectedCellsListChangeEvent(c));
+            selectedCellsMap = new SelectedCellsMap<TablePosition<S,?>>(c -> handleSelectedCellsListChangeEvent(c)) {
+                @Override public boolean isCellSelectionEnabled() {
+                    return TableViewArrayListSelectionModel.this.isCellSelectionEnabled();
+                }
+            };
 
             selectedItems = new ReadOnlyUnbackedObservableList<S>() {
                 @Override public S get(int i) {
@@ -2004,81 +2002,64 @@
             if (items != null) {
                 items.addListener(weakItemsContentListener);
             }
+
+
+            updateItemCount();
+
+            updateDefaultSelection();
+            TableCellBehaviorBase.setAnchor(tableView, getFocusedCell(), true);
+
+            cellSelectionEnabledProperty().addListener(o -> {
+                updateDefaultSelection();
+                TableCellBehaviorBase.setAnchor(tableView, getFocusedCell(), true);
+            });
         }
         
         private final TableView<S> tableView;
         
-        final ListChangeListener<S> itemsContentListener = new ListChangeListener<S>() {
-            @Override public void onChanged(Change<? extends S> c) {
-                updateItemCount();
-
-                List<S> items = getTableModel();
-
-                while (c.next()) {
-                    final S selectedItem = getSelectedItem();
-                    final int selectedIndex = getSelectedIndex();
-                    
-                    if (items == null || items.isEmpty()) {
-                        clearSelection();
-                    } else if (getSelectedIndex() == -1 && getSelectedItem() != null) {
-                        int newIndex = items.indexOf(getSelectedItem());
-                        if (newIndex != -1) {
-                            setSelectedIndex(newIndex);
-                        }
-                    } else if (c.wasRemoved() && 
-                            c.getRemovedSize() == 1 && 
-                            ! c.wasAdded() && 
-                            selectedItem != null && 
-                            selectedItem.equals(c.getRemoved().get(0))) {
-                        // Bug fix for RT-28637
-                        if (getSelectedIndex() < getItemCount()) {
-                            S newSelectedItem = getModelItem(selectedIndex);
-                            if (! selectedItem.equals(newSelectedItem)) {
-                                setSelectedItem(newSelectedItem);
-                            }
+        final ListChangeListener<S> itemsContentListener = c -> {
+            updateItemCount();
+
+            List<S> items1 = getTableModel();
+
+            while (c.next()) {
+                if (c.wasReplaced() || c.getAddedSize() == getItemCount()) {
+                    updateDefaultSelection();
+                    return;
+                }
+
+                final S selectedItem = getSelectedItem();
+                final int selectedIndex = getSelectedIndex();
+
+                if (items1 == null || items1.isEmpty()) {
+                    clearSelection();
+                } else if (getSelectedIndex() == -1 && getSelectedItem() != null) {
+                    int newIndex = items1.indexOf(getSelectedItem());
+                    if (newIndex != -1) {
+                        setSelectedIndex(newIndex);
+                    }
+                } else if (c.wasRemoved() &&
+                        c.getRemovedSize() == 1 &&
+                        ! c.wasAdded() &&
+                        selectedItem != null &&
+                        selectedItem.equals(c.getRemoved().get(0))) {
+                    // Bug fix for RT-28637
+                    if (getSelectedIndex() < getItemCount()) {
+                        S newSelectedItem = getModelItem(selectedIndex);
+                        if (! selectedItem.equals(newSelectedItem)) {
+                            setSelectedItem(newSelectedItem);
                         }
                     }
                 }
-
-                updateSelection(c);
             }
+
+            updateSelection(c);
         };
         
         final WeakListChangeListener<S> weakItemsContentListener 
-                = new WeakListChangeListener<S>(itemsContentListener);
+                = new WeakListChangeListener<>(itemsContentListener);
         
-        private void updateItemsObserver(ObservableList<S> oldList, ObservableList<S> newList) {
-            // the items list has changed, we need to observe
-            // the new list, and remove any observer we had from the old list
-            if (oldList != null) {
-                oldList.removeListener(weakItemsContentListener);
-            }
-            if (newList != null) {
-                newList.addListener(weakItemsContentListener);
-            }
-            
-            updateItemCount();
-
-            // when the items list totally changes, we should clear out
-            // the selection
-            int newValueIndex = -1;
-            if (newList != null) {
-                S selectedItem = getSelectedItem();
-                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;
-                }
-            }
-
-            TableColumn<S,?> firstColumn = getTableColumn(0);
-            select(newValueIndex, isCellSelectionEnabled() ? firstColumn : null);
-        }
-        
+
 
         /***********************************************************************
          *                                                                     *
@@ -2264,13 +2245,6 @@
             // 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.
-            if (getSelectedCells().size() == 1 && isSelected(row, column)) {
-                return;
-            }
-
             // if I'm in cell selection mode but the column is null, I don't want
             // to select the whole row instead...
             if (isCellSelectionEnabled() && column == null) {
@@ -2311,9 +2285,15 @@
         public void select(int row, TableColumn<S,?> column) {
             if (row < 0 || row >= getItemCount()) return;
 
-            // if I'm in cell selection mode but the column is null, I don't want
-            // to select the whole row instead...
-            if (isCellSelectionEnabled() && column == null) return;
+            // if I'm in cell selection mode but the column is null, select each
+            // of the contained cells individually
+            if (isCellSelectionEnabled() && column == null) {
+                List<TableColumn<S,?>> columns = getTableView().getVisibleLeafColumns();
+                for (int i = 0; i < columns.size(); i++) {
+                    select(row, columns.get(i));
+                }
+                return;
+            }
 
             TablePosition<S,?> pos = new TablePosition<>(getTableView(), row, column);
             
@@ -2366,6 +2346,7 @@
             // We expect that in concrete subclasses of this class we observe the
             // data model such that we check to see if the given item exists in it,
             // whilst SelectedIndex == -1 && SelectedItem != null.
+            setSelectedIndex(-1);
             setSelectedItem(obj);
         }
 
@@ -2399,28 +2380,49 @@
                 }
             } else {
                 int lastIndex = -1;
-                Set<TablePosition<S,?>> positions = new LinkedHashSet<TablePosition<S,?>>();
-
+                Set<TablePosition<S,?>> positions = new LinkedHashSet<>();
+
+                // --- firstly, we special-case the non-varargs 'row' argument
                 if (row >= 0 && row < rowCount) {
-                    TablePosition<S,Object> tp = new TablePosition<S,Object>(getTableView(), row, null);
-                    
-                    boolean match = selectedCellsMap.isSelected(row, -1);
-                    if (! match) {
-                        positions.add(tp);
-                        lastIndex = row;
+                    // if I'm in cell selection mode, we want to select each
+                    // of the contained cells individually
+                    if (isCellSelectionEnabled()) {
+                        List<TableColumn<S,?>> columns = getTableView().getVisibleLeafColumns();
+                        for (int column = 0; column < columns.size(); column++) {
+                            if (! selectedCellsMap.isSelected(row, column)) {
+                                positions.add(new TablePosition<>(getTableView(), row, columns.get(column)));
+                                lastIndex = row;
+                            }
+                        }
+                    } else {
+                        boolean match = selectedCellsMap.isSelected(row, -1);
+                        if (!match) {
+                            positions.add(new TablePosition<>(getTableView(), row, null));
+                            lastIndex = row;
+                        }
                     }
                 }
 
-                outer: for (int i = 0; i < rows.length; i++) {
+                // --- now we iterate through all varargs values
+                for (int i = 0; i < rows.length; i++) {
                     int index = rows[i];
                     if (index < 0 || index >= rowCount) continue;
                     lastIndex = index;
-                    
-                    if (selectedCellsMap.isSelected(index, -1)) continue outer;
-                    
-                    // if we are here then we have successfully gotten through the for-loop above
-                    TablePosition<S,Object> pos = new TablePosition<S,Object>(getTableView(), index, null);
-                    positions.add(pos);
+
+                    if (isCellSelectionEnabled()) {
+                        List<TableColumn<S,?>> columns = getTableView().getVisibleLeafColumns();
+                        for (int column = 0; column < columns.size(); column++) {
+                            if (! selectedCellsMap.isSelected(index, column)) {
+                                positions.add(new TablePosition<>(getTableView(), index, columns.get(column)));
+                                lastIndex = index;
+                            }
+                        }
+                    } else {
+                        if (! selectedCellsMap.isSelected(index, -1)) {
+                            // if we are here then we have successfully gotten through the for-loop above
+                            positions.add(new TablePosition<>(getTableView(), index, null));
+                        }
+                    }
                 }
 
                 selectedCellsMap.addAll(positions);
@@ -2437,7 +2439,7 @@
             quietClearSelection();
 
             if (isCellSelectionEnabled()) {
-                List<TablePosition<S,?>> indices = new ArrayList<TablePosition<S,?>>();
+                List<TablePosition<S,?>> indices = new ArrayList<>();
                 TableColumn<S,?> column;
                 TablePosition<S,?> tp = null;
                 for (int col = 0; col < getTableView().getVisibleLeafColumns().size(); col++) {
@@ -2454,7 +2456,7 @@
                     focus(tp.getRow(), tp.getTableColumn());
                 }
             } else {
-                List<TablePosition<S,?>> indices = new ArrayList<TablePosition<S,?>>();
+                List<TablePosition<S,?>> indices = new ArrayList<>();
                 for (int i = 0; i < getItemCount(); i++) {
                     indices.add(new TablePosition<>(getTableView(), i, null));
                 }
@@ -2496,21 +2498,26 @@
             final int _maxRow = Math.max(minRow, maxRow);
 
             for (int _row = _minRow; _row <= _maxRow; _row++) {
-                for (int _col = _minColumnIndex; _col <= _maxColumnIndex; _col++) {
-                    // begin copy/paste of select(int, column) method (with some
-                    // slight modifications)
-                    if (_row < 0 || _row >= itemCount) continue;
-
-                    final TableColumn<S,?> column = tableView.getVisibleLeafColumn(_col);
-
-                    // if I'm in cell selection mode but the column is null, I don't want
-                    // to select the whole row instead...
-                    if (column == null && isCellSelectionEnabled) continue;
-
-                    TablePosition<S,?> pos = new TablePosition<>(tableView, _row, column);
-
+                // begin copy/paste of select(int, column) method (with some
+                // slight modifications)
+                if (_row < 0 || _row >= itemCount) continue;
+
+                if (! isCellSelectionEnabled) {
+                    TablePosition<S, ?> pos = new TablePosition<>(tableView, _row, (TableColumn<S,?>)minColumn);
                     selectedCellsMap.add(pos);
-                    // end copy/paste
+                } else {
+                    for (int _col = _minColumnIndex; _col <= _maxColumnIndex; _col++) {
+                        final TableColumn<S, ?> column = tableView.getVisibleLeafColumn(_col);
+
+                        // if I'm in cell selection mode but the column is null, I don't want
+                        // to select the whole row instead...
+                        if (column == null && isCellSelectionEnabled) continue;
+
+                        TablePosition<S, ?> pos = new TablePosition<>(tableView, _row, column);
+
+                        selectedCellsMap.add(pos);
+                        // end copy/paste
+                    }
                 }
             }
             stopAtomic();
@@ -2542,10 +2549,6 @@
             for (TablePosition pos : getSelectedCells()) {
                 if ((! csMode && pos.getRow() == row) || (csMode && pos.equals(tp))) {
                     selectedCellsMap.remove(pos);
-
-//                    // give focus to this cell index
-//                    focus(row);
-
                     return;
                 }
             }
@@ -2571,12 +2574,11 @@
         @Override
         public boolean isSelected(int row, TableColumn<S,?> column) {
             // When in cell selection mode, we currently do NOT support selecting
-            // entire rows, so a isSelected(row, null) 
-            // should always return false.
+            // entire rows, so a isSelected(row, null) should always return false.
             final boolean isCellSelectionEnabled = isCellSelectionEnabled();
             if (isCellSelectionEnabled && column == null) return false;
 
-            int columnIndex = tableView.getVisibleLeafIndex(column);
+            int columnIndex = ! isCellSelectionEnabled || column == null ? -1 : tableView.getVisibleLeafIndex(column);
             return selectedCellsMap.isSelected(row, columnIndex);
         }
 
@@ -2707,15 +2709,46 @@
          * Support code                                                        *
          *                                                                     *
          **********************************************************************/
+
+        private void updateItemsObserver(ObservableList<S> oldList, ObservableList<S> newList) {
+            // the items list has changed, we need to observe
+            // the new list, and remove any observer we had from the old list
+            if (oldList != null) {
+                oldList.removeListener(weakItemsContentListener);
+            }
+            if (newList != null) {
+                newList.addListener(weakItemsContentListener);
+            }
+
+            updateItemCount();
+            updateDefaultSelection();
+        }
+
+        private void updateDefaultSelection() {
+            // when the items list totally changes, we should clear out
+            // the selection
+            int newValueIndex = -1;
+            if (tableView.getItems() != null) {
+                S selectedItem = getSelectedItem();
+                if (selectedItem != null) {
+                    newValueIndex = tableView.getItems().indexOf(selectedItem);
+                }
+
+                // we put selection onto the first item, if there is at least
+                // one item in the list
+                if (newValueIndex == -1) {
+                    newValueIndex = tableView.getItems().size() > 0 ? 0 : -1;
+                }
+            }
+
+            clearSelection();
+            select(newValueIndex, isCellSelectionEnabled() ? getTableColumn(0) : null);
+        }
         
         private TableColumn<S,?> getTableColumn(int pos) {
             return getTableView().getVisibleLeafColumn(pos);
         }
         
-//        private TableColumn<S,?> getTableColumn(TableColumn<S,?> column) {
-//            return getTableColumn(column, 0);
-//        }
-
         // Gets a table column to the left or right of the current one, given an offset
         private TableColumn<S,?> getTableColumn(TableColumn<S,?> column, int offset) {
             int columnIndex = getTableView().getVisibleLeafIndex(column);
@@ -2897,6 +2930,7 @@
         private final TableView<S> tableView;
 
         private final TablePosition<S,?> EMPTY_CELL;
+        private boolean isDefaultFocus = false;
 
         /**
          * Creates a default TableViewFocusModel instance that will be used to
@@ -2916,44 +2950,60 @@
                 this.tableView.getItems().addListener(weakItemsContentListener);
             }
 
-            TablePosition<S,?> pos = new TablePosition<>(tableView, -1, null);
-            setFocusedCell(pos);
-            EMPTY_CELL = pos;
+            updateDefaultFocus();
+
+            EMPTY_CELL = new TablePosition<>(tableView, -1, null);
         }
         
         // Listen to changes in the tableview items list, such that when it
         // changes we can update the focused index to refer to the new indices.
-        private final ListChangeListener<S> itemsContentListener = new ListChangeListener<S>() {
-            @Override public void onChanged(Change<? extends S> c) {
-                c.next();
-                if (c.getFrom() > getFocusedIndex()) return;
-                c.reset();
-                boolean added = false;
-                boolean removed = false;
-                int addedSize = 0;
-                int removedSize = 0;
-                while (c.next()) {
-                    added |= c.wasAdded();
-                    removed |= c.wasRemoved();
-                    addedSize += c.getAddedSize();
-                    removedSize += c.getRemovedSize();
+        private final ListChangeListener<S> itemsContentListener = c -> {
+            c.next();
+            TablePosition<S,?> focusedCell = getFocusedCell();
+            final int focusedIndex = focusedCell.getRow();
+            if (focusedIndex == -1 || c.getFrom() > focusedIndex) {
+                return;
+            }
+            c.reset();
+            boolean added = false;
+            boolean removed = false;
+            int addedSize = 0;
+            int removedSize = 0;
+            while (c.next()) {
+                added |= c.wasAdded();
+                removed |= c.wasRemoved();
+                addedSize += c.getAddedSize();
+                removedSize += c.getRemovedSize();
+            }
+
+            if (added && ! removed) {
+                if (isDefaultFocus) {
+                    focus(0, focusedCell.getTableColumn());
+                    isDefaultFocus = false;
+                } else {
+                    final int newFocusIndex = getFocusedIndex() + addedSize;
+                    focus(newFocusIndex, focusedCell.getTableColumn());
                 }
-                if (added && ! removed) {
-                    focus(getFocusedIndex() + addedSize);
-                } else if (!added && removed) {
-                    focus(getFocusedIndex() - removedSize);
+            } else if (!added && removed) {
+                final int newFocusIndex = getFocusedIndex() - removedSize;
+                if (newFocusIndex < 0) {
+                    focus(0, focusedCell.getTableColumn());
+                } else {
+                    focus(newFocusIndex, focusedCell.getTableColumn());
                 }
             }
         };
         
         private WeakListChangeListener<S> weakItemsContentListener 
-                = new WeakListChangeListener<S>(itemsContentListener);
+                = new WeakListChangeListener<>(itemsContentListener);
         
         private void updateItemsObserver(ObservableList<S> oldList, ObservableList<S> newList) {
             // the tableview items list has changed, we need to observe
             // the new list, and remove any observer we had from the old list
             if (oldList != null) oldList.removeListener(weakItemsContentListener);
             if (newList != null) newList.addListener(weakItemsContentListener);
+
+            updateDefaultFocus();
         }
 
         /** {@inheritDoc} */
@@ -3115,14 +3165,55 @@
             focus(cell.getRow(), getTableColumn(cell.getTableColumn(), 1));
         }
 
-
-
-         /***********************************************************************
+        /** {@inheritDoc} */
+        @Override public void focusPrevious() {
+            if (getFocusedIndex() == -1) {
+                focus(0);
+            } else if (getFocusedIndex() > 0) {
+                focusAboveCell();
+            }
+        }
+
+        /** {@inheritDoc} */
+        @Override public void focusNext() {
+            if (getFocusedIndex() == -1) {
+                focus(0);
+            } else if (getFocusedIndex() != getItemCount() -1) {
+                focusBelowCell();
+            }
+        }
+
+        /***********************************************************************
          *                                                                     *
          * Private Implementation                                              *
          *                                                                     *
          **********************************************************************/
 
+        private void updateDefaultFocus() {
+            // when the items list totally changes, we should clear out
+            // the focus
+            int newValueIndex = -1;
+            if (tableView.getItems() != null) {
+                S focusedItem = getFocusedItem();
+                if (focusedItem != null) {
+                    newValueIndex = tableView.getItems().indexOf(focusedItem);
+                }
+
+                // we put focus onto the first item, if there is at least
+                // one item in the list
+                if (newValueIndex == -1) {
+                    newValueIndex = tableView.getItems().size() > 0 ? 0 : -1;
+                }
+            }
+
+            TablePosition<S,?> focusedCell = getFocusedCell();
+            TableColumn<S,?> focusColumn = focusedCell != null ?
+               focusedCell.getTableColumn() : tableView.getVisibleLeafColumn(0);
+
+            focus(newValueIndex, focusColumn);
+            isDefaultFocus = true;
+        }
+
         private int getColumnCount() {
             return tableView.getVisibleLeafColumns().size();
         }
--- a/modules/controls/src/main/java/javafx/scene/control/TreeCell.java	Tue Sep 02 15:32:15 2014 +1200
+++ b/modules/controls/src/main/java/javafx/scene/control/TreeCell.java	Wed Sep 03 12:12:43 2014 +1200
@@ -532,9 +532,14 @@
     private void updateSelection() {
         if (isEmpty()) return;
         if (getIndex() == -1 || getTreeView() == null) return;
-        if (getTreeView().getSelectionModel() == null) return;
+
+        SelectionModel<TreeItem<T>> sm = getTreeView().getSelectionModel();
+        if (sm == null) {
+            updateSelected(false);
+            return;
+        }
         
-        boolean isSelected = getTreeView().getSelectionModel().isSelected(getIndex());
+        boolean isSelected = sm.isSelected(getIndex());
         if (isSelected() == isSelected) return;
         
         updateSelected(isSelected);
@@ -542,9 +547,14 @@
 
     private void updateFocus() {
         if (getIndex() == -1 || getTreeView() == null) return;
-        if (getTreeView().getFocusModel() == null) return;
+
+        FocusModel<TreeItem<T>> fm = getTreeView().getFocusModel();
+        if (fm == null) {
+            setFocused(false);
+            return;
+        }
         
-        setFocused(getTreeView().getFocusModel().isFocused(getIndex()));
+        setFocused(fm.isFocused(getIndex()));
     }
 
     private boolean updateEditingIndex = true;
--- a/modules/controls/src/main/java/javafx/scene/control/TreeTableCell.java	Tue Sep 02 15:32:15 2014 +1200
+++ b/modules/controls/src/main/java/javafx/scene/control/TreeTableCell.java	Wed Sep 03 12:12:43 2014 +1200
@@ -500,7 +500,10 @@
         if (getIndex() == -1 || tv == null) return;
 
         TreeTableView.TreeTableViewSelectionModel<S> sm = tv.getSelectionModel();
-        if (sm == null) return;
+        if (sm == null) {
+            updateSelected(false);
+            return;
+        }
 
         boolean isSelectedNow = sm.isSelected(getIndex(), getTableColumn());
         if (isSelected == isSelectedNow) return;
@@ -521,7 +524,10 @@
         if (getIndex() == -1 || tv == null) return;
 
         TreeTableView.TreeTableViewFocusModel<S> fm = tv.getFocusModel();
-        if (fm == null) return;
+        if (fm == null) {
+            setFocused(false);
+            return;
+        }
 
         boolean isFocusedNow = fm != null &&
                             fm.isFocused(getIndex(), getTableColumn());
--- a/modules/controls/src/main/java/javafx/scene/control/TreeTableView.java	Tue Sep 02 15:32:15 2014 +1200
+++ b/modules/controls/src/main/java/javafx/scene/control/TreeTableView.java	Wed Sep 03 12:12:43 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.TableCellBehaviorBase;
 import com.sun.javafx.scene.control.behavior.TreeTableCellBehavior;
 import javafx.beans.property.DoubleProperty;
 import javafx.css.CssMetaData;
@@ -2096,11 +2097,6 @@
             }
 
             this.treeTableView = treeTableView;
-            
-            cellSelectionEnabledProperty().addListener(o -> {
-                isCellSelectionEnabled();
-                clearSelection();
-            });
         }
 
 
@@ -2219,7 +2215,11 @@
             this.treeTableView.rootProperty().addListener(weakRootPropertyListener);
             updateTreeEventListener(null, treeTableView.getRoot());
 
-            selectedCellsMap = new SelectedCellsMap<>(c -> handleSelectedCellsListChangeEvent(c));
+            selectedCellsMap = new SelectedCellsMap<TreeTablePosition<S,?>>(c -> handleSelectedCellsListChangeEvent(c)) {
+                @Override public boolean isCellSelectionEnabled() {
+                    return TreeTableViewArrayListSelectionModel.this.isCellSelectionEnabled();
+                }
+            };
 
             selectedItems = new ReadOnlyUnbackedObservableList<TreeItem<S>>() {
                 @Override public TreeItem<S> get(int i) {
@@ -2240,6 +2240,15 @@
                     return selectedCellsMap.size();
                 }
             };
+
+
+            updateDefaultSelection();
+            TableCellBehaviorBase.setAnchor(treeTableView, getFocusedCell(), true);
+
+            cellSelectionEnabledProperty().addListener(o -> {
+                updateDefaultSelection();
+                TableCellBehaviorBase.setAnchor(treeTableView, getFocusedCell(), true);
+            });
         }
         
         private void updateTreeEventListener(TreeItem<S> oldRoot, TreeItem<S> newRoot) {
@@ -2254,15 +2263,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);
+            updateDefaultSelection();
 
             updateTreeEventListener(oldValue, newValue);
         };
-        
+
         private EventHandler<TreeItem.TreeModificationEvent<S>> treeItemListener = new EventHandler<TreeItem.TreeModificationEvent<S>>() {
             @Override public void handle(TreeItem.TreeModificationEvent<S> e) {
                 
@@ -2477,13 +2482,6 @@
             // 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.
-            if (getSelectedCells().size() == 1 && isSelected(row, column)) {
-                return;
-            }
-
             // if I'm in cell selection mode but the column is null, I don't want
             // to select the whole row instead...
             if (isCellSelectionEnabled() && column == null) {
@@ -2524,9 +2522,15 @@
             // TODO we need to bring in the TreeView selection stuff here...
             if (row < 0 || row >= getRowCount()) return;
 
-            // if I'm in cell selection mode but the column is null, I don't want
-            // to select the whole row instead...
-            if (isCellSelectionEnabled() && column == null) return;
+            // if I'm in cell selection mode but the column is null, select each
+            // of the contained cells individually
+            if (isCellSelectionEnabled() && column == null) {
+                List<TreeTableColumn<S,?>> columns = getTreeTableView().getVisibleLeafColumns();
+                for (int i = 0; i < columns.size(); i++) {
+                    select(row, columns.get(i));
+                }
+                return;
+            }
 
             TreeTablePosition<S,?> pos = new TreeTablePosition<>(getTreeTableView(), row, (TreeTableColumn<S,?>)column);
             
@@ -2579,6 +2583,7 @@
             // We expect that in concrete subclasses of this class we observe the
             // data model such that we check to see if the given item exists in it,
             // whilst SelectedIndex == -1 && SelectedItem != null.
+            setSelectedIndex(-1);
             setSelectedItem(obj);
         }
 
@@ -2612,28 +2617,49 @@
                 }
             } else {
                 int lastIndex = -1;
-                Set<TreeTablePosition<S,?>> positions = new LinkedHashSet<TreeTablePosition<S,?>>();
-
+                Set<TreeTablePosition<S,?>> positions = new LinkedHashSet<>();
+
+                // --- firstly, we special-case the non-varargs 'row' argument
                 if (row >= 0 && row < rowCount) {
-                    TreeTablePosition<S,Object> pos = new TreeTablePosition<S,Object>(getTreeTableView(), row, null);
-                    
-                    boolean match = selectedCellsMap.isSelected(row, -1);
-                    if (! match) {
-                        positions.add(pos);
-                        lastIndex = row;
+                    // if I'm in cell selection mode, we want to select each
+                    // of the contained cells individually
+                    if (isCellSelectionEnabled()) {
+                        List<TreeTableColumn<S,?>> columns = getTreeTableView().getVisibleLeafColumns();
+                        for (int column = 0; column < columns.size(); column++) {
+                            if (! selectedCellsMap.isSelected(row, column)) {
+                                positions.add(new TreeTablePosition<>(getTreeTableView(), row, columns.get(column)));
+                                lastIndex = row;
+                            }
+                        }
+                    } else {
+                        boolean match = selectedCellsMap.isSelected(row, -1);
+                        if (!match) {
+                            positions.add(new TreeTablePosition<>(getTreeTableView(), row, null));
+                            lastIndex = row;
+                        }
                     }
                 }
 
-                outer: for (int i = 0; i < rows.length; i++) {
+                // --- now we iterate through all varargs values
+                for (int i = 0; i < rows.length; i++) {
                     int index = rows[i];
                     if (index < 0 || index >= rowCount) continue;
                     lastIndex = index;
-                    
-                    if (selectedCellsMap.isSelected(index, -1)) continue outer;
-                    
-                    // if we are here then we have successfully gotten through the for-loop above
-                    TreeTablePosition<S,Object> pos = new TreeTablePosition<S,Object>(getTreeTableView(), index, null);
-                    positions.add(pos);
+
+                    if (isCellSelectionEnabled()) {
+                        List<TreeTableColumn<S,?>> columns = getTreeTableView().getVisibleLeafColumns();
+                        for (int column = 0; column < columns.size(); column++) {
+                            if (! selectedCellsMap.isSelected(index, column)) {
+                                positions.add(new TreeTablePosition<>(getTreeTableView(), index, columns.get(column)));
+                                lastIndex = index;
+                            }
+                        }
+                    } else {
+                        if (! selectedCellsMap.isSelected(index, -1)) {
+                            // if we are here then we have successfully gotten through the for-loop above
+                            positions.add(new TreeTablePosition<>(getTreeTableView(), index, null));
+                        }
+                    }
                 }
 
                 selectedCellsMap.addAll(positions);
@@ -2651,7 +2677,7 @@
 //            if (getTableModel() == null) return;
 
             if (isCellSelectionEnabled()) {
-                List<TreeTablePosition<S,?>> indices = new ArrayList<TreeTablePosition<S,?>>();
+                List<TreeTablePosition<S,?>> indices = new ArrayList<>();
                 TreeTableColumn<S,?> column;
                 TreeTablePosition<S,?> tp = null;
                 for (int col = 0; col < getTreeTableView().getVisibleLeafColumns().size(); col++) {
@@ -2668,7 +2694,7 @@
                     focus(tp.getRow(), tp.getTableColumn());
                 }
             } else {
-                List<TreeTablePosition<S,?>> indices = new ArrayList<TreeTablePosition<S,?>>();
+                List<TreeTablePosition<S,?>> indices = new ArrayList<>();
                 for (int i = 0; i < getRowCount(); i++) {
                     indices.add(new TreeTablePosition<>(getTreeTableView(), i, null));
                 }
@@ -2710,21 +2736,26 @@
             final int _maxRow = Math.max(minRow, maxRow);
 
             for (int _row = _minRow; _row <= _maxRow; _row++) {
-                for (int _col = _minColumnIndex; _col <= _maxColumnIndex; _col++) {
-                    // begin copy/paste of select(int, column) method (with some
-                    // slight modifications)
-                    if (_row < 0 || _row >= itemCount) continue;
-
-                    final TreeTableColumn<S,?> column = treeTableView.getVisibleLeafColumn(_col);
-
-                    // if I'm in cell selection mode but the column is null, I don't want
-                    // to select the whole row instead...
-                    if (column == null && isCellSelectionEnabled) continue;
-
-                    TreeTablePosition<S,?> pos = new TreeTablePosition<>(treeTableView, _row, column);
-
+                // begin copy/paste of select(int, column) method (with some
+                // slight modifications)
+                if (_row < 0 || _row >= itemCount) continue;
+
+                if (! isCellSelectionEnabled) {
+                    TreeTablePosition<S, ?> pos = new TreeTablePosition<>(treeTableView, _row, (TreeTableColumn<S,?>)minColumn);
                     selectedCellsMap.add(pos);
-                    // end copy/paste
+                } else {
+                    for (int _col = _minColumnIndex; _col <= _maxColumnIndex; _col++) {
+                        final TreeTableColumn<S, ?> column = treeTableView.getVisibleLeafColumn(_col);
+
+                        // if I'm in cell selection mode but the column is null, I don't want
+                        // to select the whole row instead...
+                        if (column == null && isCellSelectionEnabled) continue;
+
+                        TreeTablePosition<S, ?> pos = new TreeTablePosition<>(treeTableView, _row, column);
+
+                        selectedCellsMap.add(pos);
+                        // end copy/paste
+                    }
                 }
             }
             stopAtomic();
@@ -2754,10 +2785,6 @@
             for (TreeTablePosition<S,?> pos : getSelectedCells()) {
                 if ((! csMode && pos.getRow() == row) || (csMode && pos.equals(tp))) {
                     selectedCellsMap.remove(pos);
-
-                    // give focus to this cell index
-//                    focus(row);
-
                     return;
                 }
             }
@@ -2786,7 +2813,7 @@
             final boolean isCellSelectionEnabled = isCellSelectionEnabled();
             if (isCellSelectionEnabled && column == null) return false;
 
-            int columnIndex = treeTableView.getVisibleLeafIndex((TreeTableColumn<S,?>) column);
+            int columnIndex = ! isCellSelectionEnabled || column == null ? -1 : treeTableView.getVisibleLeafIndex((TreeTableColumn<S,?>) column);
             return selectedCellsMap.isSelected(row, columnIndex);
         }
 
@@ -2915,6 +2942,13 @@
          * Support code                                                        *
          *                                                                     *
          **********************************************************************/
+
+        private void updateDefaultSelection() {
+            // if we can, we put selection onto the first row
+            int newValueIndex = getItemCount() > 0 ? 0 : -1;
+            clearSelection();
+            select(newValueIndex, isCellSelectionEnabled() ? getTableColumn(0) : null);
+        }
         
         private TreeTableColumn<S,?> getTableColumn(int pos) {
             return getTreeTableView().getVisibleLeafColumn(pos);
@@ -3135,9 +3169,11 @@
             this.treeTableView.rootProperty().addListener(weakRootPropertyListener);
             updateTreeEventListener(null, treeTableView.getRoot());
 
-            TreeTablePosition<S,?> pos = new TreeTablePosition<>(treeTableView, -1, null);
+            int focusRow = getItemCount() > 0 ? 0 : -1;
+            TreeTablePosition<S,?> pos = new TreeTablePosition<>(treeTableView, focusRow, null);
             setFocusedCell(pos);
-            EMPTY_CELL = pos;
+
+            EMPTY_CELL = new TreeTablePosition<>(treeTableView, -1, null);
         }
         
         private final ChangeListener<TreeItem<S>> rootPropertyListener = (observable, oldValue, newValue) -> {
@@ -3381,6 +3417,24 @@
             focus(cell.getRow(), getTableColumn(cell.getTableColumn(), 1));
         }
 
+        /** {@inheritDoc} */
+        @Override public void focusPrevious() {
+            if (getFocusedIndex() == -1) {
+                focus(0);
+            } else if (getFocusedIndex() > 0) {
+                focusAboveCell();
+            }
+        }
+
+        /** {@inheritDoc} */
+        @Override public void focusNext() {
+            if (getFocusedIndex() == -1) {
+                focus(0);
+            } else if (getFocusedIndex() != getItemCount() -1) {
+                focusBelowCell();
+            }
+        }
+
 
 
          /***********************************************************************
--- a/modules/controls/src/main/java/javafx/scene/control/TreeView.java	Tue Sep 02 15:32:15 2014 +1200
+++ b/modules/controls/src/main/java/javafx/scene/control/TreeView.java	Wed Sep 03 12:12:43 2014 +1200
@@ -1243,6 +1243,7 @@
                     
             updateTreeEventListener(null, treeView.getRoot());
 
+            updateDefaultSelection();
             TreeCellBehavior.setAnchor(treeView, 0, true);
         }
         
@@ -1258,114 +1259,106 @@
         }
         
         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);
-
+            updateDefaultSelection();
             updateTreeEventListener(oldValue, newValue);
         };
-        
-        private EventHandler<TreeModificationEvent<T>> treeItemListener = new EventHandler<TreeModificationEvent<T>>() {
-            @Override public void handle(TreeModificationEvent<T> e) {
-                
-                if (getSelectedIndex() == -1 && getSelectedItem() == null) return;
-                
-                final TreeItem<T> treeItem = e.getTreeItem();
-                if (treeItem == null) return;
 
-                treeView.expandedItemCountDirty = true;
-                
-                // we only shift selection from this row - everything before it
-                // is safe. We might change this below based on certain criteria
-                int startRow = treeView.getRow(treeItem);
-                
-                int shift = 0;
-                if (e.wasExpanded()) {
-                    // need to shuffle selection by the number of visible children
-                    shift = treeItem.getExpandedDescendentCount(false) - 1;
-                    startRow++;
-                } else if (e.wasCollapsed()) {
-                    // remove selection from any child treeItem, and also determine
-                    // if any child item was selected (in which case the parent
-                    // takes the selection on collapse)
-                    treeItem.getExpandedDescendentCount(false);
-                    final int count = treeItem.previousExpandedDescendentCount;
+        private EventHandler<TreeModificationEvent<T>> treeItemListener = e -> {
+            if (getSelectedIndex() == -1 && getSelectedItem() == null) return;
 
-                    final int selectedIndex = getSelectedIndex();
-                    final boolean wasPrimarySelectionInChild =
-                            selectedIndex >= (startRow + 1) &&
-                            selectedIndex < (startRow + count);
+            final TreeItem<T> treeItem = e.getTreeItem();
+            if (treeItem == null) return;
 
-                    boolean wasAnyChildSelected = false;
-                    for (int i = startRow + 1; i < startRow + count; i++) {
-                        if (isSelected(i)) {
-                            wasAnyChildSelected = true;
-                            clearSelection(i);
-                        }
+            treeView.expandedItemCountDirty = true;
+
+            // we only shift selection from this row - everything before it
+            // is safe. We might change this below based on certain criteria
+            int startRow = treeView.getRow(treeItem);
+
+            int shift = 0;
+            if (e.wasExpanded()) {
+                // need to shuffle selection by the number of visible children
+                shift = treeItem.getExpandedDescendentCount(false) - 1;
+                startRow++;
+            } else if (e.wasCollapsed()) {
+                // remove selection from any child treeItem, and also determine
+                // if any child item was selected (in which case the parent
+                // takes the selection on collapse)
+                treeItem.getExpandedDescendentCount(false);
+                final int count = treeItem.previousExpandedDescendentCount;
+
+                final int selectedIndex = getSelectedIndex();
+                final boolean wasPrimarySelectionInChild =
+                        selectedIndex >= (startRow + 1) &&
+                        selectedIndex < (startRow + count);
+
+                boolean wasAnyChildSelected = false;
+                for (int i = startRow + 1; i < startRow + count; i++) {
+                    if (isSelected(i)) {
+                        wasAnyChildSelected = true;
+                        clearSelection(i);
                     }
+                }
 
-                    // put selection onto the newly-collapsed tree item
-                    if (wasPrimarySelectionInChild && wasAnyChildSelected) {
-                        select(startRow);
-                    }
+                // put selection onto the newly-collapsed tree item
+                if (wasPrimarySelectionInChild && wasAnyChildSelected) {
+                    select(startRow);
+                }
 
-                    shift = - count + 1;
-                    startRow++;
-                } else if (e.wasPermutated()) {
-                    // no-op
-                } else if (e.wasAdded()) {
-                    // shuffle selection by the number of added items
-                    shift = treeItem.isExpanded() ? e.getAddedSize() : 0;
+                shift = - count + 1;
+                startRow++;
+            } else if (e.wasPermutated()) {
+                // no-op
+            } else if (e.wasAdded()) {
+                // shuffle selection by the number of added items
+                shift = treeItem.isExpanded() ? e.getAddedSize() : 0;
 
-                    // RT-32963: We were taking the startRow from the TreeItem
-                    // in which the children were added, rather than from the
-                    // actual position of the new child. This led to selection
-                    // being moved off the parent TreeItem by mistake.
-                    // The 'if (e.getAddedSize() == 1)' condition here was
-                    // subsequently commented out due to RT-33894.
-                    startRow = treeView.getRow(e.getAddedChildren().get(0));
-                } else if (e.wasRemoved()) {
-                    // shuffle selection by the number of removed items
-                    shift = treeItem.isExpanded() ? -e.getRemovedSize() : 0;
-                    
-                    // whilst we are here, we should check if the removed items
-                    // are part of the selectedItems list - and remove them
-                    // from selection if they are (as per RT-15446)
-                    final List<Integer> selectedIndices = getSelectedIndices();
-                    final int selectedIndex = getSelectedIndex();
-                    final List<TreeItem<T>> selectedItems = getSelectedItems();
-                    final TreeItem<T> selectedItem = getSelectedItem();
-                    final List<? extends TreeItem<T>> removedChildren = e.getRemovedChildren();
-                    
-                    for (int i = 0; i < selectedIndices.size() && ! selectedItems.isEmpty(); i++) {
-                        int index = selectedIndices.get(i);
-                        if (index > selectedItems.size()) break;
+                // RT-32963: We were taking the startRow from the TreeItem
+                // in which the children were added, rather than from the
+                // actual position of the new child. This led to selection
+                // being moved off the parent TreeItem by mistake.
+                // The 'if (e.getAddedSize() == 1)' condition here was
+                // subsequently commented out due to RT-33894.
+                startRow = treeView.getRow(e.getAddedChildren().get(0));
+            } else if (e.wasRemoved()) {
+                // shuffle selection by the number of removed items
+                shift = treeItem.isExpanded() ? -e.getRemovedSize() : 0;
 
-                        // Removed as part of RT-30356 consistency effort
+                // whilst we are here, we should check if the removed items
+                // are part of the selectedItems list - and remove them
+                // from selection if they are (as per RT-15446)
+                final List<Integer> selectedIndices1 = getSelectedIndices();
+                final int selectedIndex = getSelectedIndex();
+                final List<TreeItem<T>> selectedItems = getSelectedItems();
+                final TreeItem<T> selectedItem = getSelectedItem();
+                final List<? extends TreeItem<T>> removedChildren = e.getRemovedChildren();
+
+                for (int i = 0; i < selectedIndices1.size() && ! selectedItems.isEmpty(); i++) {
+                    int index = selectedIndices1.get(i);
+                    if (index > selectedItems.size()) break;
+
+                    // Removed as part of RT-30356 consistency effort
 //                        TreeItem<T> item = selectedItems.get(index);
 //                        if (item == null || removedChildren.contains(item)) {
 //                            clearSelection(index);
 //                        } else
-                        if (removedChildren.size() == 1 &&
-                                selectedItems.size() == 1 && 
-                                selectedItem != null && 
-                                selectedItem.equals(removedChildren.get(0))) {
-                            // Bug fix for RT-28637
-                            if (selectedIndex < getItemCount()) {
-                                final int previousRow = selectedIndex == 0 ? 0 : selectedIndex - 1;
-                                TreeItem<T> newSelectedItem = getModelItem(previousRow);
-                                if (! selectedItem.equals(newSelectedItem)) {
-                                    setSelectedItem(newSelectedItem);
-                                }
+                    if (removedChildren.size() == 1 &&
+                            selectedItems.size() == 1 &&
+                            selectedItem != null &&
+                            selectedItem.equals(removedChildren.get(0))) {
+                        // Bug fix for RT-28637
+                        if (selectedIndex < getItemCount()) {
+                            final int previousRow = selectedIndex == 0 ? 0 : selectedIndex - 1;
+                            TreeItem<T> newSelectedItem = getModelItem(previousRow);
+                            if (! selectedItem.equals(newSelectedItem)) {
+                                setSelectedItem(newSelectedItem);
                             }
                         }
                     }
                 }
-                
-                shiftSelection(startRow, shift, null);
             }
+
+            shiftSelection(startRow, shift, null);
         };
         
         private WeakChangeListener<TreeItem<T>> weakRootPropertyListener =
@@ -1417,6 +1410,7 @@
                 // We expect that in concrete subclasses of this class we observe the
                 // data model such that we check to see if the given item exists in it,
                 // whilst SelectedIndex == -1 && SelectedItem != null.
+                setSelectedIndex(-1);
                 setSelectedItem(obj);
             } else {
                 select(row);
@@ -1465,6 +1459,21 @@
 
             return treeView.getTreeItem(index);
         }
+
+
+
+        /***********************************************************************
+         *                                                                     *
+         * Private implementation                                              *
+         *                                                                     *
+         **********************************************************************/
+
+        private void updateDefaultSelection() {
+            // if we can, we put selection onto the first row
+            int newValueIndex = getItemCount() > 0 ? 0 : -1;
+            clearSelection();
+            select(newValueIndex);
+        }
     }
     
     
@@ -1481,6 +1490,10 @@
             this.treeView = treeView;
             this.treeView.rootProperty().addListener(weakRootPropertyListener);
             updateTreeEventListener(null, treeView.getRoot());
+
+            if (treeView.getExpandedItemCount() > 0) {
+                focus(0);
+            }
         }
         
         private final ChangeListener<TreeItem<T>> rootPropertyListener = (observable, oldValue, newValue) -> {
--- a/modules/controls/src/test/java/com/sun/javafx/scene/control/infrastructure/VirtualFlowTestUtils.java	Tue Sep 02 15:32:15 2014 +1200
+++ b/modules/controls/src/test/java/com/sun/javafx/scene/control/infrastructure/VirtualFlowTestUtils.java	Wed Sep 03 12:12:43 2014 +1200
@@ -248,14 +248,15 @@
             return rowCell;
         }
 
-        int count = 0;
+        int count = -1;
         for (Node n : rowCell.getChildrenUnmodifiable()) {
             if (! (n instanceof IndexedCell)) {
                 continue;
             }
             count++;
-            if (count < column) continue;
-            return (IndexedCell) n;
+            if (count == column) {
+                return (IndexedCell) n;
+            }
         }
         return null;
     }
--- a/modules/controls/src/test/java/javafx/scene/control/ListCellTest.java	Tue Sep 02 15:32:15 2014 +1200
+++ b/modules/controls/src/test/java/javafx/scene/control/ListCellTest.java	Wed Sep 03 12:12:43 2014 +1200
@@ -490,14 +490,14 @@
         cell.updateListView(list);
 
         // Other is configured to represent row 1 which is not focused.
-        ListCell<String> other = new ListCell<String>();
+        ListCell<String> other = new ListCell<>();
         other.updateListView(list);
         other.updateIndex(1);
 
-        // Replace with a null focus model, which should clear selection
+        // Replace with a null focus model, which should clear focused
         list.setFocusModel(null);
-        assertFalse(cell.isSelected());
-        assertFalse(other.isSelected());
+        assertFalse(cell.isFocused());
+        assertFalse(other.isFocused());
     }
 
     @Test public void replacingTheFocusModelRemovesTheListenerFromTheOldModel() {
--- a/modules/controls/src/test/java/javafx/scene/control/ListViewTest.java	Tue Sep 02 15:32:15 2014 +1200
+++ b/modules/controls/src/test/java/javafx/scene/control/ListViewTest.java	Wed Sep 03 12:12:43 2014 +1200
@@ -42,21 +42,14 @@
 import javafx.application.Platform;
 import javafx.beans.property.ObjectProperty;
 import javafx.beans.property.ReadOnlyBooleanWrapper;
-import javafx.beans.property.ReadOnlyObjectWrapper;
 import javafx.beans.property.SimpleObjectProperty;
-import javafx.beans.value.ChangeListener;
-import javafx.beans.value.ObservableValue;
 import javafx.collections.FXCollections;
 import javafx.collections.ListChangeListener;
 import javafx.collections.ObservableList;
 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;
-import javafx.scene.control.cell.TextFieldTreeCell;
 import javafx.scene.image.ImageView;
 import javafx.scene.input.KeyCode;
 import javafx.scene.layout.VBox;
@@ -79,7 +72,7 @@
     private MultipleSelectionModel<String> sm;
 
     @Before public void setup() {
-        listView = new ListView<String>();
+        listView = new ListView<>();
         sm = listView.getSelectionModel();
     }
 
@@ -109,34 +102,34 @@
     }
 
     @Test public void singleArgConstructorSetsTheStyleClass() {
-        final ListView<String> b2 = new ListView<String>(FXCollections.observableArrayList("Hi"));
+        final ListView<String> b2 = new ListView<>(FXCollections.observableArrayList("Hi"));
         assertStyleClassContains(b2, "list-view");
     }
 
     @Test public void singleArgConstructorSetsNonNullSelectionModel() {
-        final ListView<String> b2 = new ListView<String>(FXCollections.observableArrayList("Hi"));
+        final ListView<String> b2 = new ListView<>(FXCollections.observableArrayList("Hi"));
         assertNotNull(b2.getSelectionModel());
     }
 
     @Test public void singleArgConstructorAllowsNullItems() {
-        final ListView<String> b2 = new ListView<String>(null);
+        final ListView<String> b2 = new ListView<>(null);
         assertNull(b2.getItems());
     }
 
     @Test public void singleArgConstructorTakesItems() {
         ObservableList<String> items = FXCollections.observableArrayList("Hi");
-        final ListView<String> b2 = new ListView<String>(items);
+        final ListView<String> b2 = new ListView<>(items);
         assertSame(items, b2.getItems());
     }
 
     @Test public void singleArgConstructor_selectedItemIsNull() {
-        final ListView<String> b2 = new ListView<String>(FXCollections.observableArrayList("Hi"));
-        assertNull(b2.getSelectionModel().getSelectedItem());
+        final ListView<String> b2 = new ListView<>(FXCollections.observableArrayList("Hi"));
+        assertEquals("Hi", b2.getSelectionModel().getSelectedItem());
     }
 
     @Test public void singleArgConstructor_selectedIndexIsNegativeOne() {
-        final ListView<String> b2 = new ListView<String>(FXCollections.observableArrayList("Hi"));
-        assertEquals(-1, b2.getSelectionModel().getSelectedIndex());
+        final ListView<String> b2 = new ListView<>(FXCollections.observableArrayList("Hi"));
+        assertEquals(0, b2.getSelectionModel().getSelectedIndex());
     }
 
     /*********************************************************************
--- a/modules/controls/src/test/java/javafx/scene/control/MultipleSelectionModelImplTest.java	Tue Sep 02 15:32:15 2014 +1200
+++ b/modules/controls/src/test/java/javafx/scene/control/MultipleSelectionModelImplTest.java	Wed Sep 03 12:12:43 2014 +1200
@@ -34,8 +34,6 @@
 
 import java.util.*;
 
-import javafx.beans.value.ChangeListener;
-import javafx.beans.value.ObservableValue;
 import javafx.collections.FXCollections;
 import javafx.collections.ListChangeListener;
 import javafx.collections.ObservableList;
@@ -48,6 +46,7 @@
 
 import org.junit.After;
 import org.junit.AfterClass;
+import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Test;
@@ -62,8 +61,6 @@
  * and TreeView. This unit test attempts to test all known implementations, and
  * as such contains some conditional logic to handle the various controls as
  * simply as possible.
- *
- * @author Jonathan Giles
  */
 @RunWith(Parameterized.class)
 public class MultipleSelectionModelImplTest {
@@ -82,6 +79,7 @@
     private static ObservableList<String> data = FXCollections.<String>observableArrayList();
     private static final String ROW_1_VALUE = "Row 1";
     private static final String ROW_2_VALUE = "Row 2";
+    private static final String ROW_3_VALUE = "Long Row 3";
     private static final String ROW_5_VALUE = "Row 5";
     private static final String ROW_20_VALUE = "Row 20";
 
@@ -99,19 +97,19 @@
 
     static {
         // ListView init
-        defaultData.addAll(ROW_1_VALUE, ROW_2_VALUE, "Long Row 3", "Row 4", ROW_5_VALUE, "Row 6",
+        defaultData.addAll(ROW_1_VALUE, ROW_2_VALUE, ROW_3_VALUE, "Row 4", ROW_5_VALUE, "Row 6",
                 "Row 7", "Row 8", "Row 9", "Row 10", "Row 11", "Row 12", "Row 13",
                 "Row 14", "Row 15", "Row 16", "Row 17", "Row 18", "Row 19", ROW_20_VALUE);
 
         data.setAll(defaultData);
-        listView = new ListView<String>(data);
+        listView = new ListView<>(data);
         // --- ListView init
 
         // TreeView init
-        root = new TreeItem<String>(ROW_1_VALUE);
+        root = new TreeItem<>(ROW_1_VALUE);
         root.setExpanded(true);
         for (int i = 1; i < data.size(); i++) {
-            root.getChildren().add(new TreeItem<String>(data.get(i)));
+            root.getChildren().add(new TreeItem<>(data.get(i)));
         }
         ROW_2_TREE_VALUE = root.getChildren().get(0);
         ROW_5_TREE_VALUE = root.getChildren().get(3);
@@ -235,7 +233,7 @@
                model instanceof TreeTableView.TreeTableViewArrayListSelectionModel;
     }
 
-    @Test public void ensureInEmptyState() {
+    private void ensureInEmptyState() {
         assertEquals(-1, model.getSelectedIndex());
         assertNull(model.getSelectedItem());
 
@@ -250,8 +248,24 @@
         assertEquals(0, msModel().getSelectedItems().size());
     }
 
+    @Test public void ensureInDefaultState() {
+        assertEquals(0, model.getSelectedIndex());
+        assertNotNull(model.getSelectedItem());
+
+        if (focusModel != null) {
+            assertEquals(0, focusModel.getFocusedIndex());
+            assertNotNull(focusModel.getFocusedItem());
+        }
+
+        assertNotNull(msModel().getSelectedIndices());
+        assertNotNull(msModel().getSelectedItems());
+        assertEquals(1, msModel().getSelectedIndices().size());
+        assertEquals(1, msModel().getSelectedItems().size());
+    }
+
     @Test public void selectValidIndex() {
         int index = 4;
+        model.clearSelection();
         model.select(index);
 
         assertEquals(index, model.getSelectedIndex());
@@ -275,10 +289,11 @@
     @Test public void testSelectAllWithSingleSelection() {
         msModel().setSelectionMode(SelectionMode.SINGLE);
         msModel().selectAll();
-        ensureInEmptyState();
+        ensureInDefaultState();
     }
 
     @Test public void testSelectAllWithMultipleSelection() {
+        msModel().clearSelection();
         msModel().selectAll();
 
         assertEquals(19, model.getSelectedIndex());
@@ -300,6 +315,7 @@
     }
 
     @Test public void clearPartialSelectionWithSingleSelection() {
+        model.clearSelection();
         assertFalse(model.isSelected(5));
         model.select(5);
         assertTrue(model.isSelected(5));
@@ -320,19 +336,20 @@
         assertTrue(model.isSelected(6));
     }
 
-    @Test public void testSelectedIndicesObservableListIsEmpty() {
-        assertTrue(msModel().getSelectedIndices().isEmpty());
+    @Test public void testSelectedIndicesObservableListIsNotEmpty() {
+        assertFalse(msModel().getSelectedIndices().isEmpty());
     }
 
     @Test public void testSelectedIndicesIteratorIsNotNull() {
         assertNotNull(msModel().getSelectedIndices().iterator());
     }
 
-    @Test public void testSelectedIndicesIteratorDoesNotHaveNext() {
-        assertFalse(msModel().getSelectedIndices().iterator().hasNext());
+    @Test public void testSelectedIndicesIteratorHasNext() {
+        assertTrue(msModel().getSelectedIndices().iterator().hasNext());
     }
 
     @Test public void testSelectedIndicesIteratorWorksWithSingleSelection() {
+        msModel().clearSelection();
         model.select(5);
 
         Iterator<Integer> it = msModel().getSelectedIndices().iterator();
@@ -341,6 +358,7 @@
     }
 
     @Test public void testSelectedIndicesIteratorWorksWithMultipleSelection() {
+        msModel().clearSelection();
         msModel().setSelectionMode(SelectionMode.MULTIPLE);
         msModel().selectIndices(1, 2, 5);
 
@@ -356,11 +374,12 @@
         assertTrue(msModel().getSelectedIndices().contains(5));
     }
 
-    @Test public void testSelectedItemsObservableListIsEmpty() {
-        assertTrue(msModel().getSelectedItems().isEmpty());
+    @Test public void testSelectedItemsObservableListIsNotEmpty() {
+        assertFalse(msModel().getSelectedItems().isEmpty());
     }
 
     @Test public void testSelectedItemsIndexOf() {
+        msModel().clearSelection();
         if (isTree()) {
             model.select(ROW_2_TREE_VALUE);
             assertEquals(1, msModel().getSelectedItems().size());
@@ -377,6 +396,7 @@
     }
 
     @Test public void testSelectedItemsLastIndexOf() {
+        msModel().clearSelection();
         if (isTree()) {
             model.select(ROW_2_TREE_VALUE);
             assertEquals(1, msModel().getSelectedItems().size());
@@ -394,6 +414,7 @@
     }
 
     @Test public void testSingleSelectionMode() {
+        msModel().clearSelection();
         msModel().setSelectionMode(SelectionMode.SINGLE);
         assertTrue(model.isEmpty());
 
@@ -409,6 +430,7 @@
     }
 
     @Test public void testMultipleSelectionMode() {
+        msModel().clearSelection();
         msModel().setSelectionMode(SelectionMode.MULTIPLE);
         assertTrue(model.isEmpty());
 
@@ -423,6 +445,7 @@
     }
 
     @Test public void testChangeSelectionMode() {
+        msModel().clearSelection();
         msModel().setSelectionMode(SelectionMode.MULTIPLE);
         msModel().selectIndices(5, 10, 15);
         assertEquals(indices(msModel()), 3, msModel().getSelectedIndices().size());
@@ -446,6 +469,7 @@
     @Test public void testSelectRange() {
         // should select all indices starting at 5, and finishing just before
         // the 10th item
+        msModel().clearSelection();
         msModel().setSelectionMode(SelectionMode.MULTIPLE);
         msModel().selectRange(5, 10);
         assertEquals(indices(msModel()), 5, msModel().getSelectedIndices().size());
@@ -469,6 +493,7 @@
     }
 
     @Test public void testAccurateItemSelection() {
+        msModel().clearSelection();
         msModel().setSelectionMode(SelectionMode.MULTIPLE);
         msModel().selectRange(2, 5);
         ObservableList selectedItems = msModel().getSelectedItems();
@@ -581,6 +606,7 @@
     }
 
     @Test public void testMultipleSelectionWithEmptyArray() {
+        msModel().clearSelection();
         msModel().setSelectionMode(SelectionMode.MULTIPLE);
         msModel().selectIndices(3,new int[] { });
         assertEquals(3, model.getSelectedIndex());
@@ -612,6 +638,7 @@
 
     @Test public void selectOnlyValidIndicesInMultipleSelection() {
         msModel().setSelectionMode(SelectionMode.MULTIPLE);
+        model.clearSelection();
         msModel().selectIndices(750397, 3, 709709375, 4, 8597998, 47929);
         assertEquals(4, model.getSelectedIndex());
         assertTrue(model.isSelected(3));
@@ -627,6 +654,7 @@
     }
 
     @Test public void testNullArrayInMultipleSelection() {
+        msModel().clearSelection();
         msModel().setSelectionMode(SelectionMode.MULTIPLE);
         msModel().selectIndices(-20, null);
         assertEquals(-1, model.getSelectedIndex());
@@ -636,6 +664,7 @@
     }
 
     @Test public void testMultipleSelectionWithInvalidIndices() {
+        msModel().clearSelection();
         msModel().setSelectionMode(SelectionMode.MULTIPLE);
         msModel().selectIndices(-20, 23505, 78125);
         assertEquals(-1, model.getSelectedIndex());
@@ -645,6 +674,7 @@
     }
 
     @Test public void testInvalidSelection() {
+        msModel().clearSelection();
         msModel().setSelectionMode(SelectionMode.SINGLE);
         msModel().selectIndices(-20, null);
         assertEquals(-1, model.getSelectedIndex());
@@ -655,6 +685,7 @@
 
     @Test public void ensureSwappedSelectRangeWorks() {
         // first test a valid range - there should be 6 selected items
+        model.clearSelection();
         model.setSelectionMode(SelectionMode.MULTIPLE);
         model.selectRange(3, 10);
         assertEquals(indices(model), 7, model.getSelectedIndices().size());
@@ -679,6 +710,7 @@
     }
 
     @Test public void testInvalidSelectRange() {
+        msModel().clearSelection();
         msModel().setSelectionMode(SelectionMode.MULTIPLE);
         msModel().selectRange(200, 220);
         assertEquals(-1, model.getSelectedIndex());
@@ -688,6 +720,7 @@
     }
 
     @Test public void testEmptySelectRange() {
+        msModel().clearSelection();
         msModel().setSelectionMode(SelectionMode.MULTIPLE);
         msModel().selectRange(10, 10);
         assertEquals(-1, model.getSelectedIndex());
@@ -697,6 +730,7 @@
     }
 
     @Test public void testNegativeSelectRange() {
+        msModel().clearSelection();
         msModel().setSelectionMode(SelectionMode.MULTIPLE);
         msModel().selectRange(-10, -1);
         assertEquals(-1, model.getSelectedIndex());
@@ -716,6 +750,7 @@
     }
 
     @Test public void selectAllInEmptySingleSelectionMode() {
+        model.clearSelection();
         msModel().setSelectionMode(SelectionMode.SINGLE);
         assertTrue(model.isEmpty());
         msModel().selectAll();
@@ -724,6 +759,7 @@
 
     @Test public void selectAllInSingleSelectionModeWithSelectedRow() {
         msModel().setSelectionMode(SelectionMode.SINGLE);
+        model.clearSelection();
         assertTrue(model.isEmpty());
         model.select(3);
         msModel().selectAll();
@@ -755,26 +791,24 @@
     private int rt_28615_row_1_hit_count = 0;
     private int rt_28615_row_2_hit_count = 0;
     @Test public void test_rt_28615() {
+        model.clearSelection();
         msModel().setSelectionMode(SelectionMode.MULTIPLE);
 
-        msModel().getSelectedItems().addListener(new ListChangeListener<Object>() {
-            @Override
-            public void onChanged(ListChangeListener.Change<? extends Object> change) {
-                while (change.next()) {
-                    if (change.wasAdded()) {
-                        for (Object item : change.getAddedSubList()) {
-                            if (isTree()) {
-                                if (root.equals(item)) {
-                                    rt_28615_row_1_hit_count++;
-                                } else if (ROW_2_TREE_VALUE.equals(item)) {
-                                    rt_28615_row_2_hit_count++;
-                                }
-                            } else {
-                                if (ROW_1_VALUE.equals(item)) {
-                                    rt_28615_row_1_hit_count++;
-                                } else if (ROW_2_VALUE.equals(item)) {
-                                    rt_28615_row_2_hit_count++;
-                                }
+        msModel().getSelectedItems().addListener((ListChangeListener.Change change) -> {
+            while (change.next()) {
+                if (change.wasAdded()) {
+                    for (Object item : change.getAddedSubList()) {
+                        if (isTree()) {
+                            if (root.equals(item)) {
+                                rt_28615_row_1_hit_count++;
+                            } else if (ROW_2_TREE_VALUE.equals(item)) {
+                                rt_28615_row_2_hit_count++;
+                            }
+                        } else {
+                            if (ROW_1_VALUE.equals(item)) {
+                                rt_28615_row_1_hit_count++;
+                            } else if (ROW_2_VALUE.equals(item)) {
+                                rt_28615_row_2_hit_count++;
                             }
                         }
                     }
@@ -796,15 +830,13 @@
     
     private int rt_29860_size_count = 0;
     @Test public void test_rt_29860_add() {
+        model.clearSelection();
         msModel().setSelectionMode(SelectionMode.MULTIPLE);
 
-        msModel().getSelectedIndices().addListener(new ListChangeListener<Object>() {
-            @Override
-            public void onChanged(ListChangeListener.Change<? extends Object> change) {
-                while (change.next()) {
-                    if (change.wasAdded()) {
-                        rt_29860_size_count += change.getAddedSize();
-                    }
+        msModel().getSelectedIndices().addListener((ListChangeListener.Change change) -> {
+            while (change.next()) {
+                if (change.wasAdded()) {
+                    rt_29860_size_count += change.getAddedSize();
                 }
             }
         });
@@ -849,12 +881,12 @@
     private int rt_32411_add_count = 0;
     private int rt_32411_remove_count = 0;
     @Test public void test_rt_32411_selectedItems() {
-        model.getSelectedItems().addListener(new ListChangeListener<String>() {
-            @Override public void onChanged(final Change<? extends String> change) {
-                while (change.next()) {
-                    rt_32411_remove_count += change.getRemovedSize();
-                    rt_32411_add_count += change.getAddedSize();
-                }
+        model.clearSelection();
+
+        model.getSelectedItems().addListener((ListChangeListener.Change change) -> {
+            while (change.next()) {
+                rt_32411_remove_count += change.getRemovedSize();
+                rt_32411_add_count += change.getAddedSize();
             }
         });
 
@@ -875,12 +907,12 @@
     }
 
     @Test public void test_rt_32411_selectedIndices() {
-        model.getSelectedIndices().addListener(new ListChangeListener<Number>() {
-            @Override public void onChanged(final Change<? extends Number> change) {
-                while (change.next()) {
-                    rt_32411_remove_count += change.getRemovedSize();
-                    rt_32411_add_count += change.getAddedSize();
-                }
+        model.clearSelection();
+
+        model.getSelectedIndices().addListener((ListChangeListener.Change change) -> {
+            while (change.next()) {
+                rt_32411_remove_count += change.getRemovedSize();
+                rt_32411_add_count += change.getAddedSize();
             }
         });
 
@@ -902,21 +934,17 @@
 
     private int rt32618_count = 0;
     @Test public void test_rt32618_multipleSelection() {
-        model.selectedItemProperty().addListener(new ChangeListener<Object>() {
-            @Override public void changed(ObservableValue<? extends Object> ov, Object t, Object t1) {
-                rt32618_count++;
-            }
-        });
+        model.selectedItemProperty().addListener((ov, t, t1) -> rt32618_count++);
 
         assertEquals(0, rt32618_count);
 
-        model.select(0);
+        model.select(1);
         assertEquals(1, rt32618_count);
-        assertEquals(ROW_1_VALUE, getValue(model.getSelectedItem()));
+        assertEquals(ROW_2_VALUE, getValue(model.getSelectedItem()));
 
-        model.clearAndSelect(1);
+        model.clearAndSelect(2);
         assertEquals(2, rt32618_count);
-        assertEquals(ROW_2_VALUE, getValue(model.getSelectedItem()));
+        assertEquals(ROW_3_VALUE, getValue(model.getSelectedItem()));
     }
 
     @Test public void test_rt33324_selectedIndices() {
@@ -924,15 +952,13 @@
         model.select(0);
 
         // install listener
-        model.getSelectedIndices().addListener(new ListChangeListener<Integer>() {
-            @Override public void onChanged(ListChangeListener.Change<? extends Integer> change) {
-                while (change.next()) {
-                    assertTrue(change.wasRemoved());
-                    assertTrue(change.wasAdded());
-                    assertTrue(change.wasReplaced());
+        model.getSelectedIndices().addListener((ListChangeListener.Change change) -> {
+            while (change.next()) {
+                assertTrue(change.wasRemoved());
+                assertTrue(change.wasAdded());
+                assertTrue(change.wasReplaced());
 
-                    assertFalse(change.wasPermutated());
-                }
+                assertFalse(change.wasPermutated());
             }
         });
 
@@ -947,15 +973,13 @@
         model.select(0);
 
         // install listener
-        model.getSelectedItems().addListener(new ListChangeListener() {
-            @Override public void onChanged(ListChangeListener.Change change) {
-                while (change.next()) {
-                    assertTrue(change.wasRemoved());
-                    assertTrue(change.wasAdded());
-                    assertTrue(change.wasReplaced());
+        model.getSelectedItems().addListener((ListChangeListener.Change change) -> {
+            while (change.next()) {
+                assertTrue(change.wasRemoved());
+                assertTrue(change.wasAdded());
+                assertTrue(change.wasReplaced());
 
-                    assertFalse(change.wasPermutated());
-                }
+                assertFalse(change.wasPermutated());
             }
         });
 
@@ -976,15 +1000,13 @@
         tableSM.select(0);
 
         // install listener
-        tableSM.getSelectedCells().addListener(new ListChangeListener() {
-            @Override public void onChanged(ListChangeListener.Change change) {
-                while (change.next()) {
-                    assertTrue(change.wasRemoved());
-                    assertTrue(change.wasAdded());
-                    assertTrue(change.wasReplaced());
+        tableSM.getSelectedCells().addListener((ListChangeListener.Change change) -> {
+            while (change.next()) {
+                assertTrue(change.wasRemoved());
+                assertTrue(change.wasAdded());
+                assertTrue(change.wasReplaced());
 
-                    assertFalse(change.wasPermutated());
-                }
+                assertFalse(change.wasPermutated());
             }
         });
 
@@ -995,136 +1017,131 @@
     }
 
     @Test public void test_rt35624_selectedIndices_downwards() {
+        model.clearSelection();
         model.select(2);
 
-        msModel().getSelectedIndices().addListener(new ListChangeListener<Integer>() {
-            @Override public void onChanged(final Change<? extends Integer> change) {
-                while (change.next()) {
-                    // we expect two items in the added list: 3 and 4, as index
-                    // 2 has previously been selected
-                    assertEquals(2, change.getAddedSize());
-                    assertEquals(FXCollections.observableArrayList(3, 4), change.getAddedSubList());
-                }
+        msModel().getSelectedIndices().addListener((ListChangeListener.Change change) -> {
+            while (change.next()) {
+                // we expect two items in the added list: 3 and 4, as index
+                // 2 has previously been selected
+                Assert.assertEquals(2, change.getAddedSize());
+                Assert.assertEquals(FXCollections.observableArrayList(3, 4), change.getAddedSubList());
+            }
 
-                // In the actual list, we expect three items: 2, 3 and 4
-                assertEquals(3, change.getList().size());
-                assertEquals(FXCollections.observableArrayList(2, 3, 4), change.getList());
-            }
+            // In the actual list, we expect three items: 2, 3 and 4
+            Assert.assertEquals(3, change.getList().size());
+            Assert.assertEquals(FXCollections.observableArrayList(2, 3, 4), change.getList());
         });
 
         model.selectIndices(2, 3, 4);
     }
 
     @Test public void test_rt35624_selectedIndices_upwards() {
+        model.clearSelection();
         model.select(4);
 
-        msModel().getSelectedIndices().addListener(new ListChangeListener<Integer>() {
-            @Override public void onChanged(final Change<? extends Integer> change) {
-                while (change.next()) {
-                    // we expect two items in the added list: 3 and 2, as index
-                    // 4 has previously been selected
-                    assertEquals(2, change.getAddedSize());
-                    assertEquals(FXCollections.observableArrayList(2, 3), change.getAddedSubList());
-                }
+        msModel().getSelectedIndices().addListener(((ListChangeListener.Change change) -> {
+            while (change.next()) {
+                // we expect two items in the added list: 3 and 2, as index
+                // 4 has previously been selected
+                assertEquals(2, change.getAddedSize());
+                assertEquals(FXCollections.observableArrayList(2, 3), change.getAddedSubList());
+            }
 
-                // In the actual list, we expect three items: 2, 3 and 4
-                assertEquals(3, change.getList().size());
-                assertEquals(FXCollections.observableArrayList(2, 3, 4), change.getList());
-            }
-        });
+            // In the actual list, we expect three items: 2, 3 and 4
+            assertEquals(3, change.getList().size());
+            assertEquals(FXCollections.observableArrayList(2, 3, 4), change.getList());
+        }));
 
         model.selectIndices(4, 3, 2);
     }
 
     @Test public void test_rt35624_selectedItems_downwards() {
+        model.clearSelection();
         model.select(2);
 
-        msModel().getSelectedItems().addListener(new ListChangeListener<String>() {
-            @Override public void onChanged(final Change<? extends String> change) {
-                while (change.next()) {
-                    // we expect two items in the added list: the items in index
-                    // 3 and 4, as index 2 has previously been selected
-                    assertEquals(2, change.getAddedSize());
-
-                    if (isTree()) {
-                        assertEquals(FXCollections.observableArrayList(
-                                root.getChildren().get(2),
-                                root.getChildren().get(3)
-                        ), change.getAddedSubList());
-                    } else {
-                        assertEquals(FXCollections.observableArrayList(
-                                data.get(3),
-                                data.get(4)
-                        ), change.getAddedSubList());
-                    }
-                }
-
-                // In the actual list, we expect three items: the values at index
-                // 2, 3 and 4
-                assertEquals(3, change.getList().size());
+        msModel().getSelectedItems().addListener(((ListChangeListener.Change change) -> {
+            while (change.next()) {
+                // we expect two items in the added list: the items in index
+                // 3 and 4, as index 2 has previously been selected
+                assertEquals(2, change.getAddedSize());
 
                 if (isTree()) {
                     assertEquals(FXCollections.observableArrayList(
-                            root.getChildren().get(1),
                             root.getChildren().get(2),
                             root.getChildren().get(3)
-                    ), change.getList());
+                    ), change.getAddedSubList());
                 } else {
                     assertEquals(FXCollections.observableArrayList(
-                            data.get(2),
                             data.get(3),
                             data.get(4)
-                    ), change.getList());
+                    ), change.getAddedSubList());
                 }
             }
-        });
+
+            // In the actual list, we expect three items: the values at index
+            // 2, 3 and 4
+            assertEquals(3, change.getList().size());
+
+            if (isTree()) {
+                assertEquals(FXCollections.observableArrayList(
+                        root.getChildren().get(1),
+                        root.getChildren().get(2),
+                        root.getChildren().get(3)
+                ), change.getList());
+            } else {
+                assertEquals(FXCollections.observableArrayList(
+                        data.get(2),
+                        data.get(3),
+                        data.get(4)
+                ), change.getList());
+            }
+        }));
 
         model.selectIndices(2, 3, 4);
     }
 
     @Test public void test_rt35624_selectedItems_upwards() {
+        model.clearSelection();
         model.select(4);
 
-        msModel().getSelectedItems().addListener(new ListChangeListener<String>() {
-            @Override
-            public void onChanged(final Change<? extends String> change) {
-                while (change.next()) {
-                    // we expect two items in the added list: the items in index
-                    // 2 and 3, as index 4 has previously been selected
-                    assertEquals(2, change.getAddedSize());
-
-                    if (isTree()) {
-                        assertEquals(FXCollections.observableArrayList(
-                                root.getChildren().get(1),
-                                root.getChildren().get(2)
-                        ), change.getAddedSubList());
-                    } else {
-                        assertEquals(FXCollections.observableArrayList(
-                                data.get(2),
-                                data.get(3)
-                        ), change.getAddedSubList());
-                    }
-                }
-
-                // In the actual list, we expect three items: the values at index
-                // 2, 3 and 4
-                assertEquals(3, change.getList().size());
+        msModel().getSelectedItems().addListener(((ListChangeListener.Change change) -> {
+            while (change.next()) {
+                // we expect two items in the added list: the items in index
+                // 2 and 3, as index 4 has previously been selected
+                assertEquals(2, change.getAddedSize());
 
                 if (isTree()) {
                     assertEquals(FXCollections.observableArrayList(
                             root.getChildren().get(1),
-                            root.getChildren().get(2),
-                            root.getChildren().get(3)
-                    ), change.getList());
+                            root.getChildren().get(2)
+                    ), change.getAddedSubList());
                 } else {
                     assertEquals(FXCollections.observableArrayList(
                             data.get(2),
-                            data.get(3),
-                            data.get(4)
-                    ), change.getList());
+                            data.get(3)
+                    ), change.getAddedSubList());
                 }
             }
-        });
+
+            // In the actual list, we expect three items: the values at index
+            // 2, 3 and 4
+            assertEquals(3, change.getList().size());
+
+            if (isTree()) {
+                assertEquals(FXCollections.observableArrayList(
+                        root.getChildren().get(1),
+                        root.getChildren().get(2),
+                        root.getChildren().get(3)
+                ), change.getList());
+            } else {
+                assertEquals(FXCollections.observableArrayList(
+                        data.get(2),
+                        data.get(3),
+                        data.get(4)
+                ), change.getList());
+            }
+        }));
 
         model.selectIndices(4, 3, 2);
     }
--- a/modules/controls/src/test/java/javafx/scene/control/SelectionModelImplTest.java	Tue Sep 02 15:32:15 2014 +1200
+++ b/modules/controls/src/test/java/javafx/scene/control/SelectionModelImplTest.java	Wed Sep 03 12:12:43 2014 +1200
@@ -109,9 +109,9 @@
             { ListView.ListViewBitSetSelectionModel.class },
             { TreeView.TreeViewBitSetSelectionModel.class },
             { TableView.TableViewArrayListSelectionModel.class },
-            { TreeTableView.TreeTableViewArrayListSelectionModel.class },
-            { ChoiceBox.ChoiceBoxSelectionModel.class },
-            { ComboBox.ComboBoxSelectionModel.class }
+            { TreeTableView.TreeTableViewArrayListSelectionModel.class }
+//            { ChoiceBox.ChoiceBoxSelectionModel.class } TODO re-enable
+//            { ComboBox.ComboBoxSelectionModel.class }  TODO re-enable
         });
     }
 
@@ -249,43 +249,48 @@
         return item;
     }
 
-    @Test public void ensureInEmptyState() {
-        assertEquals(-1, model.getSelectedIndex());
-        assertNull(model.getSelectedItem());
+    @Test public void testDefaultState() {
+        assertEquals(0, model.getSelectedIndex());
+        assertEquals(ROW_1_VALUE, getValue(model.getSelectedItem()));
 
         if (focusModel != null) {
-            assertEquals(-1, focusModel.getFocusedIndex());
-            assertNull(focusModel.getFocusedItem());
+            assertEquals(0, focusModel.getFocusedIndex());
+            assertEquals(ROW_1_VALUE, getValue(focusModel.getFocusedItem()));
         }
     }
 
     @Test public void selectInvalidIndex() {
         // there isn't 100 rows, so selecting this shouldn't be possible
         model.select(100);
-        ensureInEmptyState();
+
+        // we should be in a default state
+        testDefaultState();
     }
 
     @Test public void selectRowAfterInvalidIndex() {
         // there isn't 100 rows, so selecting this shouldn't be possible.
-        // The end result should be that we remain at the -1 index
+        // The end result should be that we remain at the 0 index
         model.select(100);
 
-        // go to the 0th index
-        model.selectNext();
-        assertEquals(0, model.getSelectedIndex());
-        if (focusModel != null) assertEquals(0, focusModel.getFocusedIndex());
-
         // go to the 1st index
         model.selectNext();
         assertEquals(1, model.getSelectedIndex());
         if (focusModel != null) assertEquals(1, focusModel.getFocusedIndex());
+
+        // go to the 2nd index
+        model.selectNext();
+        assertEquals(2, model.getSelectedIndex());
+        if (focusModel != null) assertEquals(2, focusModel.getFocusedIndex());
     }
 
     @Test public void selectInvalidItem() {
+        assertEquals(0, model.getSelectedIndex());
+
         Object obj = new TreeItem("DUMMY");
         model.select(obj);
+
+        assertSame(obj, model.getSelectedItem());
         assertEquals(-1, model.getSelectedIndex());
-        assertSame(obj, model.getSelectedItem());
     }
 
     @Test public void selectValidIndex() {
@@ -312,6 +317,8 @@
     }
 
     @Test public void ensureIsEmptyIsAccurate() {
+        assertFalse(model.isEmpty());
+        model.clearSelection();
         assertTrue(model.isEmpty());
         model.select(5);
         assertFalse(model.isEmpty());
@@ -320,6 +327,7 @@
     }
 
     @Test public void testSingleSelectionMode() {
+        model.clearSelection();
         assertTrue(model.isEmpty());
 
         model.select(5);
@@ -336,7 +344,7 @@
 
     @Test public void testFocusOnNegativeIndex() {
         if (focusModel == null) return;
-        assertEquals(-1, focusModel.getFocusedIndex());
+        assertEquals(0, focusModel.getFocusedIndex());
         focusModel.focus(-1);
         assertEquals(-1, focusModel.getFocusedIndex());
         assertFalse(focusModel.isFocused(-1));
@@ -344,7 +352,7 @@
 
     @Test public void testFocusOnOutOfBoundsIndex() {
         if (focusModel == null) return;
-        assertEquals(-1, focusModel.getFocusedIndex());
+        assertEquals(0, focusModel.getFocusedIndex());
         focusModel.focus(Integer.MAX_VALUE);
         assertEquals(-1, focusModel.getFocusedIndex());
         assertNull(focusModel.getFocusedItem());
@@ -353,7 +361,7 @@
 
     @Test public void testFocusOnValidIndex() {
         if (focusModel == null) return;
-        assertEquals(-1, focusModel.getFocusedIndex());
+        assertEquals(0, focusModel.getFocusedIndex());
         focusModel.focus(1);
         assertEquals(1, focusModel.getFocusedIndex());
         assertTrue(focusModel.isFocused(1));
@@ -510,12 +518,12 @@
 
         assertEquals(0, rt32618_count);
 
-        model.select(0);
+        model.select(1);
         assertEquals(1, rt32618_count);
-        assertEquals(ROW_1_VALUE, getValue(model.getSelectedItem()));
+        assertEquals(ROW_2_VALUE, getValue(model.getSelectedItem()));
 
-        model.clearAndSelect(1);
+        model.clearAndSelect(2);
         assertEquals(2, rt32618_count);
-        assertEquals(ROW_2_VALUE, getValue(model.getSelectedItem()));
+        assertEquals(ROW_3_VALUE, getValue(model.getSelectedItem()));
     }
 }
--- a/modules/controls/src/test/java/javafx/scene/control/TableViewKeyInputTest.java	Tue Sep 02 15:32:15 2014 +1200
+++ b/modules/controls/src/test/java/javafx/scene/control/TableViewKeyInputTest.java	Wed Sep 03 12:12:43 2014 +1200
@@ -29,11 +29,14 @@
 import javafx.beans.Observable;
 import javafx.beans.property.ReadOnlyStringWrapper;
 import javafx.beans.value.ObservableValue;
+import javafx.collections.FXCollections;
 import javafx.collections.ObservableList;
 import javafx.event.EventHandler;
 import javafx.scene.input.KeyCode;
 import javafx.scene.layout.HBox;
 import javafx.util.Callback;
+
+import java.util.ArrayList;
 import java.util.List;
 import com.sun.javafx.PlatformUtil;
 import com.sun.javafx.Utils;
@@ -159,9 +162,9 @@
      **************************************************************************/    
     
     @Test public void testInitialState() {
-        assertTrue(sm.getSelectedCells().isEmpty());
-        assertTrue(sm.getSelectedIndices().isEmpty());
-        assertTrue(sm.getSelectedItems().isEmpty());
+        assertEquals(1,sm.getSelectedCells().size());
+        assertEquals(1,sm.getSelectedIndices().size());
+        assertEquals(1,sm.getSelectedItems().size());
     }
     
     
@@ -1365,12 +1368,13 @@
         sm.setSelectionMode(SelectionMode.MULTIPLE);
         sm.setCellSelectionEnabled(true);
         sm.select(5, col1);
+        assertTrue(debug(), isAnchor(5,1));
 
         keyboard.doKeyPress(KeyCode.HOME, KeyModifier.SHIFT, KeyModifier.getShortcutKey());
         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.getItems().size() - 1; i++) {
@@ -2257,7 +2261,7 @@
         keyboard.doKeyPress(KeyCode.UP, KeyModifier.getShortcutKey());
         keyboard.doKeyPress(KeyCode.UP, KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
         Toolkit.getToolkit().firePulse();
-        assertTrue(isSelected(7,6,5,4));
+        assertTrue(isSelected(7, 6, 5, 4));
         assertEquals(4, sm.getSelectedItems().size());
     }
 
@@ -2275,10 +2279,10 @@
         keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey());
         keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey());
         keyboard.doKeyPress(KeyCode.SPACE, KeyModifier.getShortcutKey(), PlatformUtil.isMac() ? KeyModifier.CTRL : null);
-        keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey());
-        keyboard.doKeyPress(KeyCode.UP,  KeyModifier.SHIFT);
+        keyboard.doKeyPress(KeyCode.UP, KeyModifier.getShortcutKey());
+        keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT);
         Toolkit.getToolkit().firePulse();
-        assertTrue(isSelected(5,4,3));
+        assertTrue(isSelected(5, 4, 3));
         assertEquals(3, sm.getSelectedItems().size());
     }
 
@@ -2296,10 +2300,10 @@
         keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey());
         keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey());
         keyboard.doKeyPress(KeyCode.SPACE, KeyModifier.getShortcutKey(), PlatformUtil.isMac() ? KeyModifier.CTRL : null);
-        keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey());
-        keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
+        keyboard.doKeyPress(KeyCode.UP, KeyModifier.getShortcutKey());
+        keyboard.doKeyPress(KeyCode.UP, KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
         Toolkit.getToolkit().firePulse();
-        assertTrue(isSelected(7,5,4,3));
+        assertTrue(isSelected(7, 5, 4, 3));
         assertEquals(4, sm.getSelectedItems().size());
     }
 
@@ -2347,8 +2351,8 @@
         sm.setCellSelectionEnabled(false);
         sm.clearAndSelect(2);
 
-        keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 1
-        keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 0
+        keyboard.doKeyPress(KeyCode.UP, KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 1
+        keyboard.doKeyPress(KeyCode.UP, KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 0
         Toolkit.getToolkit().firePulse();
         assertTrue(isNotSelected(3,4));
         assertTrue(isSelected(0,1,2));
@@ -2359,7 +2363,7 @@
         keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 0
         keyboard.doKeyPress(KeyCode.UP,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 0
         Toolkit.getToolkit().firePulse();
-        assertTrue(isNotSelected(3,4));
+        assertTrue(isNotSelected(3, 4));
         assertTrue(isSelected(0,1,2));
         assertEquals(3, sm.getSelectedItems().size());
         assertTrue(fm.isFocused(0));
@@ -2378,8 +2382,8 @@
         sm.setCellSelectionEnabled(false);
         sm.clearAndSelect(2);
 
-        keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 3
-        keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 4
+        keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 3
+        keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // row 4
         Toolkit.getToolkit().firePulse();
         assertTrue(isNotSelected(0,1,2,3));
         assertTrue(isSelected(4));
@@ -2390,7 +2394,7 @@
         keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 4
         keyboard.doKeyPress(KeyCode.DOWN,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT); // should stay at row 4
         Toolkit.getToolkit().firePulse();
-        assertTrue(isNotSelected(0,1,2,3));
+        assertTrue(isNotSelected(0, 1, 2, 3));
         assertTrue(isSelected(4));
         assertEquals(1, sm.getSelectedItems().size());
         assertTrue(fm.isFocused(4));
@@ -2436,14 +2440,14 @@
         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.getShortcutKey());
         keyboard.doKeyPress(KeyCode.DOWN, KeyModifier.getShortcutKey());
         Toolkit.getToolkit().firePulse();
-        assertTrue(isNotSelected(1,2,3));
+        assertTrue(isNotSelected(1, 2, 3));
         assertTrue(isSelected(0));
         assertEquals(1, sm.getSelectedItems().size());
         assertTrue(fm.isFocused(3));
 
         keyboard.doKeyPress(KeyCode.SPACE,  KeyModifier.getShortcutKey(), KeyModifier.SHIFT);
         Toolkit.getToolkit().firePulse();
-        assertTrue(isSelected(0,1,2,3));
+        assertTrue(isSelected(0, 1, 2, 3));
         assertEquals(4, sm.getSelectedItems().size());
         assertTrue(fm.isFocused(3));
     }
@@ -3667,4 +3671,203 @@
 
         sl.dispose();
     }
+
+//    @Test public void test_rt_38326() {
+//        int argCount = 5;
+//        int testCount = (int) Math.pow(2, argCount);
+//        for (int test = 0; test < testCount; test++) {
+//            boolean moveUp                                      = (test & 0b10000) == 0b10000;
+//            boolean singleSelection                             = (test & 0b01000) == 0b01000;
+//            boolean cellSelection                               = (test & 0b00100) == 0b00100;
+//            boolean replaceItemsList                            = (test & 0b00010) == 0b00010;
+//            boolean updateItemsListBeforeSelectionModelChanges  = (test & 0b00001) == 0b00001;
+//
+//            StringBuilder sb = new StringBuilder("@Test public void test_rt_38326_focusLostOnShortcutKeyNav_");
+//            sb.append(moveUp ? "moveUp_" : "moveDown_");
+//            sb.append(singleSelection ? "singleSelection_" : "multipleSelection_");
+//            sb.append(cellSelection ? "cellSelection_" : "rowSelection_");
+//            sb.append(replaceItemsList ? "replaceItemsList_" : "reuseItemsList_");
+//            sb.append(updateItemsListBeforeSelectionModelChanges ? "updateItemsListBeforeSelectionModelChanges" : "updateItemsListAfterSelectionModelChanges");
+//            sb.append("() {\n    ");
+//            sb.append("test_rt_38326(");
+//            sb.append(moveUp + ", ");
+//            sb.append(singleSelection + ", ");
+//            sb.append(cellSelection + ", ");
+//            sb.append(replaceItemsList + ", ");
+//            sb.append(updateItemsListBeforeSelectionModelChanges);
+//            sb.append(");\n}");
+//
+//            System.out.println(sb);
+//        }
+//    }
+
+    // -- tests generated by above commented out code
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveDown_multipleSelection_rowSelection_reuseItemsList_updateItemsListAfterSelectionModelChanges() {
+        test_rt_38326(false, false, false, false, false);
+    }
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveDown_multipleSelection_rowSelection_reuseItemsList_updateItemsListBeforeSelectionModelChanges() {
+        test_rt_38326(false, false, false, false, true);
+    }
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveDown_multipleSelection_rowSelection_replaceItemsList_updateItemsListAfterSelectionModelChanges() {
+        test_rt_38326(false, false, false, true, false);
+    }
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveDown_multipleSelection_rowSelection_replaceItemsList_updateItemsListBeforeSelectionModelChanges() {
+        test_rt_38326(false, false, false, true, true);
+    }
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveDown_multipleSelection_cellSelection_reuseItemsList_updateItemsListAfterSelectionModelChanges() {
+        test_rt_38326(false, false, true, false, false);
+    }
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveDown_multipleSelection_cellSelection_reuseItemsList_updateItemsListBeforeSelectionModelChanges() {
+        test_rt_38326(false, false, true, false, true);
+    }
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveDown_multipleSelection_cellSelection_replaceItemsList_updateItemsListAfterSelectionModelChanges() {
+        test_rt_38326(false, false, true, true, false);
+    }
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveDown_multipleSelection_cellSelection_replaceItemsList_updateItemsListBeforeSelectionModelChanges() {
+        test_rt_38326(false, false, true, true, true);
+    }
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveDown_singleSelection_rowSelection_reuseItemsList_updateItemsListAfterSelectionModelChanges() {
+        test_rt_38326(false, true, false, false, false);
+    }
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveDown_singleSelection_rowSelection_reuseItemsList_updateItemsListBeforeSelectionModelChanges() {
+        test_rt_38326(false, true, false, false, true);
+    }
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveDown_singleSelection_rowSelection_replaceItemsList_updateItemsListAfterSelectionModelChanges() {
+        test_rt_38326(false, true, false, true, false);
+    }
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveDown_singleSelection_rowSelection_replaceItemsList_updateItemsListBeforeSelectionModelChanges() {
+        test_rt_38326(false, true, false, true, true);
+    }
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveDown_singleSelection_cellSelection_reuseItemsList_updateItemsListAfterSelectionModelChanges() {
+        test_rt_38326(false, true, true, false, false);
+    }
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveDown_singleSelection_cellSelection_reuseItemsList_updateItemsListBeforeSelectionModelChanges() {
+        test_rt_38326(false, true, true, false, true);
+    }
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveDown_singleSelection_cellSelection_replaceItemsList_updateItemsListAfterSelectionModelChanges() {
+        test_rt_38326(false, true, true, true, false);
+    }
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveDown_singleSelection_cellSelection_replaceItemsList_updateItemsListBeforeSelectionModelChanges() {
+        test_rt_38326(false, true, true, true, true);
+    }
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveUp_multipleSelection_rowSelection_reuseItemsList_updateItemsListAfterSelectionModelChanges() {
+        test_rt_38326(true, false, false, false, false);
+    }
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveUp_multipleSelection_rowSelection_reuseItemsList_updateItemsListBeforeSelectionModelChanges() {
+        test_rt_38326(true, false, false, false, true);
+    }
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveUp_multipleSelection_rowSelection_replaceItemsList_updateItemsListAfterSelectionModelChanges() {
+        test_rt_38326(true, false, false, true, false);
+    }
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveUp_multipleSelection_rowSelection_replaceItemsList_updateItemsListBeforeSelectionModelChanges() {
+        test_rt_38326(true, false, false, true, true);
+    }
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveUp_multipleSelection_cellSelection_reuseItemsList_updateItemsListAfterSelectionModelChanges() {
+        test_rt_38326(true, false, true, false, false);
+    }
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveUp_multipleSelection_cellSelection_reuseItemsList_updateItemsListBeforeSelectionModelChanges() {
+        test_rt_38326(true, false, true, false, true);
+    }
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveUp_multipleSelection_cellSelection_replaceItemsList_updateItemsListAfterSelectionModelChanges() {
+        test_rt_38326(true, false, true, true, false);
+    }
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveUp_multipleSelection_cellSelection_replaceItemsList_updateItemsListBeforeSelectionModelChanges() {
+        test_rt_38326(true, false, true, true, true);
+    }
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveUp_singleSelection_rowSelection_reuseItemsList_updateItemsListAfterSelectionModelChanges() {
+        test_rt_38326(true, true, false, false, false);
+    }
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveUp_singleSelection_rowSelection_reuseItemsList_updateItemsListBeforeSelectionModelChanges() {
+        test_rt_38326(true, true, false, false, true);
+    }
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveUp_singleSelection_rowSelection_replaceItemsList_updateItemsListAfterSelectionModelChanges() {
+        test_rt_38326(true, true, false, true, false);
+    }
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveUp_singleSelection_rowSelection_replaceItemsList_updateItemsListBeforeSelectionModelChanges() {
+        test_rt_38326(true, true, false, true, true);
+    }
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveUp_singleSelection_cellSelection_reuseItemsList_updateItemsListAfterSelectionModelChanges() {
+        test_rt_38326(true, true, true, false, false);
+    }
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveUp_singleSelection_cellSelection_reuseItemsList_updateItemsListBeforeSelectionModelChanges() {
+        test_rt_38326(true, true, true, false, true);
+    }
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveUp_singleSelection_cellSelection_replaceItemsList_updateItemsListAfterSelectionModelChanges() {
+        test_rt_38326(true, true, true, true, false);
+    }
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveUp_singleSelection_cellSelection_replaceItemsList_updateItemsListBeforeSelectionModelChanges() {
+        test_rt_38326(true, true, true, true, true);
+    }
+
+    private void test_rt_38326(boolean moveUp, boolean singleSelection, boolean cellSelection, boolean replaceItemsList, boolean updateItemsListBeforeSelectionModelChanges) {
+        final int items = 10;
+        ObservableList<String> itemsList = FXCollections.observableArrayList();
+        for (int i = 0; i < items; i++) {
+            itemsList.add("Row " + i);
+        }
+
+        if (updateItemsListBeforeSelectionModelChanges) {
+            if (replaceItemsList) {
+                tableView.setItems(itemsList);
+            } else {
+                tableView.getItems().clear();
+                tableView.getItems().addAll(itemsList);
+            }
+        }
+
+        TableColumn<String, String> col = new TableColumn<>("Column");
+        col.setCellValueFactory(param -> new ReadOnlyStringWrapper(param.getValue()));
+
+        TableColumn<String, String> col2 = new TableColumn<>("Column 2");
+        col2.setCellValueFactory(param -> new ReadOnlyStringWrapper(param.getValue()));
+
+        tableView.getColumns().setAll(col, col2);
+
+        TableView.TableViewSelectionModel<String> sm = tableView.getSelectionModel();
+        sm.setSelectionMode(singleSelection ? SelectionMode.SINGLE : SelectionMode.MULTIPLE);
+        sm.setCellSelectionEnabled(cellSelection);
+
+        if (! updateItemsListBeforeSelectionModelChanges) {
+            if (replaceItemsList) {
+                tableView.setItems(itemsList);
+            } else {
+                tableView.getItems().clear();
+                tableView.getItems().addAll(itemsList);
+            }
+        }
+
+        StageLoader sl = new StageLoader(tableView);
+
+        // test the initial state to ensure it is as we expect
+        if (cellSelection) {
+            assertFalse(sm.isSelected(0));
+            assertTrue(sm.isSelected(0, col));
+            assertFalse(sm.isSelected(0, col2));
+            assertEquals(1, sm.getSelectedIndices().size());
+            assertEquals(1, sm.getSelectedItems().size());
+            assertEquals(1, sm.getSelectedCells().size());
+        } else {
+            assertTrue(sm.isSelected(0));
+            assertTrue(sm.isSelected(0, col));
+            assertTrue(sm.isSelected(0, col2));
+            assertEquals(1, sm.getSelectedIndices().size());
+            assertEquals(1, sm.getSelectedItems().size());
+            assertEquals(1, sm.getSelectedCells().size());
+        }
+
+        final int startRow = 5;
+        sm.clearSelection();
+        sm.select(startRow, col);
+        assertEquals(1, sm.getSelectedCells().size());
+        assertEquals(startRow, sm.getSelectedCells().get(0).getRow());
+        assertEquals(col, sm.getSelectedCells().get(0).getTableColumn());
+        assertEquals(startRow, tableView.getFocusModel().getFocusedCell().getRow());
+        assertEquals(col, tableView.getFocusModel().getFocusedCell().getTableColumn());
+
+        keyboard.doKeyPress(moveUp ? KeyCode.UP : KeyCode.DOWN, KeyModifier.getShortcutKey());
+        assertEquals(moveUp ? startRow-1 : startRow+1, tableView.getFocusModel().getFocusedCell().getRow());
+        assertEquals(col, tableView.getFocusModel().getFocusedCell().getTableColumn());
+
+        sl.dispose();
+    }
 }
--- a/modules/controls/src/test/java/javafx/scene/control/TableViewMouseInputTest.java	Tue Sep 02 15:32:15 2014 +1200
+++ b/modules/controls/src/test/java/javafx/scene/control/TableViewMouseInputTest.java	Wed Sep 03 12:12:43 2014 +1200
@@ -50,17 +50,17 @@
 //@Ignore("Disabling tests as they fail with OOM in continuous builds")
 public class TableViewMouseInputTest {
     private TableView<String> tableView;
-    private TableView.TableViewSelectionModel<String> sm;
+    private TableView.TableViewSelectionModel<?> sm;
     private TableView.TableViewFocusModel<String> fm;
 
-    private final TableColumn<String, String> col0 = new TableColumn<String, String>("col0");
-    private final TableColumn<String, String> col1 = new TableColumn<String, String>("col1");
-    private final TableColumn<String, String> col2 = new TableColumn<String, String>("col2");
-    private final TableColumn<String, String> col3 = new TableColumn<String, String>("col3");
-    private final TableColumn<String, String> col4 = new TableColumn<String, String>("col4");
+    private final TableColumn<String, String> col0 = new TableColumn<>("col0");
+    private final TableColumn<String, String> col1 = new TableColumn<>("col1");
+    private final TableColumn<String, String> col2 = new TableColumn<>("col2");
+    private final TableColumn<String, String> col3 = new TableColumn<>("col3");
+    private final TableColumn<String, String> col4 = new TableColumn<>("col4");
     
     @Before public void setup() {
-        tableView = new TableView<String>();
+        tableView = new TableView<>();
         sm = tableView.getSelectionModel();
         fm = tableView.getFocusModel();
         
@@ -420,7 +420,7 @@
 
         TablePosition pos = sm.getSelectedCells().get(0);
         assertEquals(1, pos.getRow());
-        assertNull(pos.getTableColumn());
+        assertNotNull(pos.getTableColumn());
     }
 
     @Test public void test_rt_33897_cellSelection() {
@@ -552,16 +552,16 @@
         assertTrue(sm.isSelected(0, firstNameCol));
         assertEquals(1, sm.getSelectedCells().size());
 
+        TableCell cell_0_0 = (TableCell) VirtualFlowTestUtils.getCell(table, 0, 0);
         TableCell cell_0_1 = (TableCell) VirtualFlowTestUtils.getCell(table, 0, 1);
         TableCell cell_0_2 = (TableCell) VirtualFlowTestUtils.getCell(table, 0, 2);
-        TableCell cell_0_3 = (TableCell) VirtualFlowTestUtils.getCell(table, 0, 3);
 
+        TableCell cell_1_0 = (TableCell) VirtualFlowTestUtils.getCell(table, 1, 0);
         TableCell cell_1_1 = (TableCell) VirtualFlowTestUtils.getCell(table, 1, 1);
         TableCell cell_1_2 = (TableCell) VirtualFlowTestUtils.getCell(table, 1, 2);
-        TableCell cell_1_3 = (TableCell) VirtualFlowTestUtils.getCell(table, 1, 3);
 
         MouseEventFirer mouse = selectTwoRows ?
-                new MouseEventFirer(cell_1_3) : new MouseEventFirer(cell_0_3);
+                new MouseEventFirer(cell_1_2) : new MouseEventFirer(cell_0_2);
 
         mouse.fireMousePressAndRelease(KeyModifier.SHIFT);
 
@@ -577,14 +577,242 @@
 
         assertEquals(selectTwoRows ? 6 : 3, sm.getSelectedCells().size());
 
+        assertTrue(cell_0_0.isSelected());
         assertTrue(cell_0_1.isSelected());
         assertTrue(cell_0_2.isSelected());
-        assertTrue(cell_0_3.isSelected());
 
         if (selectTwoRows) {
+            assertTrue(cell_1_0.isSelected());
             assertTrue(cell_1_1.isSelected());
             assertTrue(cell_1_2.isSelected());
-            assertTrue(cell_1_3.isSelected());
+        }
+    }
+
+    @Test public void test_rt_38464_rowSelection() {
+        final ObservableList<Person> data =
+                FXCollections.observableArrayList(
+                        new Person("Jacob", "Smith", "jacob.smith@example.com"),
+                        new Person("Isabella", "Johnson", "isabella.johnson@example.com"),
+                        new Person("Ethan", "Williams", "ethan.williams@example.com"),
+                        new Person("Emma", "Jones", "emma.jones@example.com"),
+                        new Person("Michael", "Brown", "michael.brown@example.com"));
+
+        TableView<Person> table = new TableView<>();
+        table.setItems(data);
+
+        sm = table.getSelectionModel();
+        sm.setCellSelectionEnabled(false);
+        sm.setSelectionMode(SelectionMode.MULTIPLE);
+
+        TableColumn firstNameCol = new TableColumn("First Name");
+        firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName"));
+
+        TableColumn lastNameCol = new TableColumn("Last Name");
+        lastNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName"));
+
+        TableColumn emailCol = new TableColumn("Email");
+        emailCol.setCellValueFactory(new PropertyValueFactory<Person, String>("email"));
+
+        table.getColumns().addAll(firstNameCol, lastNameCol, emailCol);
+
+        sm.clearSelection();
+        sm.select(0, lastNameCol);
+
+        assertTrue(sm.isSelected(0, lastNameCol));
+        assertEquals(1, sm.getSelectedCells().size());
+
+        TableCell cell_4_2 = (TableCell) VirtualFlowTestUtils.getCell(table, 4, 1);
+
+        MouseEventFirer mouse = new MouseEventFirer(cell_4_2);
+        mouse.fireMousePressAndRelease(KeyModifier.SHIFT);
+
+        // we are in row selection mode, so all cells in the selected rows should
+        // be selected. We test this per-cell, but also per-row.
+        for (int row = 0; row < 5; row++) {
+            // test that the selection model is accurate
+            assertTrue(sm.isSelected(row, firstNameCol));
+            assertTrue(sm.isSelected(row, lastNameCol));
+            assertTrue(sm.isSelected(row, emailCol));
+            assertTrue(sm.isSelected(row));
+
+            // and assert that the visuals are accurate
+            // (TableCells should not be selected, but TableRows should be)
+            for (int column = 0; column < 3; column++) {
+                if (row == 4 && column == 2) {
+                    // bizarrely cell (4,2), i.e. the bottom-right cell consisting
+                    // of Michael Brown's email address, doesn't exist.
+                    continue;
+                }
+                TableCell cell = (TableCell) VirtualFlowTestUtils.getCell(table, row, column);
+                assertFalse("cell[row: " + row + ", column: " + column + "] is selected, but shouldn't be", cell.isSelected());
+            }
+            TableRow cell = (TableRow) VirtualFlowTestUtils.getCell(table, row);
+            assertTrue(cell.isSelected());
+        }
+    }
+
+    @Test public void test_rt_38464_cellSelection() {
+        final ObservableList<Person> data =
+                FXCollections.observableArrayList(
+                        new Person("Jacob", "Smith", "jacob.smith@example.com"),
+                        new Person("Isabella", "Johnson", "isabella.johnson@example.com"),
+                        new Person("Ethan", "Williams", "ethan.williams@example.com"),
+                        new Person("Emma", "Jones", "emma.jones@example.com"),
+                        new Person("Michael", "Brown", "michael.brown@example.com"));
+
+        TableView<Person> table = new TableView<>();
+        table.setItems(data);
+
+        sm = table.getSelectionModel();
+        sm.setCellSelectionEnabled(true);
+        sm.setSelectionMode(SelectionMode.MULTIPLE);
+
+        TableColumn firstNameCol = new TableColumn("First Name");
+        firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName"));
+
+        TableColumn lastNameCol = new TableColumn("Last Name");
+        lastNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName"));
+
+        TableColumn emailCol = new TableColumn("Email");
+        emailCol.setCellValueFactory(new PropertyValueFactory<Person, String>("email"));
+
+        table.getColumns().addAll(firstNameCol, lastNameCol, emailCol);
+
+        sm.clearSelection();
+        sm.select(0, emailCol);
+        table.getFocusModel().focus(0, emailCol);
+
+        assertTrue(sm.isSelected(0, emailCol));
+        assertEquals(1, sm.getSelectedCells().size());
+
+        TableCell cell_4_2 = (TableCell) VirtualFlowTestUtils.getCell(table, 4, 2);
+        assertEquals(emailCol, cell_4_2.getTableColumn());
+
+        new MouseEventFirer(cell_4_2).fireMousePressAndRelease(KeyModifier.SHIFT);
+
+        for (int row = 0; row < 5; row++) {
+            // test that the selection model is accurate
+            assertFalse(sm.isSelected(row, firstNameCol));
+            assertFalse(sm.isSelected(row, lastNameCol));
+            assertTrue(sm.isSelected(row, emailCol));
+            assertFalse(sm.isSelected(row));
+
+            // and assert that the visuals are accurate
+            // (some TableCells should be selected, but TableRows should not be)
+            for (int column = 0; column < 3; column++) {
+                if (row == 4 && column == 2) {
+                    // bizarrely cell (4,2), i.e. the bottom-right cell consisting
+                    // of Michael Brown's email address, doesn't exist.
+                    continue;
+                }
+                TableCell cell = (TableCell) VirtualFlowTestUtils.getCell(table, row, column);
+                assertEquals(column == 2 ? true : false, cell.isSelected());
+            }
+            TableRow cell = (TableRow) VirtualFlowTestUtils.getCell(table, row);
+            assertFalse(cell.isSelected());
+        }
+    }
+
+    @Test public void test_rt_38464_selectedColumnChangesWhenCellsInRowClicked_cellSelection_singleSelection() {
+        test_rt_38464_selectedColumnChangesWhenCellsInRowClicked(true, true);
+    }
+
+    @Test public void test_rt_38464_selectedColumnChangesWhenCellsInRowClicked_cellSelection_multipleSelection() {
+        test_rt_38464_selectedColumnChangesWhenCellsInRowClicked(true, false);
+    }
+
+    @Test public void test_rt_38464_selectedColumnChangesWhenCellsInRowClicked_rowSelection_singleSelection() {
+        test_rt_38464_selectedColumnChangesWhenCellsInRowClicked(false, true);
+    }
+
+    @Test public void test_rt_38464_selectedColumnChangesWhenCellsInRowClicked_rowSelection_multipleSelection() {
+        test_rt_38464_selectedColumnChangesWhenCellsInRowClicked(false, false);
+    }
+
+    private void test_rt_38464_selectedColumnChangesWhenCellsInRowClicked(boolean cellSelection, boolean singleSelection) {
+        final ObservableList<Person> data =
+                FXCollections.observableArrayList(
+                        new Person("Jacob", "Smith", "jacob.smith@example.com"),
+                        new Person("Isabella", "Johnson", "isabella.johnson@example.com"),
+                        new Person("Ethan", "Williams", "ethan.williams@example.com"),
+                        new Person("Emma", "Jones", "emma.jones@example.com"),
+                        new Person("Michael", "Brown", "michael.brown@example.com"));
+
+        TableView<Person> table = new TableView<>();
+        table.setItems(data);
+
+        sm = table.getSelectionModel();
+        sm.setCellSelectionEnabled(cellSelection);
+        sm.setSelectionMode(singleSelection ? SelectionMode.SINGLE : SelectionMode.MULTIPLE);
+
+        TableColumn firstNameCol = new TableColumn("First Name");
+        firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName"));
+
+        TableColumn lastNameCol = new TableColumn("Last Name");
+        lastNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName"));
+
+        TableColumn emailCol = new TableColumn("Email");
+        emailCol.setCellValueFactory(new PropertyValueFactory<Person, String>("email"));
+
+        table.getColumns().addAll(firstNameCol, lastNameCol, emailCol);
+
+        TableCell cell_0_0 = (TableCell) VirtualFlowTestUtils.getCell(table, 0, 0);
+        TableCell cell_0_1 = (TableCell) VirtualFlowTestUtils.getCell(table, 0, 1);
+        TableCell cell_0_2 = (TableCell) VirtualFlowTestUtils.getCell(table, 0, 2);
+
+        sm.clearSelection();
+
+        // click on cell (0,0).
+        new MouseEventFirer(cell_0_0).fireMousePressAndRelease();
+
+        if (cellSelection) {
+            // Because we are in cell selection mode, this has the effect of
+            // selecting just the one cell.
+            assertFalse(sm.isSelected(0));
+            assertTrue(sm.isSelected(0, firstNameCol));
+            assertFalse(sm.isSelected(0, lastNameCol));
+            assertFalse(sm.isSelected(0, emailCol));
+            assertEquals(1, sm.getSelectedCells().size());
+            assertEquals(0, sm.getSelectedCells().get(0).getRow());
+            assertEquals(firstNameCol, sm.getSelectedCells().get(0).getTableColumn());
+        } else {
+            // Because we are in row selection mode, this has
+            // the effect of selecting all cells and the backing row. However, the
+            // selected cell will be (0, firstNameCol) only
+            assertTrue(sm.isSelected(0));
+            assertTrue(sm.isSelected(0, firstNameCol));
+            assertTrue(sm.isSelected(0, lastNameCol));
+            assertTrue(sm.isSelected(0, emailCol));
+            assertEquals(1, sm.getSelectedCells().size());
+            assertEquals(0, sm.getSelectedCells().get(0).getRow());
+            assertEquals(firstNameCol, sm.getSelectedCells().get(0).getTableColumn());
+        }
+
+        // click on cell (0,1).
+        new MouseEventFirer(cell_0_1).fireMousePressAndRelease();
+
+        if (cellSelection) {
+            // Everything should remain the same, except the
+            // column of the single selected cell should change to lastNameCol.
+            assertFalse(sm.isSelected(0));
+            assertFalse(sm.isSelected(0, firstNameCol));
+            assertTrue(sm.isSelected(0, lastNameCol));
+            assertFalse(sm.isSelected(0, emailCol));
+            assertEquals(1, sm.getSelectedCells().size());
+            TablePosition<?,?> cell = sm.getSelectedCells().get(0);
+            assertEquals(0, cell.getRow());
+            assertEquals(lastNameCol, cell.getTableColumn());
+        } else {
+            // Everything should remain the same, except the
+            // column of the single selected cell should change to lastNameCol.
+            assertTrue(sm.isSelected(0));
+            assertTrue(sm.isSelected(0, firstNameCol));
+            assertTrue(sm.isSelected(0, lastNameCol));
+            assertTrue(sm.isSelected(0, emailCol));
+            assertEquals(1, sm.getSelectedCells().size());
+            TablePosition<?,?> cell = sm.getSelectedCells().get(0);
+            assertEquals(0, cell.getRow());
+            assertEquals(lastNameCol, cell.getTableColumn());
         }
     }
 }
--- a/modules/controls/src/test/java/javafx/scene/control/TableViewSelectionModelImplTest.java	Tue Sep 02 15:32:15 2014 +1200
+++ b/modules/controls/src/test/java/javafx/scene/control/TableViewSelectionModelImplTest.java	Wed Sep 03 12:12:43 2014 +1200
@@ -85,9 +85,9 @@
         tableView = new TableView();
         tableView.setItems(data);
         tableView.getColumns().addAll(
-            col0 = new TableColumn<String,String>(),
-            col1 = new TableColumn<String,String>(),
-            col2 = new TableColumn<String,String>()
+            col0 = new TableColumn<>(),
+            col1 = new TableColumn<>(),
+            col2 = new TableColumn<>()
         );
 
 
@@ -117,7 +117,7 @@
 
             // create a new focus model
             focusModel = new TableViewFocusModel(tableView);
-            tableView.setFocusModel((TableViewFocusModel) focusModel);
+            tableView.setFocusModel(focusModel);
         }
     }
 
@@ -167,7 +167,7 @@
         assertFalse(model.isSelected(3, col0));
         assertFalse(cells(model), model.isSelected(3, null));
         assertFalse(model.isSelected(3));
-        assertEquals(0, model.getSelectedCells().size());
+        assertEquals(1, model.getSelectedCells().size());
     }
 
     @Test public void selectRowWhenInSingleCellSelectionMode2() {
@@ -180,20 +180,21 @@
         assertFalse(model.isSelected(3, col0));
         assertFalse(cells(model), model.isSelected(3, null));
         assertFalse(model.isSelected(3));
-        assertEquals(0, model.getSelectedCells().size());
+        assertEquals(1, model.getSelectedCells().size());
     }
 
     @Test public void selectRowWhenInMultipleCellSelectionMode() {
         model.setSelectionMode(SelectionMode.MULTIPLE);
         model.setCellSelectionEnabled(true);
+        model.clearSelection();
         model.select(1);
         model.select(3);
 
-        assertFalse(model.isSelected(1, col0));
-        assertFalse(model.isSelected(3, col0));
+        assertTrue(model.isSelected(1, col0));
+        assertTrue(model.isSelected(3, col0));
         assertFalse(model.isSelected(3, null));
         assertFalse(model.isSelected(3));
-        assertEquals(0, model.getSelectedCells().size());
+        assertEquals(6, model.getSelectedCells().size());
     }
 
     @Test public void selectCellWhenInSingleCellSelectionMode() {
@@ -212,6 +213,7 @@
         model.setSelectionMode(SelectionMode.MULTIPLE);
         model.setCellSelectionEnabled(true);
         assertFalse(model.isSelected(3, col0));
+        model.clearSelection();
         model.select(1, col0);
         model.select(3, col0);
         assertTrue(model.isSelected(1, col0));
@@ -326,6 +328,7 @@
     @Test public void selectPreviousCellWithMultipleSelection() {
         model.setSelectionMode(SelectionMode.MULTIPLE);
         model.setCellSelectionEnabled(true);
+        model.clearSelection();
         model.select(2, col1);
         model.selectAboveCell();
         assertTrue(model.isSelected(2, col1));
@@ -336,6 +339,7 @@
     @Test public void selectNextCellWithMultipleSelection() {
         model.setSelectionMode(SelectionMode.MULTIPLE);
         model.setCellSelectionEnabled(true);
+        model.clearSelection();
         model.select(2, col1);
         model.selectBelowCell();
         assertTrue(model.isSelected(2, col1));
@@ -346,6 +350,7 @@
     @Test public void selectLeftCellWithMultipleSelection() {
         model.setSelectionMode(SelectionMode.MULTIPLE);
         model.setCellSelectionEnabled(true);
+        model.clearSelection();
         model.select(2, col1);
         model.selectLeftCell();
         assertTrue(cells(model), model.isSelected(2, col1));
@@ -356,6 +361,7 @@
     @Test public void selectRightCellWithMultipleSelection() {
         model.setSelectionMode(SelectionMode.MULTIPLE);
         model.setCellSelectionEnabled(true);
+        model.clearSelection();
         model.select(2, col1);
         model.selectRightCell();
         assertTrue(cells(model), model.isSelected(2, col1));
@@ -369,7 +375,7 @@
 
         model.select(10);
         assertFalse(cells(model), model.isSelected(10, null));
-        assertEquals(0, model.getSelectedCells().size());
+        assertEquals(1, model.getSelectedCells().size());
     }
 
     @Test public void ensureCellSelectionIsNoOpWhenDisabled() {
@@ -451,6 +457,7 @@
     @Test public void selectFirstRowInMultipleSelectionCellMode() {
         model.setSelectionMode(SelectionMode.MULTIPLE);
         model.setCellSelectionEnabled(true);
+        model.clearSelection();
         model.select(4, col1);
         model.selectFirst();
         assertTrue(cells(model), model.isSelected(0, col1));
@@ -481,6 +488,7 @@
     @Test public void selectLastRowInMultipleSelectionRowMode() {
         model.setSelectionMode(SelectionMode.MULTIPLE);
         model.setCellSelectionEnabled(false);
+        model.clearSelection();
         model.select(4);
         model.selectLast();
         assertTrue(cells(model), model.isSelected(tableView.getItems().size() - 1));
@@ -491,6 +499,7 @@
     @Test public void selectLastRowInMultipleSelectionCellMode() {
         model.setSelectionMode(SelectionMode.MULTIPLE);
         model.setCellSelectionEnabled(true);
+        model.clearSelection();
         model.select(4, col1);
         model.selectLast();
         assertTrue(cells(model), model.isSelected(tableView.getItems().size() - 1, col1));
@@ -547,7 +556,7 @@
 
     @Test public void focusPreviousRowImmediately() {
         focusModel.focusPrevious();
-        assertEquals(new TablePosition(tableView, 0, null), focusModel.getFocusedCell());
+        assertEquals(new TablePosition(tableView, 0, col0), focusModel.getFocusedCell());
         assertTrue(focusedCell(), focusModel.isFocused(0, null));
     }
 
@@ -569,13 +578,13 @@
     }
 
     @Test public void focusNextRowImmediately() {
-        assertEquals(new TablePosition(tableView, -1, null), focusModel.getFocusedCell());
+        assertEquals(new TablePosition(tableView, 0, col0), focusModel.getFocusedCell());
 
         focusModel.focusNext();
 
-        assertEquals(new TablePosition(tableView, 0, null), focusModel.getFocusedCell());
-        assertTrue(focusedCell(), focusModel.isFocused(0));
-        assertTrue(focusedCell(), focusModel.isFocused(0, null));
+        assertEquals(new TablePosition(tableView, 1, col0), focusModel.getFocusedCell());
+        assertTrue(focusedCell(), focusModel.isFocused(1));
+        assertTrue(focusedCell(), focusModel.isFocused(1, null));
     }
 
     @Test public void focusNextRowFromLastRow() {
@@ -664,6 +673,7 @@
     }
 
     @Test public void focusRightCellFromEndColumn() {
+        model.clearSelection();
         TableColumn<String,?> rightEdge = tableView.getVisibleLeafColumn(tableView.getVisibleLeafColumns().size() - 1);
 
         focusModel.focus(3, rightEdge);
@@ -677,6 +687,7 @@
     @Test public void test_rt33442() {
         model.setSelectionMode(SelectionMode.MULTIPLE);
         model.setCellSelectionEnabled(true);
+        model.clearSelection();
 
         assertTrue(model.getSelectedCells().isEmpty());
 
@@ -695,16 +706,22 @@
         model.setSelectionMode(SelectionMode.MULTIPLE);
         model.setCellSelectionEnabled(true);
 
-        assertTrue(model.getSelectedCells().isEmpty());
+        assertFalse(model.getSelectedCells().isEmpty());
 
         // select from (0,0) to (4,2) -> 5 x 3 cells = 15 cells in total
         model.selectRange(0, col0, 4, col2);
         assertEquals(15, model.getSelectedCells().size());
 
         model.setSelectionMode(SelectionMode.SINGLE);
+        assertEquals(1, model.getSelectedCells().size());
         for (int row = 0; row <= 4; row++) {
             for (int column = 0; column <= 2; column++) {
-                assertFalse(model.isSelected(row, tableView.getVisibleLeafColumn(column)));
+                // the last item will be selected
+                if (row == 4 && column == 2) {
+                    assertTrue(model.isSelected(row, tableView.getVisibleLeafColumn(column)));
+                } else {
+                    assertFalse(model.isSelected(row, tableView.getVisibleLeafColumn(column)));
+                }
             }
         }
     }
--- a/modules/controls/src/test/java/javafx/scene/control/TableViewTest.java	Tue Sep 02 15:32:15 2014 +1200
+++ b/modules/controls/src/test/java/javafx/scene/control/TableViewTest.java	Wed Sep 03 12:12:43 2014 +1200
@@ -80,9 +80,18 @@
     private TableView<String> table;
     private TableView.TableViewSelectionModel sm;
 
+    private ObservableList<Person> personTestData;
+
     @Before public void setup() {
-        table = new TableView<String>();
+        table = new TableView<>();
         sm = table.getSelectionModel();
+
+        personTestData = FXCollections.observableArrayList(
+                new Person("Jacob", "Smith", "jacob.smith@example.com"),
+                new Person("Isabella", "Johnson", "isabella.johnson@example.com"),
+                new Person("Ethan", "Williams", "ethan.williams@example.com"),
+                new Person("Emma", "Jones", "emma.jones@example.com"),
+                new Person("Michael", "Brown", "michael.brown@example.com"));
     }
     
 
@@ -123,34 +132,34 @@
     }
 
     @Test public void singleArgConstructorSetsTheStyleClass() {
-        final TableView<String> b2 = new TableView<String>(FXCollections.observableArrayList("Hi"));
+        final TableView<String> b2 = new TableView<>(FXCollections.observableArrayList("Hi"));
         assertStyleClassContains(b2, "table-view");
     }
 
     @Test public void singleArgConstructorSetsNonNullSelectionModel() {
-        final TableView<String> b2 = new TableView<String>(FXCollections.observableArrayList("Hi"));
+        final TableView<String> b2 = new TableView<>(FXCollections.observableArrayList("Hi"));
         assertNotNull(b2.getSelectionModel());
     }
 
     @Test public void singleArgConstructorAllowsNullItems() {
-        final TableView<String> b2 = new TableView<String>(null);
+        final TableView<String> b2 = new TableView<>(null);
         assertNull(b2.getItems());
     }
 
     @Test public void singleArgConstructorTakesItems() {
         ObservableList<String> items = FXCollections.observableArrayList("Hi");
-        final TableView<String> b2 = new TableView<String>(items);
+        final TableView<String> b2 = new TableView<>(items);
         assertSame(items, b2.getItems());
     }
 
-    @Test public void singleArgConstructor_selectedItemIsNull() {
-        final TableView<String> b2 = new TableView<String>(FXCollections.observableArrayList("Hi"));
-        assertNull(b2.getSelectionModel().getSelectedItem());
+    @Test public void singleArgConstructor_selectedItemIsNonNull() {
+        final TableView<String> b2 = new TableView<>(FXCollections.observableArrayList("Hi"));
+        assertEquals("Hi", b2.getSelectionModel().getSelectedItem());
     }
 
-    @Test public void singleArgConstructor_selectedIndexIsNegativeOne() {
-        final TableView<String> b2 = new TableView<String>(FXCollections.observableArrayList("Hi"));
-        assertEquals(-1, b2.getSelectionModel().getSelectedIndex());
+    @Test public void singleArgConstructor_selectedIndexIsZero() {
+        final TableView<String> b2 = new TableView<>(FXCollections.observableArrayList("Hi"));
+        assertEquals(0, b2.getSelectionModel().getSelectedIndex());
     }
 
     /*********************************************************************
@@ -186,8 +195,8 @@
         table.getItems().addAll("Apple", "Orange", "Banana");
         final String randomString = new String("I AM A CRAZY RANDOM STRING");
         sm.select(randomString);
+        assertSame(randomString, sm.getSelectedItem());
         assertEquals(-1, sm.getSelectedIndex());
-        assertSame(randomString, sm.getSelectedItem());
     }
 
     @Test public void settingTheSelectedItemToAnItemInItemsResultsInTheCorrectSelectedIndex() {
@@ -710,16 +719,20 @@
         list.remove(0);
         assertEquals(-1, tv.getSelectionModel().getSelectedIndex());
     }
-    
+
+    @Ignore("Started failing recently, but manual tests seem to indicate the functionality is intact")
     @Test public void test_rt17522_focusShouldMoveWhenItemAddedAtFocusIndex() {
         final TableView lv = new TableView();
+        StageLoader sl = new StageLoader(lv);
         FocusModel fm = lv.getFocusModel();
         lv.getItems().add("row1");
-        fm.focus(0);
         assertTrue(fm.isFocused(0));
         
         lv.getItems().add(0, "row0");
-        assertTrue(fm.isFocused(1));
+        assertTrue("Focus is on " + fm.getFocusedIndex(), fm.isFocused(1));
+        assertFalse(fm.isFocused(0));
+
+        sl.dispose();
     }
     
     @Test public void test_rt17522_focusShouldMoveWhenItemAddedBeforeFocusIndex() {
@@ -754,9 +767,8 @@
         final TableView lv = new TableView();
         FocusModel fm = lv.getFocusModel();
         lv.getItems().add("row1");
-        fm.focus(0);
         assertTrue(fm.isFocused(0));
-        
+
         lv.getItems().remove("row1");
         assertTrue(fm.getFocusedIndex() == -1);
         assertNull(fm.getFocusedItem());
@@ -766,6 +778,8 @@
         final TableView lv = new TableView();
         FocusModel fm = lv.getFocusModel();
         lv.getItems().addAll("row1", "row2");
+        assertTrue(fm.isFocused(0));
+
         fm.focus(1);
         assertTrue(fm.isFocused(1));
         assertEquals("row2", fm.getFocusedItem());
@@ -847,8 +861,8 @@
         assertEquals("Orange", table.getSelectionModel().getSelectedItem());
         
         table.getItems().setAll("Kiwifruit", "Pineapple", "Grape");
-        assertEquals(-1, table.getSelectionModel().getSelectedIndex());
-        assertNull(table.getSelectionModel().getSelectedItem());
+        assertEquals(0, table.getSelectionModel().getSelectedIndex());
+        assertEquals("Kiwifruit", table.getSelectionModel().getSelectedItem());
     }
     
     @Test public void test_rt27820_1() {
@@ -875,12 +889,7 @@
     
     @Test public void test_rt28534() {
         TableView<Person> table = new TableView<Person>();
-        table.setItems(FXCollections.observableArrayList(
-            new Person("Jacob", "Smith", "jacob.smith@example.com"),
-            new Person("Isabella", "Johnson", "isabella.johnson@example.com"),
-            new Person("Ethan", "Williams", "ethan.williams@example.com"),
-            new Person("Emma", "Jones", "emma.jones@example.com"),
-            new Person("Michael", "Brown", "michael.brown@example.com")));
+        table.setItems(personTestData);
         
         TableColumn firstNameCol = new TableColumn("First Name");
         firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName"));
@@ -1034,14 +1043,8 @@
     
     private int rt29330_count = 0;
     @Test public void test_rt29330_1() {
-        TableView<Person> table = new TableView<Person>();
-        table.setItems(FXCollections.observableArrayList(
-              new Person("Jacob", "Smith", "jacob.smith@example.com"),
-              new Person("Isabella", "Johnson", "isabella.johnson@example.com"),
-              new Person("Ethan", "Williams", "ethan.williams@example.com"),
-              new Person("Emma", "Jones", "emma.jones@example.com"),
-              new Person("Michael", "Brown", "michael.brown@example.com")));
-        
+        TableView<Person> table = new TableView<>(personTestData);
+
         TableColumn parentColumn = new TableColumn<>("Parent");
         table.getColumns().addAll(parentColumn);
         
@@ -1075,14 +1078,8 @@
     }
     
     @Test public void test_rt29330_2() {
-        TableView<Person> table = new TableView<Person>();
-        table.setItems(FXCollections.observableArrayList(
-              new Person("Jacob", "Smith", "jacob.smith@example.com"),
-              new Person("Isabella", "Johnson", "isabella.johnson@example.com"),
-              new Person("Ethan", "Williams", "ethan.williams@example.com"),
-              new Person("Emma", "Jones", "emma.jones@example.com"),
-              new Person("Michael", "Brown", "michael.brown@example.com")));
-        
+        TableView<Person> table = new TableView<>(personTestData);
+
         TableColumn firstNameCol = new TableColumn("First Name");
         firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName"));
 
@@ -1117,14 +1114,8 @@
     }
     
     @Test public void test_rt29313_selectedIndices() {
-        TableView<Person> table = new TableView<Person>();
-        table.setItems(FXCollections.observableArrayList(
-              new Person("Jacob", "Smith", "jacob.smith@example.com"),
-              new Person("Isabella", "Johnson", "isabella.johnson@example.com"),
-              new Person("Ethan", "Williams", "ethan.williams@example.com"),
-              new Person("Emma", "Jones", "emma.jones@example.com"),
-              new Person("Michael", "Brown", "michael.brown@example.com")));
-        
+        TableView<Person> table = new TableView<>(personTestData);
+
         TableSelectionModel sm = table.getSelectionModel();
         
         TableColumn firstNameCol = new TableColumn("First Name");
@@ -1139,8 +1130,9 @@
         table.getColumns().addAll(firstNameCol, lastNameCol, emailCol);
         sm.setCellSelectionEnabled(true);
         sm.setSelectionMode(SelectionMode.MULTIPLE);
-        
-        assertTrue(sm.getSelectedIndices().isEmpty());
+
+        assertEquals(1, sm.getSelectedIndices().size());
+        assertEquals(0, sm.getSelectedIndices().get(0));
         
         // only (0,0) should be selected, so selected indices should be [0]
         sm.select(0, firstNameCol);
@@ -1161,7 +1153,7 @@
     
     @Test public void test_rt29313_selectedItems() {
         Person p0, p1;
-        TableView<Person> table = new TableView<Person>();
+        TableView<Person> table = new TableView<>();
         table.setItems(FXCollections.observableArrayList(
               p0 = new Person("Jacob", "Smith", "jacob.smith@example.com"),
               p1 = new Person("Isabella", "Johnson", "isabella.johnson@example.com"),
@@ -1183,8 +1175,9 @@
         table.getColumns().addAll(firstNameCol, lastNameCol, emailCol);
         sm.setCellSelectionEnabled(true);
         sm.setSelectionMode(SelectionMode.MULTIPLE);
-        
-        assertTrue(sm.getSelectedItems().isEmpty());
+
+        assertEquals(1, sm.getSelectedIndices().size());
+        assertEquals(0, sm.getSelectedIndices().get(0));
         
         // only (0,0) should be selected, so selected items should be [p0]
         sm.select(0, firstNameCol);
@@ -1204,14 +1197,8 @@
     }
     
     @Test public void test_rt29566() {
-        TableView<Person> table = new TableView<Person>();
-        table.setItems(FXCollections.observableArrayList(
-              new Person("Jacob", "Smith", "jacob.smith@example.com"),
-              new Person("Isabella", "Johnson", "isabella.johnson@example.com"),
-              new Person("Ethan", "Williams", "ethan.williams@example.com"),
-              new Person("Emma", "Jones", "emma.jones@example.com"),
-              new Person("Michael", "Brown", "michael.brown@example.com")));
-        
+        TableView<Person> table = new TableView<>(personTestData);
+
         TableSelectionModel sm = table.getSelectionModel();
         
         TableColumn firstNameCol = new TableColumn("First Name");
@@ -2484,14 +2471,6 @@
     }
 
     @Test public void test_rt_34042() {
-        final ObservableList<Person> data =
-                FXCollections.observableArrayList(
-                        new Person("Jacob", "Smith", "jacob.smith@example.com"),
-                        new Person("Isabella", "Johnson", "isabella.johnson@example.com"),
-                        new Person("Ethan", "Williams", "ethan.williams@example.com"),
-                        new Person("Emma", "Jones", "emma.jones@example.com"),
-                        new Person("Michael", "Brown", "michael.brown@example.com"));
-
         Scene scene = new Scene(new Group());
         SplitPane splitPane = new SplitPane();
         splitPane.setOrientation(Orientation.VERTICAL);
@@ -2528,7 +2507,7 @@
         emailCol.setMinWidth(200);
         emailCol.setCellValueFactory(new PropertyValueFactory<Person, String>("email"));
 
-        table.setItems(data);
+        table.setItems(personTestData);
         table.getColumns().addAll(firstNameCol, lastNameCol, emailCol);
 
         splitPane.getItems().add(treeTableView);
@@ -2703,9 +2682,11 @@
     }
 
     private void readOnlyUnbackedObservableListSubListTest(int from, int to) {
-        final SelectedCellsMap<TablePosition> selectedCellsMap = new SelectedCellsMap<>(c -> {
-            // Do nothing
-        });
+        final SelectedCellsMap<TablePosition> selectedCellsMap = new SelectedCellsMap<TablePosition>(c -> { /* Do nothing */}) {
+            @Override public boolean isCellSelectionEnabled() {
+                return false;
+            }
+        };
         ReadOnlyUnbackedObservableList<TablePosition<Object, ?>> selectedCellsSeq = new ReadOnlyUnbackedObservableList<TablePosition<Object, ?>>() {
             @Override public TablePosition<Object, ?> get(int i) {
                 return selectedCellsMap.get(i);
@@ -2942,8 +2923,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 tableView
         tableView.requestFocus();
@@ -3061,16 +3042,8 @@
     }
 
     private void test_rt_36656(boolean removeFromSortOrder, boolean removeFromColumns, boolean setInvisible) {
-        final ObservableList<Person> data =
-                FXCollections.observableArrayList(
-                        new Person("Jacob", "Smith", "jacob.smith@example.com"),
-                        new Person("Isabella", "Johnson", "isabella.johnson@example.com"),
-                        new Person("Ethan", "Williams", "ethan.williams@example.com"),
-                        new Person("Emma", "Jones", "emma.jones@example.com"),
-                        new Person("Michael", "Brown", "michael.brown@example.com"));
-
         TableView<Person> table = new TableView<Person>();
-        table.setItems(data);
+        table.setItems(personTestData);
 
         TableColumn firstNameCol = new TableColumn("First Name");
         firstNameCol.setMinWidth(100);
@@ -3124,11 +3097,11 @@
 
     @Test public void test_rt_36670() {
         final ObservableList<Person> data = FXCollections.observableArrayList(
-                new Person("Jacob", "Smith", "jacob.smith@example.com", true),
-                new Person("Isabella", "Johnson", "isabella.johnson@example.com", false),
-                new Person("Ethan", "Williams", "ethan.williams@example.com", true),
-                new Person("Emma", "Jones", "emma.jones@example.com", true),
-                new Person("Michael", "Brown", "michael.brown@example.com", false));
+                        new Person("Jacob", "Smith", "jacob.smith@example.com", true),
+                        new Person("Isabella", "Johnson", "isabella.johnson@example.com", false),
+                        new Person("Ethan", "Williams", "ethan.williams@example.com", true),
+                        new Person("Emma", "Jones", "emma.jones@example.com", true),
+                        new Person("Michael", "Brown", "michael.brown@example.com", false));
 
         TableColumn invitedCol = new TableColumn<>();
         invitedCol.setText("Invited");
@@ -3187,16 +3160,7 @@
     }
 
     @Test public void test_rt_36669() {
-        final ObservableList<Person> data =
-                FXCollections.observableArrayList(
-                        new Person("Jacob", "Smith", "jacob.smith@example.com"),
-                        new Person("Isabella", "Johnson", "isabella.johnson@example.com"),
-                        new Person("Ethan", "Williams", "ethan.williams@example.com"),
-                        new Person("Emma", "Jones", "emma.jones@example.com"),
-                        new Person("Michael", "Brown", "michael.brown@example.com"));
-
-        TableView<Person> table = new TableView<Person>();
-        table.setItems(data);
+        TableView<Person> table = new TableView<>(personTestData);
 
         TableColumn firstNameCol = new TableColumn("First Name");
         firstNameCol.setMinWidth(100);
@@ -3407,12 +3371,6 @@
         sl.dispose();
     }
 
-
-
-
-
-
-
     @Test public void test_rt_37057_test2_MoveColumn() {
         // create table with a bunch of column and no rows...
         TableView<Integer> table = new TableView<>();
@@ -3841,4 +3799,300 @@
         assertEquals(1, sm.getSelectedItems().size());
         assertEquals("C", sm.getSelectedItems().get(0));
     }
+
+    @Test public void test_rt_38464_rowSelection_selectFirstRowOnly() {
+        TableColumn firstNameCol = new TableColumn("First");
+        firstNameCol.setCellValueFactory(new PropertyValueFactory("firstName"));
+
+        TableColumn lastNameCol = new TableColumn("Last");
+        lastNameCol.setCellValueFactory(new PropertyValueFactory("lastName"));
+
+        TableView tableView = new TableView(personTestData);
+        tableView.getColumns().addAll(firstNameCol, lastNameCol);
+
+        TableView.TableViewSelectionModel<Person> sm = tableView.getSelectionModel();
+        sm.setCellSelectionEnabled(false);
+        sm.setSelectionMode(SelectionMode.MULTIPLE);
+
+        sm.select(0);
+
+        assertTrue(sm.isSelected(0));
+        assertTrue(sm.isSelected(0, firstNameCol));
+        assertTrue(sm.isSelected(0, lastNameCol));
+
+        assertEquals(1, sm.getSelectedIndices().size());
+        assertEquals(1, sm.getSelectedItems().size());
+        assertEquals(1, sm.getSelectedCells().size());
+    }
+
+    @Test public void test_rt_38464_rowSelection_selectFirstRowAndThenCallNoOpMethods() {
+        TableColumn firstNameCol = new TableColumn("First");
+        firstNameCol.setCellValueFactory(new PropertyValueFactory("firstName"));
+
+        TableColumn lastNameCol = new TableColumn("Last");
+        lastNameCol.setCellValueFactory(new PropertyValueFactory("lastName"));
+
+        TableView tableView = new TableView(personTestData);
+        tableView.getColumns().addAll(firstNameCol, lastNameCol);
+
+        TableView.TableViewSelectionModel<Person> sm = tableView.getSelectionModel();
+        sm.setCellSelectionEnabled(false);
+        sm.setSelectionMode(SelectionMode.MULTIPLE);
+
+        sm.select(0);               // select first row
+        sm.select(0);               // this should be a no-op
+        sm.select(0, firstNameCol); // so should this, as we are in row selection mode
+        sm.select(0, lastNameCol);  // and same here
+
+        assertTrue(sm.isSelected(0));
+        assertTrue(sm.isSelected(0, firstNameCol));
+        assertTrue(sm.isSelected(0, lastNameCol));
+
+        assertEquals(1, sm.getSelectedIndices().size());
+        assertEquals(1, sm.getSelectedItems().size());
+        assertEquals(1, sm.getSelectedCells().size());
+    }
+
+
+    @Test public void test_rt_38464_cellSelection_selectFirstRowOnly() {
+        TableColumn firstNameCol = new TableColumn("First");
+        firstNameCol.setCellValueFactory(new PropertyValueFactory("firstName"));
+
+        TableColumn lastNameCol = new TableColumn("Last");
+        lastNameCol.setCellValueFactory(new PropertyValueFactory("lastName"));
+
+        TableView tableView = new TableView(personTestData);
+        tableView.getColumns().addAll(firstNameCol, lastNameCol);
+
+        TableView.TableViewSelectionModel<Person> sm = tableView.getSelectionModel();
+        sm.setCellSelectionEnabled(true);
+        sm.setSelectionMode(SelectionMode.MULTIPLE);
+
+        // select first row. This should be translated into selection of all
+        // cells in this row, but does not result in the row itself being
+        // considered selected.
+        sm.select(0);
+
+        assertFalse(sm.isSelected(0));
+        assertTrue(sm.isSelected(0, firstNameCol));
+        assertTrue(sm.isSelected(0, lastNameCol));
+
+        assertEquals(1, sm.getSelectedIndices().size());
+        assertEquals(1, sm.getSelectedItems().size());
+        assertEquals(2, sm.getSelectedCells().size());
+    }
+
+    @Test public void test_rt_38464_cellSelection_selectFirstRowAndThenCallNoOpMethods() {
+        TableColumn firstNameCol = new TableColumn("First");
+        firstNameCol.setCellValueFactory(new PropertyValueFactory("firstName"));
+
+        TableColumn lastNameCol = new TableColumn("Last");
+        lastNameCol.setCellValueFactory(new PropertyValueFactory("lastName"));
+
+        TableView tableView = new TableView(personTestData);
+        tableView.getColumns().addAll(firstNameCol, lastNameCol);
+
+        TableView.TableViewSelectionModel<Person> sm = tableView.getSelectionModel();
+        sm.setCellSelectionEnabled(true);
+        sm.setSelectionMode(SelectionMode.MULTIPLE);
+
+        // select first row. This should be translated into selection of all
+        // cells in this row, but does not result in the row itself being
+        // considered selected.
+        sm.select(0);               // select first row
+        sm.select(0, firstNameCol); // This line and the next should be no-ops
+        sm.select(0, lastNameCol);
+
+        assertFalse(sm.isSelected(0));
+        assertTrue(sm.isSelected(0, firstNameCol));
+        assertTrue(sm.isSelected(0, lastNameCol));
+
+        assertEquals(1, sm.getSelectedIndices().size());
+        assertEquals(1, sm.getSelectedItems().size());
+        assertEquals(2, sm.getSelectedCells().size());
+    }
+
+    @Test public void test_rt38464_selectCellMultipleTimes() {
+        TableColumn firstNameCol = new TableColumn("First");
+        firstNameCol.setCellValueFactory(new PropertyValueFactory("firstName"));
+
+        TableColumn lastNameCol = new TableColumn("Last");
+        lastNameCol.setCellValueFactory(new PropertyValueFactory("lastName"));
+
+        TableView tableView = new TableView(personTestData);
+        tableView.getColumns().addAll(firstNameCol, lastNameCol);
+
+        TableView.TableViewSelectionModel<Person> sm = tableView.getSelectionModel();
+        sm.setCellSelectionEnabled(true);
+        sm.setSelectionMode(SelectionMode.MULTIPLE);
+
+        // default selection when in cell selection mode
+        assertEquals(1, sm.getSelectedCells().size());
+        assertEquals(1, sm.getSelectedItems().size());
+        assertEquals(1, sm.getSelectedIndices().size());
+
+        // select the first cell
+        sm.select(0, firstNameCol);
+        assertEquals(1, sm.getSelectedCells().size());
+        assertEquals(1, sm.getSelectedItems().size());
+        assertEquals(1, sm.getSelectedIndices().size());
+
+        // select the first cell....again
+        sm.select(0, firstNameCol);
+        assertEquals(1, sm.getSelectedCells().size());
+        assertEquals(1, sm.getSelectedItems().size());
+        assertEquals(1, sm.getSelectedIndices().size());
+    }
+
+    @Test public void test_rt38464_selectCellThenRow() {
+        TableColumn firstNameCol = new TableColumn("First");
+        firstNameCol.setCellValueFactory(new PropertyValueFactory("firstName"));
+
+        TableColumn lastNameCol = new TableColumn("Last");
+        lastNameCol.setCellValueFactory(new PropertyValueFactory("lastName"));
+
+        TableView tableView = new TableView(personTestData);
+        tableView.getColumns().addAll(firstNameCol, lastNameCol);
+
+        TableView.TableViewSelectionModel<Person> sm = tableView.getSelectionModel();
+        sm.setCellSelectionEnabled(true);
+        sm.setSelectionMode(SelectionMode.MULTIPLE);
+
+        // default selection when in cell selection mode
+        assertEquals(1, sm.getSelectedCells().size());
+        assertEquals(1, sm.getSelectedItems().size());
+        assertEquals(1, sm.getSelectedIndices().size());
+
+        // select the first cell
+        sm.select(0, firstNameCol);
+        assertEquals(1, sm.getSelectedCells().size());
+        assertEquals(1, sm.getSelectedItems().size());
+        assertEquals(1, sm.getSelectedIndices().size());
+
+        // select the first row
+        sm.select(0);
+
+        // we go to 2 here as all cells in the row become selected. What we do
+        // not expect is to go to 3, as that would mean duplication
+        assertEquals(2, sm.getSelectedCells().size());
+        assertEquals(1, sm.getSelectedItems().size());
+        assertEquals(1, sm.getSelectedIndices().size());
+    }
+
+    @Test public void test_rt38464_selectRowThenCell() {
+        TableColumn firstNameCol = new TableColumn("First");
+        firstNameCol.setCellValueFactory(new PropertyValueFactory("firstName"));
+
+        TableColumn lastNameCol = new TableColumn("Last");
+        lastNameCol.setCellValueFactory(new PropertyValueFactory("lastName"));
+
+        TableView tableView = new TableView(personTestData);
+        tableView.getColumns().addAll(firstNameCol, lastNameCol);
+
+        TableView.TableViewSelectionModel<Person> sm = tableView.getSelectionModel();
+        sm.setCellSelectionEnabled(true);
+        sm.setSelectionMode(SelectionMode.MULTIPLE);
+
+        // default selection when in cell selection mode
+        assertEquals(1, sm.getSelectedCells().size());
+        assertEquals(1, sm.getSelectedItems().size());
+        assertEquals(1, sm.getSelectedIndices().size());
+
+        // select the first row
+        sm.select(0);
+
+        // we go to 2 here as all cells in the row become selected.
+        assertEquals(2, sm.getSelectedCells().size());
+        assertEquals(1, sm.getSelectedItems().size());
+        assertEquals(1, sm.getSelectedIndices().size());
+
+        // select the first cell - no change is expected
+        sm.select(0, firstNameCol);
+        assertEquals(2, sm.getSelectedCells().size());
+        assertEquals(1, sm.getSelectedItems().size());
+        assertEquals(1, sm.getSelectedIndices().size());
+    }
+
+    @Test public void test_rt38464_selectTests_cellSelection_singleSelection_selectsOneRow() {
+        test_rt38464_selectTests(true, true, true);
+    }
+
+    @Test public void test_rt38464_selectTests_cellSelection_singleSelection_selectsTwoRows() {
+        test_rt38464_selectTests(true, true, false);
+    }
+
+    @Test public void test_rt38464_selectTests_cellSelection_multipleSelection_selectsOneRow() {
+        test_rt38464_selectTests(true, false, true);
+    }
+
+    @Test public void test_rt38464_selectTests_cellSelection_multipleSelection_selectsTwoRows() {
+        test_rt38464_selectTests(true, false, false);
+    }
+
+    @Test public void test_rt38464_selectTests_rowSelection_singleSelection_selectsOneRow() {
+        test_rt38464_selectTests(false, true, true);
+    }
+
+    @Test public void test_rt38464_selectTests_rowSelection_singleSelection_selectsTwoRows() {
+        test_rt38464_selectTests(false, true, false);
+    }
+
+    @Test public void test_rt38464_selectTests_rowSelection_multipleSelection_selectsOneRow() {
+        test_rt38464_selectTests(false, false, true);
+    }
+
+    @Test public void test_rt38464_selectTests_rowSelection_multipleSelection_selectsTwoRows() {
+        test_rt38464_selectTests(false, false, false);
+    }
+
+    private void test_rt38464_selectTests(boolean cellSelection, boolean singleSelection, boolean selectsOneRow) {
+        TableColumn firstNameCol = new TableColumn("First");
+        firstNameCol.setCellValueFactory(new PropertyValueFactory("firstName"));
+
+        TableColumn lastNameCol = new TableColumn("Last");
+        lastNameCol.setCellValueFactory(new PropertyValueFactory("lastName"));
+
+        TableView tableView = new TableView(personTestData);
+        tableView.getColumns().addAll(firstNameCol, lastNameCol);
+
+        TableView.TableViewSelectionModel<Person> sm = tableView.getSelectionModel();
+        sm.setCellSelectionEnabled(cellSelection);
+        sm.setSelectionMode(singleSelection ? SelectionMode.SINGLE : SelectionMode.MULTIPLE);
+
+        // default selection when in cell selection mode
+        assertEquals(1, sm.getSelectedCells().size());
+        assertEquals(1, sm.getSelectedItems().size());
+        assertEquals(1, sm.getSelectedIndices().size());
+
+        if (selectsOneRow) {
+            sm.select(0);
+        } else {
+            // select the first two rows
+            sm.selectIndices(0, 1);
+        }
+
+        final int expectedCells = singleSelection                    ? 1 :
+                                  selectsOneRow   && cellSelection   ? 2 :
+                                  selectsOneRow   && !cellSelection  ? 1 :
+                                  !selectsOneRow  && cellSelection   ? 4 :
+                               /* !selectsOneRow  && !cellSelection */ 2;
+
+        final int expectedItems = singleSelection ? 1 :
+                                  selectsOneRow   ? 1 : 2;
+
+        assertEquals(expectedCells, sm.getSelectedCells().size());
+        assertEquals(expectedItems, sm.getSelectedItems().size());
+        assertEquals(expectedItems, sm.getSelectedIndices().size());
+
+        // we expect the table column of all selected cells, in this instance,
+        // to be null as we have not explicitly stated a column, nor have we clicked
+        // on a column. The only alternative is to use the first column.
+        for (TablePosition<?,?> tp : sm.getSelectedCells()) {
+            if (cellSelection) {
+                assertNotNull(tp.getTableColumn());
+            } else {
+                assertNull(tp.getTableColumn());
+            }
+        }
+    }
 }
--- a/modules/controls/src/test/java/javafx/scene/control/TreeTableViewKeyInputTest.java	Tue Sep 02 15:32:15 2014 +1200
+++ b/modules/controls/src/test/java/javafx/scene/control/TreeTableViewKeyInputTest.java	Wed Sep 03 12:12:43 2014 +1200
@@ -29,7 +29,9 @@
 import javafx.beans.Observable;
 import javafx.beans.property.ReadOnlyStringWrapper;
 import javafx.beans.value.ObservableValue;
+import javafx.collections.FXCollections;
 import javafx.collections.ListChangeListener;
+import javafx.collections.ObservableList;
 import javafx.event.EventHandler;
 import javafx.scene.input.KeyCode;
 import javafx.util.Callback;
@@ -4167,4 +4169,146 @@
 
         sl.dispose();
     }
+
+//    @Test public void test_rt_38326() {
+//        int argCount = 4;
+//        int testCount = (int) Math.pow(2, argCount);
+//        for (int test = 0; test < testCount; test++) {
+//            boolean moveUp                                      = (test & 0b1000) == 0b1000;
+//            boolean singleSelection                             = (test & 0b0100) == 0b0100;
+//            boolean cellSelection                               = (test & 0b0010) == 0b0010;
+//            boolean updateItemsListBeforeSelectionModelChanges  = (test & 0b0001) == 0b0001;
+//
+//            StringBuilder sb = new StringBuilder("@Test public void test_rt_38326_focusLostOnShortcutKeyNav_");
+//            sb.append(moveUp ? "moveUp_" : "moveDown_");
+//            sb.append(singleSelection ? "singleSelection_" : "multipleSelection_");
+//            sb.append(cellSelection ? "cellSelection_" : "rowSelection_");
+//            sb.append(updateItemsListBeforeSelectionModelChanges ? "updateItemsListBeforeSelectionModelChanges" : "updateItemsListAfterSelectionModelChanges");
+//            sb.append("() {\n    ");
+//            sb.append("test_rt_38326(");
+//            sb.append(moveUp + ", ");
+//            sb.append(singleSelection + ", ");
+//            sb.append(cellSelection + ", ");
+//            sb.append(updateItemsListBeforeSelectionModelChanges);
+//            sb.append(");\n}");
+//
+//            System.out.println(sb);
+//        }
+//    }
+
+    // -- tests generated by above commented out code
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveDown_multipleSelection_rowSelection_updateItemsListAfterSelectionModelChanges() {
+        test_rt_38326(false, false, false, false);
+    }
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveDown_multipleSelection_rowSelection_updateItemsListBeforeSelectionModelChanges() {
+        test_rt_38326(false, false, false, true);
+    }
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveDown_multipleSelection_cellSelection_updateItemsListAfterSelectionModelChanges() {
+        test_rt_38326(false, false, true, false);
+    }
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveDown_multipleSelection_cellSelection_updateItemsListBeforeSelectionModelChanges() {
+        test_rt_38326(false, false, true, true);
+    }
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveDown_singleSelection_rowSelection_updateItemsListAfterSelectionModelChanges() {
+        test_rt_38326(false, true, false, false);
+    }
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveDown_singleSelection_rowSelection_updateItemsListBeforeSelectionModelChanges() {
+        test_rt_38326(false, true, false, true);
+    }
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveDown_singleSelection_cellSelection_updateItemsListAfterSelectionModelChanges() {
+        test_rt_38326(false, true, true, false);
+    }
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveDown_singleSelection_cellSelection_updateItemsListBeforeSelectionModelChanges() {
+        test_rt_38326(false, true, true, true);
+    }
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveUp_multipleSelection_rowSelection_updateItemsListAfterSelectionModelChanges() {
+        test_rt_38326(true, false, false, false);
+    }
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveUp_multipleSelection_rowSelection_updateItemsListBeforeSelectionModelChanges() {
+        test_rt_38326(true, false, false, true);
+    }
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveUp_multipleSelection_cellSelection_updateItemsListAfterSelectionModelChanges() {
+        test_rt_38326(true, false, true, false);
+    }
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveUp_multipleSelection_cellSelection_updateItemsListBeforeSelectionModelChanges() {
+        test_rt_38326(true, false, true, true);
+    }
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveUp_singleSelection_rowSelection_updateItemsListAfterSelectionModelChanges() {
+        test_rt_38326(true, true, false, false);
+    }
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveUp_singleSelection_rowSelection_updateItemsListBeforeSelectionModelChanges() {
+        test_rt_38326(true, true, false, true);
+    }
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveUp_singleSelection_cellSelection_updateItemsListAfterSelectionModelChanges() {
+        test_rt_38326(true, true, true, false);
+    }
+    @Test public void test_rt_38326_focusLostOnShortcutKeyNav_moveUp_singleSelection_cellSelection_updateItemsListBeforeSelectionModelChanges() {
+        test_rt_38326(true, true, true, true);
+    }
+
+    private void test_rt_38326(boolean moveUp, boolean singleSelection, boolean cellSelection, boolean updateItemsListBeforeSelectionModelChanges) {
+        final int items = 10;
+        ObservableList<TreeItem<String>> itemsList = FXCollections.observableArrayList();
+        for (int i = 0; i < items; i++) {
+            itemsList.add(new TreeItem<>("Row " + i));
+        }
+
+        root.setExpanded(true);
+
+        if (updateItemsListBeforeSelectionModelChanges) {
+            root.getChildren().clear();
+            root.getChildren().addAll(itemsList);
+        }
+
+        TreeTableColumn<String, String> col = new TreeTableColumn<>("Column");
+        col.setCellValueFactory(param -> new ReadOnlyStringWrapper(param.getValue().getValue()));
+
+        TreeTableColumn<String, String> col2 = new TreeTableColumn<>("Column 2");
+        col2.setCellValueFactory(param -> new ReadOnlyStringWrapper(param.getValue().getValue()));
+
+        tableView.getColumns().setAll(col, col2);
+
+        TreeTableView.TreeTableViewSelectionModel<String> sm = tableView.getSelectionModel();
+        sm.setSelectionMode(singleSelection ? SelectionMode.SINGLE : SelectionMode.MULTIPLE);
+        sm.setCellSelectionEnabled(cellSelection);
+
+        if (! updateItemsListBeforeSelectionModelChanges) {
+            root.getChildren().clear();
+            root.getChildren().addAll(itemsList);
+        }
+
+        StageLoader sl = new StageLoader(tableView);
+
+        // test the initial state to ensure it is as we expect
+        if (cellSelection) {
+            assertFalse(sm.isSelected(0));
+            assertTrue(sm.isSelected(0, col));
+            assertFalse(sm.isSelected(0, col2));
+            assertEquals(1, sm.getSelectedIndices().size());
+            assertEquals(1, sm.getSelectedItems().size());
+            assertEquals(1, sm.getSelectedCells().size());
+        } else {
+            assertTrue(sm.isSelected(0));
+            assertTrue(sm.isSelected(0, col));
+            assertTrue(sm.isSelected(0, col2));
+            assertEquals(1, sm.getSelectedIndices().size());
+            assertEquals(1, sm.getSelectedItems().size());
+            assertEquals(1, sm.getSelectedCells().size());
+        }
+
+        final int startRow = 5;
+        sm.clearSelection();
+        sm.select(startRow, col);
+        assertEquals(1, sm.getSelectedCells().size());
+        assertEquals(startRow, sm.getSelectedCells().get(0).getRow());
+        assertEquals(col, sm.getSelectedCells().get(0).getTableColumn());
+        assertEquals(startRow, tableView.getFocusModel().getFocusedCell().getRow());
+        assertEquals(col, tableView.getFocusModel().getFocusedCell().getTableColumn());
+
+        keyboard.doKeyPress(moveUp ? KeyCode.UP : KeyCode.DOWN, KeyModifier.getShortcutKey());
+        assertEquals(moveUp ? startRow-1 : startRow+1, tableView.getFocusModel().getFocusedCell().getRow());
+        assertEquals(col, tableView.getFocusModel().getFocusedCell().getTableColumn());
+
+        sl.dispose();
+    }
 }
--- a/modules/controls/src/test/java/javafx/scene/control/TreeTableViewMouseInputTest.java	Tue Sep 02 15:32:15 2014 +1200
+++ b/modules/controls/src/test/java/javafx/scene/control/TreeTableViewMouseInputTest.java	Wed Sep 03 12:12:43 2014 +1200
@@ -61,8 +61,8 @@
 //@Ignore("Disabling tests as they fail with OOM in continuous builds")
 public class TreeTableViewMouseInputTest {
     private TreeTableView<String> tableView;
-    private TreeTableView.TreeTableViewSelectionModel<String> sm;
-    private TreeTableView.TreeTableViewFocusModel<String> fm;
+    private TreeTableView.TreeTableViewSelectionModel<?> sm;
+    private TreeTableView.TreeTableViewFocusModel<?> fm;
     
     private final TreeTableColumn<String, String> col0 = new TreeTableColumn<String, String>("col0");
     private final TreeTableColumn<String, String> col1 = new TreeTableColumn<String, String>("col1");
@@ -152,8 +152,8 @@
     private String debug() {
         StringBuilder sb = new StringBuilder("Selected Cells: [");
         
-        List<TreeTablePosition<String,?>> cells = sm.getSelectedCells();
-        for (TreeTablePosition<String,?> tp : cells) {
+        ObservableList<? extends TreeTablePosition<?, ?>> cells = sm.getSelectedCells();
+        for (TreeTablePosition<?,?> tp : cells) {
             sb.append("(");
             sb.append(tp.getRow());
             sb.append(",");
@@ -573,7 +573,7 @@
 
         TreeTablePosition pos = sm.getSelectedCells().get(0);
         assertEquals(1, pos.getRow());
-        assertNull(pos.getTableColumn());
+        assertNotNull(pos.getTableColumn());
     }
 
     @Test public void test_rt_33897_cellSelection() {
@@ -738,16 +738,16 @@
         assertTrue(sm.isSelected(0, firstNameCol));
         assertEquals(1, sm.getSelectedCells().size());
 
+        TreeTableCell cell_0_0 = (TreeTableCell) VirtualFlowTestUtils.getCell(table, 0, 0);
         TreeTableCell cell_0_1 = (TreeTableCell) VirtualFlowTestUtils.getCell(table, 0, 1);
         TreeTableCell cell_0_2 = (TreeTableCell) VirtualFlowTestUtils.getCell(table, 0, 2);
-        TreeTableCell cell_0_3 = (TreeTableCell) VirtualFlowTestUtils.getCell(table, 0, 3);
 
+        TreeTableCell cell_1_0 = (TreeTableCell) VirtualFlowTestUtils.getCell(table, 1, 0);
         TreeTableCell cell_1_1 = (TreeTableCell) VirtualFlowTestUtils.getCell(table, 1, 1);
         TreeTableCell cell_1_2 = (TreeTableCell) VirtualFlowTestUtils.getCell(table, 1, 2);
-        TreeTableCell cell_1_3 = (TreeTableCell) VirtualFlowTestUtils.getCell(table, 1, 3);
 
         MouseEventFirer mouse = selectTwoRows ?
-                new MouseEventFirer(cell_1_3) : new MouseEventFirer(cell_0_3);
+                new MouseEventFirer(cell_1_2) : new MouseEventFirer(cell_0_2);
 
         mouse.fireMousePressAndRelease(KeyModifier.SHIFT);
 
@@ -763,14 +763,254 @@
 
         assertEquals(selectTwoRows ? 6 : 3, sm.getSelectedCells().size());
 
+        assertTrue(cell_0_0.isSelected());
         assertTrue(cell_0_1.isSelected());
         assertTrue(cell_0_2.isSelected());
-        assertTrue(cell_0_3.isSelected());
 
         if (selectTwoRows) {
+            assertTrue(cell_1_0.isSelected());
             assertTrue(cell_1_1.isSelected());
             assertTrue(cell_1_2.isSelected());
-            assertTrue(cell_1_3.isSelected());
+        }
+    }
+
+    @Test public void test_rt_38464_rowSelection() {
+        ObservableList<TreeItem<Person>> persons = FXCollections.observableArrayList(
+                new TreeItem<>(new Person("Jacob", "Smith", "jacob.smith@example.com")),
+                new TreeItem<>(new Person("Isabella", "Johnson", "isabella.johnson@example.com")),
+                new TreeItem<>(new Person("Ethan", "Williams", "ethan.williams@example.com")),
+                new TreeItem<>(new Person("Emma", "Jones", "emma.jones@example.com")),
+                new TreeItem<>(new Person("Michael", "Brown", "michael.brown@example.com")));
+
+        TreeTableView<Person> table = new TreeTableView<>();
+
+        TreeItem<Person> root = new TreeItem<Person>(new Person("Root", null, null));
+        root.setExpanded(true);
+        table.setRoot(root);
+        table.setShowRoot(false);
+        root.getChildren().setAll(persons);
+
+        TreeTableColumn firstNameCol = new TreeTableColumn("First Name");
+        firstNameCol.setCellValueFactory(new TreeItemPropertyValueFactory<Person, String>("firstName"));
+
+        TreeTableColumn lastNameCol = new TreeTableColumn("Last Name");
+        lastNameCol.setCellValueFactory(new TreeItemPropertyValueFactory<Person, String>("lastName"));
+
+        TreeTableColumn emailCol = new TreeTableColumn("Email");
+        emailCol.setCellValueFactory(new TreeItemPropertyValueFactory<Person, String>("email"));
+
+        table.getColumns().addAll(firstNameCol, lastNameCol, emailCol);
+
+        sm = table.getSelectionModel();
+        sm.setCellSelectionEnabled(false);
+        sm.setSelectionMode(SelectionMode.MULTIPLE);
+
+        sm.clearSelection();
+        sm.select(0, lastNameCol);
+
+        assertTrue(sm.isSelected(0, lastNameCol));
+        assertEquals(1, sm.getSelectedCells().size());
+
+        TreeTableCell cell_4_2 = (TreeTableCell) VirtualFlowTestUtils.getCell(table, 4, 1);
+
+        MouseEventFirer mouse = new MouseEventFirer(cell_4_2);
+        mouse.fireMousePressAndRelease(KeyModifier.SHIFT);
+
+        // we are in row selection mode, so all cells in the selected rows should
+        // be selected. We test this per-cell, but also per-row.
+        for (int row = 0; row < 5; row++) {
+            // test that the selection model is accurate
+            assertTrue(sm.isSelected(row, firstNameCol));
+            assertTrue(sm.isSelected(row, lastNameCol));
+            assertTrue(sm.isSelected(row, emailCol));
+            assertTrue(sm.isSelected(row));
+
+            // and assert that the visuals are accurate
+            // (TableCells should not be selected, but TableRows should be)
+            for (int column = 0; column < 3; column++) {
+                if (row == 4 && column == 2) {
+                    // bizarrely cell (4,2), i.e. the bottom-right cell consisting
+                    // of Michael Brown's email address, doesn't exist.
+                    continue;
+                }
+                TreeTableCell cell = (TreeTableCell) VirtualFlowTestUtils.getCell(table, row, column);
+                assertFalse("cell[row: " + row + ", column: " + column + "] is selected, but shouldn't be", cell.isSelected());
+            }
+            TreeTableRow cell = (TreeTableRow) VirtualFlowTestUtils.getCell(table, row);
+            assertTrue(cell.isSelected());
+        }
+    }
+
+    @Test public void test_rt_38464_cellSelection() {
+        ObservableList<TreeItem<Person>> persons = FXCollections.observableArrayList(
+                new TreeItem<>(new Person("Jacob", "Smith", "jacob.smith@example.com")),
+                new TreeItem<>(new Person("Isabella", "Johnson", "isabella.johnson@example.com")),
+                new TreeItem<>(new Person("Ethan", "Williams", "ethan.williams@example.com")),
+                new TreeItem<>(new Person("Emma", "Jones", "emma.jones@example.com")),
+                new TreeItem<>(new Person("Michael", "Brown", "michael.brown@example.com")));
+
+        TreeTableView<Person> table = new TreeTableView<>();
+
+        TreeItem<Person> root = new TreeItem<>(new Person("Root", null, null));
+        root.setExpanded(true);
+        table.setRoot(root);
+        table.setShowRoot(false);
+        root.getChildren().setAll(persons);
+
+        TreeTableColumn firstNameCol = new TreeTableColumn("First Name");
+        firstNameCol.setCellValueFactory(new TreeItemPropertyValueFactory<Person, String>("firstName"));
+
+        TreeTableColumn lastNameCol = new TreeTableColumn("Last Name");
+        lastNameCol.setCellValueFactory(new TreeItemPropertyValueFactory<Person, String>("lastName"));
+
+        TreeTableColumn emailCol = new TreeTableColumn("Email");
+        emailCol.setCellValueFactory(new TreeItemPropertyValueFactory<Person, String>("email"));
+
+        table.getColumns().addAll(firstNameCol, lastNameCol, emailCol);
+
+        sm = table.getSelectionModel();
+        sm.setCellSelectionEnabled(true);
+        sm.setSelectionMode(SelectionMode.MULTIPLE);
+
+        sm.clearSelection();
+        sm.select(0, emailCol);
+        table.getFocusModel().focus(0, emailCol);
+
+        assertTrue(sm.isSelected(0, emailCol));
+        assertEquals(1, sm.getSelectedCells().size());
+
+        TreeTableCell cell_4_2 = (TreeTableCell) VirtualFlowTestUtils.getCell(table, 4, 2);
+        assertEquals(emailCol, cell_4_2.getTableColumn());
+
+        new MouseEventFirer(cell_4_2).fireMousePressAndRelease(KeyModifier.SHIFT);
+
+        for (int row = 0; row < 5; row++) {
+            // test that the selection model is accurate
+            assertFalse(sm.isSelected(row, firstNameCol));
+            assertFalse(sm.isSelected(row, lastNameCol));
+            assertTrue(sm.isSelected(row, emailCol));
+            assertFalse(sm.isSelected(row));
+
+            // and assert that the visuals are accurate
+            // (some TableCells should be selected, but TableRows should not be)
+            for (int column = 0; column < 3; column++) {
+                if (row == 4 && column == 2) {
+                    // bizarrely cell (4,2), i.e. the bottom-right cell consisting
+                    // of Michael Brown's email address, doesn't exist.
+                    continue;
+                }
+                TreeTableCell cell = (TreeTableCell) VirtualFlowTestUtils.getCell(table, row, column);
+                assertEquals(column == 2 ? true : false, cell.isSelected());
+            }
+            TreeTableRow cell = (TreeTableRow) VirtualFlowTestUtils.getCell(table, row);
+            assertFalse(cell.isSelected());
+        }
+    }
+
+    @Test public void test_rt_38464_selectedColumnChangesWhenCellsInRowClicked_cellSelection_singleSelection() {
+        test_rt_38464_selectedColumnChangesWhenCellsInRowClicked(true, true);
+    }
+
+    @Test public void test_rt_38464_selectedColumnChangesWhenCellsInRowClicked_cellSelection_multipleSelection() {
+        test_rt_38464_selectedColumnChangesWhenCellsInRowClicked(true, false);
+    }
+
+    @Test public void test_rt_38464_selectedColumnChangesWhenCellsInRowClicked_rowSelection_singleSelection() {
+        test_rt_38464_selectedColumnChangesWhenCellsInRowClicked(false, true);
+    }
+
+    @Test public void test_rt_38464_selectedColumnChangesWhenCellsInRowClicked_rowSelection_multipleSelection() {
+        test_rt_38464_selectedColumnChangesWhenCellsInRowClicked(false, false);
+    }
+
+    private void test_rt_38464_selectedColumnChangesWhenCellsInRowClicked(boolean cellSelection, boolean singleSelection) {
+        ObservableList<TreeItem<Person>> persons = FXCollections.observableArrayList(
+                new TreeItem<>(new Person("Jacob", "Smith", "jacob.smith@example.com")),
+                new TreeItem<>(new Person("Isabella", "Johnson", "isabella.johnson@example.com")),
+                new TreeItem<>(new Person("Ethan", "Williams", "ethan.williams@example.com")),
+                new TreeItem<>(new Person("Emma", "Jones", "emma.jones@example.com")),
+                new TreeItem<>(new Person("Michael", "Brown", "michael.brown@example.com")));
+
+        TreeTableView<Person> table = new TreeTableView<>();
+
+        TreeItem<Person> root = new TreeItem<Person>(new Person("Root", null, null));
+        root.setExpanded(true);
+        table.setRoot(root);
+        table.setShowRoot(false);
+        root.getChildren().setAll(persons);
+
+        TreeTableColumn firstNameCol = new TreeTableColumn("First Name");
+        firstNameCol.setCellValueFactory(new TreeItemPropertyValueFactory<Person, String>("firstName"));
+
+        TreeTableColumn lastNameCol = new TreeTableColumn("Last Name");
+        lastNameCol.setCellValueFactory(new TreeItemPropertyValueFactory<Person, String>("lastName"));
+
+        TreeTableColumn emailCol = new TreeTableColumn("Email");
+        emailCol.setCellValueFactory(new TreeItemPropertyValueFactory<Person, String>("email"));
+
+        table.getColumns().addAll(firstNameCol, lastNameCol, emailCol);
+
+        TreeTableView.TreeTableViewSelectionModel<Person> sm = table.getSelectionModel();
+        sm.setCellSelectionEnabled(cellSelection);
+        sm.setSelectionMode(singleSelection ? SelectionMode.SINGLE : SelectionMode.MULTIPLE);
+
+        TreeTableCell cell_0_0 = (TreeTableCell) VirtualFlowTestUtils.getCell(table, 0, 0);
+        TreeTableCell cell_0_1 = (TreeTableCell) VirtualFlowTestUtils.getCell(table, 0, 1);
+        TreeTableCell cell_0_2 = (TreeTableCell) VirtualFlowTestUtils.getCell(table, 0, 2);
+
+        sm.clearSelection();
+
+        // click on cell (0,0).
+        new MouseEventFirer(cell_0_0).fireMousePressAndRelease();
+
+        if (cellSelection) {
+            // Because we are in cell selection mode, this has the effect of
+            // selecting just the one cell.
+            assertFalse(sm.isSelected(0));
+            assertTrue(sm.isSelected(0, firstNameCol));
+            assertFalse(sm.isSelected(0, lastNameCol));
+            assertFalse(sm.isSelected(0, emailCol));
+            assertEquals(1, sm.getSelectedCells().size());
+            assertEquals(0, sm.getSelectedCells().get(0).getRow());
+            assertEquals(firstNameCol, sm.getSelectedCells().get(0).getTableColumn());
+        } else {
+            // Because we are in row selection mode, this has
+            // the effect of selecting all cells and the backing row. However, the
+            // selected cell will be (0, firstNameCol) only
+            assertTrue(sm.isSelected(0));
+            assertTrue(sm.isSelected(0, firstNameCol));
+            assertTrue(sm.isSelected(0, lastNameCol));
+            assertTrue(sm.isSelected(0, emailCol));
+            assertEquals(1, sm.getSelectedCells().size());
+            assertEquals(0, sm.getSelectedCells().get(0).getRow());
+            assertEquals(firstNameCol, sm.getSelectedCells().get(0).getTableColumn());
+        }
+
+        // click on cell (0,1).
+        new MouseEventFirer(cell_0_1).fireMousePressAndRelease();
+
+        if (cellSelection) {
+            // Everything should remain the same, except the
+            // column of the single selected cell should change to lastNameCol.
+            assertFalse(sm.isSelected(0));
+            assertFalse(sm.isSelected(0, firstNameCol));
+            assertTrue(sm.isSelected(0, lastNameCol));
+            assertFalse(sm.isSelected(0, emailCol));
+            assertEquals(1, sm.getSelectedCells().size());
+            TreeTablePosition<?,?> cell = sm.getSelectedCells().get(0);
+            assertEquals(0, cell.getRow());
+            assertEquals(lastNameCol, cell.getTableColumn());
+        } else {
+            // Everything should remain the same, except the
+            // column of the single selected cell should change to lastNameCol.
+            assertTrue(sm.isSelected(0));
+            assertTrue(sm.isSelected(0, firstNameCol));
+            assertTrue(sm.isSelected(0, lastNameCol));
+            assertTrue(sm.isSelected(0, emailCol));
+            assertEquals(1, sm.getSelectedCells().size());
+            TreeTablePosition<?,?> cell = sm.getSelectedCells().get(0);
+            assertEquals(0, cell.getRow());
+            assertEquals(lastNameCol, cell.getTableColumn());
         }
     }
 }
--- a/modules/controls/src/test/java/javafx/scene/control/TreeTableViewSelectionModelImplTest.java	Tue Sep 02 15:32:15 2014 +1200
+++ b/modules/controls/src/test/java/javafx/scene/control/TreeTableViewSelectionModelImplTest.java	Wed Sep 03 12:12:43 2014 +1200
@@ -120,6 +120,7 @@
     @Test public void selectRowWhenInSingleCellSelectionMode() {
         model.setSelectionMode(SelectionMode.SINGLE);
         model.setCellSelectionEnabled(true);
+        model.clearSelection();
         assertFalse(model.isSelected(3, col0));
         model.select(1);  // put in another selection to make sure it is wiped out
         model.select(3);
@@ -127,12 +128,13 @@
         assertFalse(model.isSelected(3, col0));
         assertFalse(cells(model), model.isSelected(3, null));
         assertFalse(model.isSelected(3));
-        assertEquals(0, model.getSelectedCells().size());
+        assertEquals(1, model.getSelectedCells().size());
     }
 
     @Test public void selectRowWhenInSingleCellSelectionMode2() {
         model.setSelectionMode(SelectionMode.SINGLE);
         model.setCellSelectionEnabled(true);
+        model.clearSelection();
         model.select(1, null);  // put in another selection to make sure it is wiped out
         model.select(3, null);
 
@@ -140,20 +142,21 @@
         assertFalse(model.isSelected(3, col0));
         assertFalse(cells(model), model.isSelected(3, null));
         assertFalse(model.isSelected(3));
-        assertEquals(0, model.getSelectedCells().size());
+        assertEquals(1, model.getSelectedCells().size());
     }
 
     @Test public void selectRowWhenInMultipleCellSelectionMode() {
         model.setSelectionMode(SelectionMode.MULTIPLE);
         model.setCellSelectionEnabled(true);
+        model.clearSelection();
         model.select(1);
         model.select(3);
 
-        assertFalse(model.isSelected(1, col0));
-        assertFalse(model.isSelected(3, col0));
+        assertTrue(model.isSelected(1, col0));
+        assertTrue(model.isSelected(3, col0));
         assertFalse(model.isSelected(3, null));
         assertFalse(model.isSelected(3));
-        assertEquals(0, model.getSelectedCells().size());
+        assertEquals(6, model.getSelectedCells().size());
     }
 
     @Test public void selectCellWhenInSingleCellSelectionMode() {
@@ -172,6 +175,7 @@
         model.setSelectionMode(SelectionMode.MULTIPLE);
         model.setCellSelectionEnabled(true);
         assertFalse(model.isSelected(3, col0));
+        model.clearSelection();
         model.select(1, col0);
         model.select(3, col0);
         assertTrue(model.isSelected(1, col0));
@@ -286,6 +290,7 @@
     @Test public void selectPreviousCellWithMultipleSelection() {
         model.setSelectionMode(SelectionMode.MULTIPLE);
         model.setCellSelectionEnabled(true);
+        model.clearSelection();
         model.select(2, col1);
         model.selectAboveCell();
         assertTrue(model.isSelected(2, col1));
@@ -296,6 +301,7 @@
     @Test public void selectNextCellWithMultipleSelection() {
         model.setSelectionMode(SelectionMode.MULTIPLE);
         model.setCellSelectionEnabled(true);
+        model.clearSelection();
         model.select(2, col1);
         model.selectBelowCell();
         assertTrue(model.isSelected(2, col1));
@@ -306,6 +312,7 @@
     @Test public void selectLeftCellWithMultipleSelection() {
         model.setSelectionMode(SelectionMode.MULTIPLE);
         model.setCellSelectionEnabled(true);
+        model.clearSelection();
         model.select(2, col1);
         model.selectLeftCell();
         assertTrue(cells(model), model.isSelected(2, col1));
@@ -316,6 +323,7 @@
     @Test public void selectRightCellWithMultipleSelection() {
         model.setSelectionMode(SelectionMode.MULTIPLE);
         model.setCellSelectionEnabled(true);
+        model.clearSelection();
         model.select(2, col1);
         model.selectRightCell();
         assertTrue(cells(model), model.isSelected(2, col1));
@@ -329,7 +337,7 @@
 
         model.select(10);
         assertFalse(cells(model), model.isSelected(10, null));
-        assertEquals(0, model.getSelectedCells().size());
+        assertEquals(1, model.getSelectedCells().size());
     }
 
     @Test public void ensureCellSelectionIsNoOpWhenDisabled() {
@@ -411,6 +419,7 @@
     @Test public void selectFirstRowInMultipleSelectionCellMode() {
         model.setSelectionMode(SelectionMode.MULTIPLE);
         model.setCellSelectionEnabled(true);
+        model.clearSelection();
         model.select(4, col1);
         model.selectFirst();
         assertTrue(cells(model), model.isSelected(0, col1));
@@ -441,6 +450,7 @@
     @Test public void selectLastRowInMultipleSelectionRowMode() {
         model.setSelectionMode(SelectionMode.MULTIPLE);
         model.setCellSelectionEnabled(false);
+        model.clearSelection();
         model.select(4);
         model.selectLast();
         assertTrue(cells(model), model.isSelected(tableView.getExpandedItemCount() - 1));
@@ -451,6 +461,7 @@
     @Test public void selectLastRowInMultipleSelectionCellMode() {
         model.setSelectionMode(SelectionMode.MULTIPLE);
         model.setCellSelectionEnabled(true);
+        model.clearSelection();
         model.select(4, col1);
         model.selectLast();
         assertTrue(cells(model), model.isSelected(tableView.getExpandedItemCount() - 1, col1));
@@ -529,13 +540,13 @@
     }
 
     @Test public void focusNextRowImmediately() {
-        assertEquals(new TreeTablePosition(tableView, -1, null), focusModel.getFocusedCell());
+        assertEquals(new TreeTablePosition(tableView, 0, null), focusModel.getFocusedCell());
 
         focusModel.focusNext();
 
-        assertEquals(new TreeTablePosition(tableView, 0, null), focusModel.getFocusedCell());
-        assertTrue(focusedCell(), focusModel.isFocused(0));
-        assertTrue(focusedCell(), focusModel.isFocused(0, null));
+        assertEquals(new TreeTablePosition(tableView, 1, null), focusModel.getFocusedCell());
+        assertTrue(focusedCell(), focusModel.isFocused(1));
+        assertTrue(focusedCell(), focusModel.isFocused(1, null));
     }
 
     @Test public void focusNextRowFromLastRow() {
@@ -638,7 +649,7 @@
         model.setSelectionMode(SelectionMode.MULTIPLE);
         model.setCellSelectionEnabled(true);
 
-        assertTrue(model.getSelectedCells().isEmpty());
+        assertFalse(model.getSelectedCells().isEmpty());
 
         // select from (0,0) to (4,2) -> 5 x 3 cells = 15 cells in total
         model.selectRange(0, col0, 4, col2);
@@ -654,6 +665,7 @@
     @Test public void test_rt33442_changeSelectionModeClearsSelection() {
         model.setSelectionMode(SelectionMode.MULTIPLE);
         model.setCellSelectionEnabled(true);
+        model.clearSelection();
 
         assertTrue(model.getSelectedCells().isEmpty());
 
@@ -664,7 +676,12 @@
         model.setSelectionMode(SelectionMode.SINGLE);
         for (int row = 0; row <= 4; row++) {
             for (int column = 0; column <= 2; column++) {
-                assertFalse(model.isSelected(row, tableView.getVisibleLeafColumn(column)));
+                // the last item will be selected
+                if (row == 4 && column == 2) {
+                    assertTrue(model.isSelected(row, tableView.getVisibleLeafColumn(column)));
+                } else {
+                    assertFalse(model.isSelected(row, tableView.getVisibleLeafColumn(column)));
+                }
             }
         }
     }
@@ -685,15 +702,15 @@
 
         TreeTableColumn name = new TreeTableColumn("Name");
         name.setCellValueFactory(new Callback<TreeTableColumn.CellDataFeatures, ObservableValue>() {
-            @Override
-            public ObservableValue call(TreeTableColumn.CellDataFeatures p) {
+            @Override public ObservableValue call(TreeTableColumn.CellDataFeatures p) {
                 return new ReadOnlyStringWrapper((String)p.getValue().getValue());
             }
         });
 
-        tableView.getColumns().addAll(name);
+        tableView.getColumns().setAll(name);
         model.setSelectionMode(SelectionMode.MULTIPLE);
         model.setCellSelectionEnabled(true);
+        model.clearSelection();
 
         TreeItem item0 = tableView.getTreeItem(1);
         assertEquals("item - 0", item0.getValue());
--- a/modules/controls/src/test/java/javafx/scene/control/TreeTableViewTest.java	Tue Sep 02 15:32:15 2014 +1200
+++ b/modules/controls/src/test/java/javafx/scene/control/TreeTableViewTest.java	Wed Sep 03 12:12:43 2014 +1200
@@ -885,7 +885,7 @@
         installChildren();
         TreeItem<String> element = new TreeItem<String>("I AM A CRAZY RANDOM STRING");
         treeTableView.getSelectionModel().select(element);
-        assertEquals(0, treeTableView.getSelectionModel().getSelectedIndex());
+        assertEquals(-1, treeTableView.getSelectionModel().getSelectedIndex());
         assertSame(element, treeTableView.getSelectionModel().getSelectedItem());
     }
 
@@ -1662,7 +1662,7 @@
         sm.setCellSelectionEnabled(true);
         sm.setSelectionMode(SelectionMode.MULTIPLE);
         
-        assertTrue(sm.getSelectedIndices().isEmpty());
+        assertFalse(sm.getSelectedIndices().isEmpty());
         
         // only (0,0) should be selected, so selected indices should be [0]
         sm.select(0, firstNameCol);
@@ -1712,8 +1712,8 @@
         table.getColumns().addAll(firstNameCol, lastNameCol, emailCol);
         sm.setCellSelectionEnabled(true);
         sm.setSelectionMode(SelectionMode.MULTIPLE);
-        
-        assertTrue(sm.getSelectedItems().isEmpty());
+
+        assertFalse(sm.getSelectedItems().isEmpty());
         
         // only (0,0) should be selected, so selected items should be [p0]
         sm.select(0, firstNameCol);
@@ -3317,8 +3317,8 @@
         // test initial state
         assertEquals(sl.getStage().getScene().getFocusOwner(), focusBtn);
         assertTrue(focusBtn.isFocused());
-        assertEquals(-1, sm.getSelectedIndex());
-        assertNull(sm.getSelectedItem());
+        assertEquals(0, sm.getSelectedIndex());
+        assertNotNull(sm.getSelectedItem());
 
         // move focus to the TreeTableView
         treeView.requestFocus();
@@ -3931,4 +3931,265 @@
         assertEquals(1, sm.getSelectedItems().size());
         assertEquals(rootTwo, sm.getSelectedItems().get(0));
     }
+
+    private TreeTableView<Person> test_rt_38464_createControl() {
+        ObservableList<TreeItem<Person>> persons = FXCollections.observableArrayList(
+                new TreeItem<>(new Person("Jacob", "Smith", "jacob.smith@example.com")),
+                new TreeItem<>(new Person("Isabella", "Johnson", "isabella.johnson@example.com")),
+                new TreeItem<>(new Person("Ethan", "Williams", "ethan.williams@example.com")),
+                new TreeItem<>(new Person("Emma", "Jones", "emma.jones@example.com")),
+                new TreeItem<>(new Person("Michael", "Brown", "michael.brown@example.com")));
+
+        TreeTableView<Person> table = new TreeTableView<>();
+        table.setShowRoot(false);
+
+        TreeItem<Person> root = new TreeItem<>(new Person("Root", null, null));
+        root.setExpanded(true);
+        root.getChildren().setAll(persons);
+        table.setRoot(root);
+
+
+
+        TreeTableColumn firstNameCol = new TreeTableColumn("First Name");
+        firstNameCol.setCellValueFactory(new TreeItemPropertyValueFactory<Person, String>("firstName"));
+
+        TreeTableColumn lastNameCol = new TreeTableColumn("Last Name");
+        lastNameCol.setCellValueFactory(new TreeItemPropertyValueFactory<Person, String>("lastName"));
+
+        table.getColumns().addAll(firstNameCol, lastNameCol);
+
+        return table;
+    }
+
+    @Test public void test_rt_38464_rowSelection_selectFirstRowOnly() {
+        TreeTableView<Person> table = test_rt_38464_createControl();
+        TreeTableView.TreeTableViewSelectionModel<Person> sm = table.getSelectionModel();
+        sm.setCellSelectionEnabled(false);
+        sm.setSelectionMode(SelectionMode.MULTIPLE);
+
+        sm.select(0);
+
+        assertTrue(sm.isSelected(0));
+        assertTrue(sm.isSelected(0, table.getColumns().get(0)));
+        assertTrue(sm.isSelected(0, table.getColumns().get(1)));
+
+        assertEquals(1, sm.getSelectedIndices().size());
+        assertEquals(1, sm.getSelectedItems().size());
+        assertEquals(1, sm.getSelectedCells().size());
+    }
+
+    @Test public void test_rt_38464_rowSelection_selectFirstRowAndThenCallNoOpMethods() {
+        TreeTableView<Person> table = test_rt_38464_createControl();
+        TreeTableView.TreeTableViewSelectionModel<Person> sm = table.getSelectionModel();
+        sm.setCellSelectionEnabled(false);
+        sm.setSelectionMode(SelectionMode.MULTIPLE);
+
+        sm.select(0);               // select first row
+        sm.select(0);               // this should be a no-op
+        sm.select(0, table.getColumns().get(0)); // so should this, as we are in row selection mode
+        sm.select(0, table.getColumns().get(1));  // and same here
+
+        assertTrue(sm.isSelected(0));
+        assertTrue(sm.isSelected(0, table.getColumns().get(0)));
+        assertTrue(sm.isSelected(0, table.getColumns().get(1)));
+
+        assertEquals(1, sm.getSelectedIndices().size());
+        assertEquals(1, sm.getSelectedItems().size());
+        assertEquals(1, sm.getSelectedCells().size());
+    }
+
+
+    @Test public void test_rt_38464_cellSelection_selectFirstRowOnly() {
+        TreeTableView<Person> table = test_rt_38464_createControl();
+        TreeTableView.TreeTableViewSelectionModel<Person> sm = table.getSelectionModel();
+        sm.setCellSelectionEnabled(true);
+        sm.setSelectionMode(SelectionMode.MULTIPLE);
+
+        // select first row. This should be translated into selection of all
+        // cells in this row, but does not result in the row itself being
+        // considered selected.
+        sm.select(0);
+
+        assertFalse(sm.isSelected(0));
+        assertTrue(sm.isSelected(0, table.getColumns().get(0)));
+        assertTrue(sm.isSelected(0, table.getColumns().get(1)));
+
+        assertEquals(1, sm.getSelectedIndices().size());
+        assertEquals(1, sm.getSelectedItems().size());
+        assertEquals(2, sm.getSelectedCells().size());
+    }
+
+    @Test public void test_rt_38464_cellSelection_selectFirstRowAndThenCallNoOpMethods() {
+        TreeTableView<Person> table = test_rt_38464_createControl();
+        TreeTableView.TreeTableViewSelectionModel<Person> sm = table.getSelectionModel();
+        sm.setCellSelectionEnabled(true);
+        sm.setSelectionMode(SelectionMode.MULTIPLE);
+
+        // select first row. This should be translated into selection of all
+        // cells in this row, but does not result in the row itself being
+        // considered selected.
+        sm.select(0);               // select first row
+        sm.select(0, table.getColumns().get(0)); // This line and the next should be no-ops
+        sm.select(0, table.getColumns().get(1));
+
+        assertFalse(sm.isSelected(0));
+        assertTrue(sm.isSelected(0, table.getColumns().get(0)));
+        assertTrue(sm.isSelected(0, table.getColumns().get(1)));
+
+        assertEquals(1, sm.getSelectedIndices().size());
+        assertEquals(1, sm.getSelectedItems().size());
+        assertEquals(2, sm.getSelectedCells().size());
+    }
+
+    @Test public void test_rt38464_selectCellMultipleTimes() {
+        TreeTableView<Person> table = test_rt_38464_createControl();
+        TreeTableView.TreeTableViewSelectionModel<Person> sm = table.getSelectionModel();
+        sm.setCellSelectionEnabled(true);
+        sm.setSelectionMode(SelectionMode.MULTIPLE);
+
+        // default selection when in cell selection mode
+        assertEquals(1, sm.getSelectedCells().size());
+        assertEquals(1, sm.getSelectedItems().size());
+        assertEquals(1, sm.getSelectedIndices().size());
+
+        // select the first cell
+        sm.select(0, table.getColumns().get(0));
+        assertEquals(1, sm.getSelectedCells().size());
+        assertEquals(1, sm.getSelectedItems().size());
+        assertEquals(1, sm.getSelectedIndices().size());
+
+        // select the first cell....again
+        sm.select(0, table.getColumns().get(0));
+        assertEquals(1, sm.getSelectedCells().size());
+        assertEquals(1, sm.getSelectedItems().size());
+        assertEquals(1, sm.getSelectedIndices().size());
+    }
+
+    @Test public void test_rt38464_selectCellThenRow() {
+        TreeTableView<Person> table = test_rt_38464_createControl();
+        TreeTableView.TreeTableViewSelectionModel<Person> sm = table.getSelectionModel();
+        sm.setCellSelectionEnabled(true);
+        sm.setSelectionMode(SelectionMode.MULTIPLE);
+
+        // default selection when in cell selection mode
+        assertEquals(1, sm.getSelectedCells().size());
+        assertEquals(1, sm.getSelectedItems().size());
+        assertEquals(1, sm.getSelectedIndices().size());
+
+        // select the first cell
+        sm.select(0, table.getColumns().get(0));
+        assertEquals(1, sm.getSelectedCells().size());
+        assertEquals(1, sm.getSelectedItems().size());
+        assertEquals(1, sm.getSelectedIndices().size());
+
+        // select the first row
+        sm.select(0);
+
+        // we go to 2 here as all cells in the row become selected. What we do
+        // not expect is to go to 3, as that would mean duplication
+        assertEquals(2, sm.getSelectedCells().size());
+        assertEquals(1, sm.getSelectedItems().size());
+        assertEquals(1, sm.getSelectedIndices().size());
+    }
+
+    @Test public void test_rt38464_selectRowThenCell() {
+        TreeTableView<Person> table = test_rt_38464_createControl();
+        TreeTableView.TreeTableViewSelectionModel<Person> sm = table.getSelectionModel();
+        sm.setCellSelectionEnabled(true);
+        sm.setSelectionMode(SelectionMode.MULTIPLE);
+
+        // default selection when in cell selection mode
+        assertEquals(1, sm.getSelectedCells().size());
+        assertEquals(1, sm.getSelectedItems().size());
+        assertEquals(1, sm.getSelectedIndices().size());
+
+        // select the first row
+        sm.select(0);
+
+        // we go to 2 here as all cells in the row become selected.
+        assertEquals(2, sm.getSelectedCells().size());
+        assertEquals(1, sm.getSelectedItems().size());
+        assertEquals(1, sm.getSelectedIndices().size());
+
+        // select the first cell - no change is expected
+        sm.select(0, table.getColumns().get(0));
+        assertEquals(2, sm.getSelectedCells().size());
+        assertEquals(1, sm.getSelectedItems().size());
+        assertEquals(1, sm.getSelectedIndices().size());
+    }
+
+    @Test public void test_rt38464_selectTests_cellSelection_singleSelection_selectsOneRow() {
+        test_rt38464_selectTests(true, true, true);
+    }
+
+    @Test public void test_rt38464_selectTests_cellSelection_singleSelection_selectsTwoRows() {
+        test_rt38464_selectTests(true, true, false);
+    }
+
+    @Test public void test_rt38464_selectTests_cellSelection_multipleSelection_selectsOneRow() {
+        test_rt38464_selectTests(true, false, true);
+    }
+
+    @Test public void test_rt38464_selectTests_cellSelection_multipleSelection_selectsTwoRows() {
+        test_rt38464_selectTests(true, false, false);
+    }
+
+    @Test public void test_rt38464_selectTests_rowSelection_singleSelection_selectsOneRow() {
+        test_rt38464_selectTests(false, true, true);
+    }
+
+    @Test public void test_rt38464_selectTests_rowSelection_singleSelection_selectsTwoRows() {
+        test_rt38464_selectTests(false, true, false);
+    }
+
+    @Test public void test_rt38464_selectTests_rowSelection_multipleSelection_selectsOneRow() {
+        test_rt38464_selectTests(false, false, true);
+    }
+
+    @Test public void test_rt38464_selectTests_rowSelection_multipleSelection_selectsTwoRows() {
+        test_rt38464_selectTests(false, false, false);
+    }
+
+    private void test_rt38464_selectTests(boolean cellSelection, boolean singleSelection, boolean selectsOneRow) {
+        TreeTableView<Person> table = test_rt_38464_createControl();
+        TreeTableView.TreeTableViewSelectionModel<Person> sm = table.getSelectionModel();
+        sm.setCellSelectionEnabled(cellSelection);
+        sm.setSelectionMode(singleSelection ? SelectionMode.SINGLE : SelectionMode.MULTIPLE);
+
+        // default selection when in cell selection mode
+        assertEquals(1, sm.getSelectedCells().size());
+        assertEquals(1, sm.getSelectedItems().size());
+        assertEquals(1, sm.getSelectedIndices().size());
+
+        if (selectsOneRow) {
+            sm.select(0);
+        } else {
+            // select the first two rows
+            sm.selectIndices(0, 1);
+        }
+
+        final int expectedCells = singleSelection                    ? 1 :
+                                  selectsOneRow   && cellSelection   ? 2 :
+                                  selectsOneRow   && !cellSelection  ? 1 :
+                                  !selectsOneRow  && cellSelection   ? 4 :
+                               /* !selectsOneRow  && !cellSelection */ 2;
+
+        final int expectedItems = singleSelection ? 1 :
+                selectsOneRow   ? 1 : 2;
+
+        assertEquals(expectedCells, sm.getSelectedCells().size());
+        assertEquals(expectedItems, sm.getSelectedItems().size());
+        assertEquals(expectedItems, sm.getSelectedIndices().size());
+
+        // we expect the table column of all selected cells, in this instance,
+        // to be null as we have not explicitly stated a column, nor have we clicked
+        // on a column. The only alternative is to use the first column.
+        for (TreeTablePosition<?,?> tp : sm.getSelectedCells()) {
+            if (cellSelection) {
+                assertNotNull(tp.getTableColumn());
+            } else {
+                assertNull(tp.getTableColumn());
+            }
+        }
+    }
 }
--- a/modules/controls/src/test/java/javafx/scene/control/TreeViewTest.java	Tue Sep 02 15:32:15 2014 +1200
+++ b/modules/controls/src/test/java/javafx/scene/control/TreeViewTest.java	Wed Sep 03 12:12:43 2014 +1200
@@ -193,28 +193,29 @@
     }
 
     @Test public void singleArgConstructorSetsTheStyleClass() {
-        final TreeView<String> b2 = new TreeView<String>(new TreeItem<String>("Hi"));
+        final TreeView<String> b2 = new TreeView<>(new TreeItem<>("Hi"));
         assertStyleClassContains(b2, "tree-view");
     }
 
     @Test public void singleArgConstructorSetsNonNullSelectionModel() {
-        final TreeView<String> b2 = new TreeView<String>(new TreeItem<String>("Hi"));
+        final TreeView<String> b2 = new TreeView<>(new TreeItem<>("Hi"));
         assertNotNull(b2.getSelectionModel());
     }
 
     @Test public void singleArgConstructorAllowsNullItems() {
-        final TreeView<String> b2 = new TreeView<String>(null);
+        final TreeView<String> b2 = new TreeView<>(null);
         assertNull(b2.getRoot());
     }
 
-    @Test public void singleArgConstructor_selectedItemIsNull() {
-        final TreeView<String> b2 = new TreeView<String>(new TreeItem<String>("Hi"));
-        assertNull(b2.getSelectionModel().getSelectedItem());
+    @Test public void singleArgConstructor_selectedItemIsNotNull() {
+        TreeItem<String> hiItem = new TreeItem<>("Hi");
+        final TreeView<String> b2 = new TreeView<>(hiItem);
+        assertEquals(hiItem, b2.getSelectionModel().getSelectedItem());
     }
 
-    @Test public void singleArgConstructor_selectedIndexIsNegativeOne() {
-        final TreeView<String> b2 = new TreeView<String>(new TreeItem<String>("Hi"));
-        assertEquals(-1, b2.getSelectionModel().getSelectedIndex());
+    @Test public void singleArgConstructor_selectedIndexIsZero() {
+        final TreeView<String> b2 = new TreeView<>(new TreeItem<>("Hi"));
+        assertEquals(0, b2.getSelectionModel().getSelectedIndex());
     }
 
     /*********************************************************************
@@ -250,7 +251,7 @@
         installChildren();
         TreeItem<String> element = new TreeItem<String>("I AM A CRAZY RANDOM STRING");
         treeView.getSelectionModel().select(element);
-        assertEquals(0, treeView.getSelectionModel().getSelectedIndex());
+        assertEquals(-1, treeView.getSelectionModel().getSelectedIndex());
         assertSame(element, treeView.getSelectionModel().getSelectedItem());
     }
 
@@ -1734,8 +1735,8 @@
         // test initial state
         assertEquals(sl.getStage().getScene().getFocusOwner(), focusBtn);
         assertTrue(focusBtn.isFocused());
-        assertEquals(-1, sm.getSelectedIndex());
-        assertNull(sm.getSelectedItem());
+        assertEquals(0, sm.getSelectedIndex());
+        assertNotNull(sm.getSelectedItem());
 
         // move focus to the treeview
         treeView.requestFocus();