changeset 3821:30e3bcb6c736

RT-30398: CheckBox cell factory renders check boxes in empty cells
author jgiles
date Fri, 31 May 2013 11:44:05 +1200
parents a92e5afc944b
children 7a327e81151a
files javafx-ui-controls/src/javafx/scene/control/ListCell.java javafx-ui-controls/src/javafx/scene/control/TableCell.java javafx-ui-controls/src/javafx/scene/control/TreeCell.java javafx-ui-controls/src/javafx/scene/control/TreeTableCell.java javafx-ui-controls/test/com/sun/javafx/scene/control/infrastructure/VirtualFlowTestUtils.java javafx-ui-controls/test/javafx/scene/control/ListViewTest.java javafx-ui-controls/test/javafx/scene/control/TableViewTest.java javafx-ui-controls/test/javafx/scene/control/TreeTableViewTest.java javafx-ui-controls/test/javafx/scene/control/TreeViewTest.java
diffstat 9 files changed, 269 insertions(+), 151 deletions(-) [+]
line wrap: on
line diff
--- a/javafx-ui-controls/src/javafx/scene/control/ListCell.java	Fri May 31 10:57:00 2013 +1200
+++ b/javafx-ui-controls/src/javafx/scene/control/ListCell.java	Fri May 31 11:44:05 2013 +1200
@@ -420,9 +420,7 @@
                 updateItem(newValue, false);
             }
         } else {
-            if (! isEmpty()) {
-                updateItem(null, true);
-            }
+            updateItem(null, true);
         }
     }
     
--- a/javafx-ui-controls/src/javafx/scene/control/TableCell.java	Fri May 31 10:57:00 2013 +1200
+++ b/javafx-ui-controls/src/javafx/scene/control/TableCell.java	Fri May 31 11:44:05 2013 +1200
@@ -533,9 +533,7 @@
                 tableColumn == null || 
                 !tableColumn.isVisible()) {
             
-            if (! isEmpty()) {
-                updateItem(null, true);
-            }
+            updateItem(null, true);
             return;
         } else {
             currentObservableValue = tableColumn.getCellObservableValue(index);
--- a/javafx-ui-controls/src/javafx/scene/control/TreeCell.java	Fri May 31 10:57:00 2013 +1200
+++ b/javafx-ui-controls/src/javafx/scene/control/TreeCell.java	Fri May 31 11:44:05 2013 +1200
@@ -470,10 +470,8 @@
                 updateItem(newValue, false);
             }
         } else {
-            if (! isEmpty()) {
-                updateTreeItem(null);
-                updateItem(null, true);
-            }
+            updateTreeItem(null);
+            updateItem(null, true);
         }
     }
 
--- a/javafx-ui-controls/src/javafx/scene/control/TreeTableCell.java	Fri May 31 10:57:00 2013 +1200
+++ b/javafx-ui-controls/src/javafx/scene/control/TreeTableCell.java	Fri May 31 11:44:05 2013 +1200
@@ -503,9 +503,7 @@
                 !tableColumn.isVisible() ||
                 tableView.getRoot() == null) {
             
-            if (! isEmpty()) {
-                updateItem(null, true);
-            }
+            updateItem(null, true);
             return;
         } else {
             currentObservableValue = tableColumn.getCellObservableValue(index);
--- a/javafx-ui-controls/test/com/sun/javafx/scene/control/infrastructure/VirtualFlowTestUtils.java	Fri May 31 10:57:00 2013 +1200
+++ b/javafx-ui-controls/test/com/sun/javafx/scene/control/infrastructure/VirtualFlowTestUtils.java	Fri May 31 11:44:05 2013 +1200
@@ -49,7 +49,7 @@
 import com.sun.javafx.tk.Toolkit;
 
 public class VirtualFlowTestUtils {
-    
+
     public static void assertListContainsItemsInOrder(final List items, final Object... expected) {
         assertEquals(expected.length, items.size());
         for (int i = 0; i < expected.length; i++) {
@@ -57,10 +57,10 @@
             assertEquals(expected[i], item);
         }
     }
-    
+
     public static void clickOnRow(final Control control, int row, KeyModifier... modifiers) {
         IndexedCell cell = VirtualFlowTestUtils.getCell(control, row);
-        
+
         if ((cell instanceof TableRow) || (cell instanceof TreeTableRow)) {
             for (Node n : cell.getChildrenUnmodifiable()) {
                 if (! (n instanceof IndexedCell)) {
@@ -74,27 +74,50 @@
             MouseEventFirer.fireMousePressAndRelease(cell, modifiers);
         }
     }
-    
+
     public static void assertRowsEmpty(final Control control, final int startRow, final int endRow) {
         assertRows(control, startRow, endRow, true);
     }
-    
+
     public static void assertRowsNotEmpty(final Control control, final int startRow, final int endRow) {
         assertRows(control, startRow, endRow, false);
     }
-    
+
     public static void assertCellEmpty(IndexedCell cell) {
-        final String text = cell.getText();
-//        System.out.println("assertCellEmpty: " + cell.getIndex() + " : " + text);
-        assertTrue("Expected null, found '" + text + "'", text == null || text.isEmpty());
+        if (cell instanceof TableRow || cell instanceof TreeTableRow) {
+            for (Node n : cell.getChildrenUnmodifiable()) {
+                if (! (n instanceof IndexedCell)) {
+                    continue;
+                }
+                IndexedCell<?> childCell = (IndexedCell<?>)n;
+                assertCellEmpty(childCell);
+            }
+        } else {
+            final String text = cell.getText();
+            assertTrue("Expected null, found '" + text + "'", text == null || text.isEmpty());
+
+            final Node graphic = cell.getGraphic();
+            assertTrue("Expected null graphic, found " + graphic, graphic == null);
+        }
     }
-    
+
     public static void assertCellNotEmpty(IndexedCell cell) {
-        final String text = cell.getText();
-//        System.out.println("assertCellNotEmpty: " + cell.getIndex() + " : " + text);
-        assertTrue("Expected a non-null, found '" + text + "'", text != null && ! text.isEmpty());
+        if (cell instanceof TableRow || cell instanceof TreeTableRow) {
+            for (Node n : cell.getChildrenUnmodifiable()) {
+                if (! (n instanceof IndexedCell)) {
+                    continue;
+                }
+                IndexedCell<?> childCell = (IndexedCell<?>)n;
+                assertCellNotEmpty(childCell);
+            }
+        } else {
+            final String text = cell.getText();
+            final Node graphic = cell.getGraphic();
+            assertTrue("Expected a non-null text or graphic property",
+                       (text != null && ! text.isEmpty()) || graphic != null);
+        }
     }
-    
+
     private static void assertRows(final Control control, final int startRow, final int endRow, final boolean expectEmpty) {
         Callback<IndexedCell<?>, Void> callback = new Callback<IndexedCell<?>, Void>() {
             @Override public Void call(IndexedCell<?> indexedCell) {
@@ -112,7 +135,7 @@
                         assertCellNotEmpty(childCell);
                     }
                 }
-                
+
                 if (! hasChildrenCell) {
                     if (expectEmpty) {
                         assertCellEmpty(indexedCell);
@@ -123,17 +146,17 @@
                 return null;
             }
         };
-        
+
         assertCallback(control, startRow, endRow, callback);
     }
-    
+
     public static void assertCellTextEquals(final Control control, final int index, final String... expected) {
         if (expected == null || expected.length == 0) return;
-        
+
         Callback<IndexedCell<?>, Void> callback = new Callback<IndexedCell<?>, Void>() {
             @Override public Void call(IndexedCell<?> indexedCell) {
                 if (indexedCell.getIndex() != index) return null;
-        
+
                 if (expected.length == 1) {
                     assertEquals(expected[0], indexedCell.getText());
                 } else {
@@ -145,7 +168,7 @@
                             jump++;
                             continue;
                         }
-                        
+
                         text = ((IndexedCell) childNode).getText();
                         assertEquals(expected[i], text);
                     }
@@ -153,24 +176,24 @@
                 return null;
             }
         };
-        
+
         assertCallback(control, index, index + 1, callback);
     }
-    
+
     public static void assertTableCellTextEquals(final Control control, final int row, final int column, final String expected) {
         Callback<IndexedCell<?>, Void> callback = new Callback<IndexedCell<?>, Void>() {
             @Override public Void call(IndexedCell<?> indexedCell) {
                 if (indexedCell.getIndex() != row) return null;
-                
+
                 IndexedCell cell = (IndexedCell) indexedCell.getChildrenUnmodifiable().get(column);
                 assertEquals(expected, cell.getText());
                 return null;
             }
         };
-        
+
         assertCallback(control, row, row + 1, callback);
     }
-    
+
     // used by TreeView / TreeTableView to ensure the correct indentation
     // (although note that it has only been developed so far for TreeView)
     public static void assertLayoutX(final Control control, final int startRow, final int endRow, final double expectedLayoutX) {
@@ -191,42 +214,42 @@
                 return null;
             }
         };
-        
+
         assertCallback(control, startRow, endRow, callback);
     }
-    
+
     public static int getCellCount(final Control control) {
         return getVirtualFlow(control).getCellCount();
     }
-    
+
     public static IndexedCell getCell(final Control control, final int index) {
         return getVirtualFlow(control).getCell(index);
     }
-    
+
     public static void assertCallback(final Control control, final int startRow, final int endRow, final Callback<IndexedCell<?>, Void> callback) {
         VirtualFlow<?> flow = getVirtualFlow(control);
-        
-//        Region clippedContainer = (Region) flow.getChildrenUnmodifiable().get(0);
-//        Group sheet = (Group) clippedContainer.getChildrenUnmodifiable().get(0);
-        
-//        final int sheetSize = sheet.getChildren().size();
+
+        //        Region clippedContainer = (Region) flow.getChildrenUnmodifiable().get(0);
+        //        Group sheet = (Group) clippedContainer.getChildrenUnmodifiable().get(0);
+
+        //        final int sheetSize = sheet.getChildren().size();
         final int sheetSize = flow.getCellCount();
         final int end = endRow == -1 ? sheetSize : Math.min(endRow, sheetSize);
         for (int row = startRow; row < end; row++) {
             // old approach:
             // callback.call((IndexedCell<?>)sheet.getChildren().get(row));
-            
+
             // new approach:
             IndexedCell cell = flow.getCell(row);
-//            System.out.println("cell index: " + cell.getIndex());
+            //            System.out.println("cell index: " + cell.getIndex());
             callback.call(cell);
         }
     }
-    
+
     public static void assertCellCount(final Control control, final int expected) {
         assertEquals(getVirtualFlow(control).getCellCount(), expected);
     }
-    
+
     public static VirtualFlow<?> getVirtualFlow(Control control) {
         Group group = new Group();
         Scene scene = new Scene(group);
@@ -237,23 +260,23 @@
         group.getChildren().setAll(control);
         stage.show();
 
-//        Toolkit.getToolkit().firePulse();
-        
+        //        Toolkit.getToolkit().firePulse();
+
         VirtualFlow<?> flow;
         if (control instanceof ComboBox) {
             final ComboBox cb = (ComboBox) control;
             final ComboBoxListViewSkin skin = (ComboBoxListViewSkin) cb.getSkin();
             control = skin.getListView();
         }
-        
+
         flow = (VirtualFlow<?>)control.lookup("#virtual-flow");
-        
+
         stage.close();
         stage = null;
-        
+
         return flow;
     }
-    
+
     public static VirtualScrollBar getVirtualFlowVerticalScrollbar(final Control control) {
         VirtualFlow<?> flow = getVirtualFlow(control);
         VirtualScrollBar scrollBar = null;
@@ -264,8 +287,8 @@
                 }
             }
         }
-        
-//        Toolkit.getToolkit().firePulse();
+
+        //        Toolkit.getToolkit().firePulse();
         return scrollBar;
     }
 }
--- a/javafx-ui-controls/test/javafx/scene/control/ListViewTest.java	Fri May 31 10:57:00 2013 +1200
+++ b/javafx-ui-controls/test/javafx/scene/control/ListViewTest.java	Fri May 31 11:44:05 2013 +1200
@@ -37,6 +37,7 @@
 import java.util.Arrays;
 
 import javafx.beans.property.ObjectProperty;
+import javafx.beans.property.ReadOnlyBooleanWrapper;
 import javafx.beans.property.SimpleObjectProperty;
 import javafx.beans.value.ChangeListener;
 import javafx.beans.value.ObservableValue;
@@ -44,7 +45,9 @@
 import javafx.collections.ObservableList;
 import javafx.geometry.Orientation;
 import javafx.scene.Node;
+import javafx.scene.control.cell.CheckBoxListCell;
 import javafx.scene.layout.StackPane;
+import javafx.util.Callback;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -60,42 +63,42 @@
 public class ListViewTest {
     private ListView<String> listView;
     private MultipleSelectionModel<String> sm;
-    
+
     @Before public void setup() {
         listView = new ListView<String>();
         sm = listView.getSelectionModel();
     }
-    
-    
+
+
     /*********************************************************************
      * Tests for the constructors                                        *
      ********************************************************************/
-    
+
     @Test public void noArgConstructorSetsTheStyleClass() {
         assertStyleClassContains(listView, "list-view");
     }
-    
+
     @Test public void noArgConstructorSetsNonNullSelectionModel() {
         assertNotNull(sm);
     }
-    
+
     @Test public void noArgConstructorSetsNonNullItems() {
         assertNotNull(listView.getItems());
     }
-    
+
     @Test public void noArgConstructor_selectedItemIsNull() {
         assertNull(sm.getSelectedItem());
     }
-    
+
     @Test public void noArgConstructor_selectedIndexIsNegativeOne() {
         assertEquals(-1, sm.getSelectedIndex());
     }
-    
+
     @Test public void singleArgConstructorSetsTheStyleClass() {
         final ListView<String> b2 = new ListView<String>(FXCollections.observableArrayList("Hi"));
         assertStyleClassContains(b2, "list-view");
     }
-    
+
     @Test public void singleArgConstructorSetsNonNullSelectionModel() {
         final ListView<String> b2 = new ListView<String>(FXCollections.observableArrayList("Hi"));
         assertNotNull(b2.getSelectionModel());
@@ -105,27 +108,27 @@
         final ListView<String> b2 = new ListView<String>(null);
         assertNull(b2.getItems());
     }
-    
+
     @Test public void singleArgConstructorTakesItems() {
         ObservableList<String> items = FXCollections.observableArrayList("Hi");
         final ListView<String> b2 = new ListView<String>(items);
         assertSame(items, b2.getItems());
     }
-    
+
     @Test public void singleArgConstructor_selectedItemIsNull() {
         final ListView<String> b2 = new ListView<String>(FXCollections.observableArrayList("Hi"));
         assertNull(b2.getSelectionModel().getSelectedItem());
     }
-    
+
     @Test public void singleArgConstructor_selectedIndexIsNegativeOne() {
         final ListView<String> b2 = new ListView<String>(FXCollections.observableArrayList("Hi"));
         assertEquals(-1, b2.getSelectionModel().getSelectedIndex());
     }
-    
+
     /*********************************************************************
      * Tests for selection model                                         *
      ********************************************************************/
-    
+
     @Test public void selectionModelCanBeNull() {
         listView.setSelectionModel(null);
         assertNull(listView.getSelectionModel());
@@ -143,14 +146,14 @@
         listView.setSelectionModel(sm);
         assertSame(sm, sm);
     }
-    
+
     @Test public void canSetSelectedItemToAnItemEvenWhenThereAreNoItems() {
         final String randomString = new String("I AM A CRAZY RANDOM STRING");
         sm.select(randomString);
         assertEquals(-1, sm.getSelectedIndex());
         assertSame(randomString, sm.getSelectedItem());
     }
-        
+
     @Test public void canSetSelectedItemToAnItemNotInTheDataModel() {
         listView.getItems().addAll("Apple", "Orange", "Banana");
         final String randomString = new String("I AM A CRAZY RANDOM STRING");
@@ -158,21 +161,21 @@
         assertEquals(-1, sm.getSelectedIndex());
         assertSame(randomString, sm.getSelectedItem());
     }
-        
+
     @Test public void settingTheSelectedItemToAnItemInItemsResultsInTheCorrectSelectedIndex() {
         listView.getItems().addAll("Apple", "Orange", "Banana");
         sm.select("Orange");
         assertEquals(1, sm.getSelectedIndex());
         assertSame("Orange", sm.getSelectedItem());
     }
-    
+
     @Test public void settingTheSelectedItemToANonexistantItemAndThenSettingItemsWhichContainsItResultsInCorrectSelectedIndex() {
         sm.select("Orange");
         listView.getItems().addAll("Apple", "Orange", "Banana");
         assertEquals(1, sm.getSelectedIndex());
         assertSame("Orange", sm.getSelectedItem());
     }
-    
+
     @Test public void ensureSelectionClearsWhenAllItemsAreRemoved_selectIndex0() {
         listView.getItems().addAll("Apple", "Orange", "Banana");
         sm.select(0);
@@ -180,7 +183,7 @@
         assertEquals(-1, sm.getSelectedIndex());
         assertEquals(null, sm.getSelectedItem());
     }
-    
+
     @Test public void ensureSelectionClearsWhenAllItemsAreRemoved_selectIndex2() {
         listView.getItems().addAll("Apple", "Orange", "Banana");
         sm.select(2);
@@ -188,73 +191,73 @@
         assertEquals(-1, sm.getSelectedIndex());
         assertEquals(null, sm.getSelectedItem());
     }
-    
+
     @Test public void ensureSelectedItemRemainsAccurateWhenItemsAreCleared() {
         listView.getItems().addAll("Apple", "Orange", "Banana");
         sm.select(2);
         listView.getItems().clear();
         assertNull(sm.getSelectedItem());
         assertEquals(-1, sm.getSelectedIndex());
-        
+
         listView.getItems().addAll("Kiwifruit", "Mandarin", "Pineapple");
         sm.select(2);
         assertEquals("Pineapple", sm.getSelectedItem());
     }
-    
+
     @Test public void ensureSelectionShiftsDownWhenOneNewItemIsAdded() {
         listView.getItems().addAll("Apple", "Orange", "Banana");
         sm.select(1);
         assertEquals(1, sm.getSelectedIndex());
         assertEquals("Orange", sm.getSelectedItem());
-        
+
         listView.getItems().add(0, "Kiwifruit");
         assertEquals(2, sm.getSelectedIndex());
         assertEquals("Orange", sm.getSelectedItem());
     }
-    
+
     @Test public void ensureSelectionShiftsDownWhenMultipleNewItemAreAdded() {
         listView.getItems().addAll("Apple", "Orange", "Banana");
         sm.select(1);
         assertEquals(1, sm.getSelectedIndex());
         assertEquals("Orange", sm.getSelectedItem());
-        
+
         listView.getItems().addAll(0, Arrays.asList("Kiwifruit", "Pineapple", "Mandarin"));
         assertEquals("Orange", sm.getSelectedItem());
         assertEquals(4, sm.getSelectedIndex());
     }
-    
+
     @Test public void ensureSelectionShiftsUpWhenOneItemIsRemoved() {
         listView.getItems().addAll("Apple", "Orange", "Banana");
         sm.select(1);
         assertEquals(1, sm.getSelectedIndex());
         assertEquals("Orange", sm.getSelectedItem());
-        
+
         listView.getItems().remove("Apple");
         assertEquals(0, sm.getSelectedIndex());
         assertEquals("Orange", sm.getSelectedItem());
     }
-    
+
     @Test public void ensureSelectionShiftsUpWheMultipleItemsAreRemoved() {
         listView.getItems().addAll("Apple", "Orange", "Banana");
         sm.select(2);
         assertEquals(2, sm.getSelectedIndex());
         assertEquals("Banana", sm.getSelectedItem());
-        
+
         listView.getItems().removeAll(Arrays.asList("Apple", "Orange"));
         assertEquals(0, sm.getSelectedIndex());
         assertEquals("Banana", sm.getSelectedItem());
     }
-    
+
     @Test public void ensureSelectionIsCorrectWhenItemsChange() {
         listView.setItems(FXCollections.observableArrayList("Item 1"));
         sm.select(0);
         assertEquals("Item 1", sm.getSelectedItem());
-        
+
         listView.setItems(FXCollections.observableArrayList("Item 2"));
         assertEquals(-1, sm.getSelectedIndex());
         assertEquals(null, sm.getSelectedItem());
     }
-    
+
     @Test public void test_rt15793() {
         // ListView selectedIndex is 0 although the items list is empty
         final ListView lv = new ListView();
@@ -266,18 +269,18 @@
         list.remove(0);
         assertEquals(-1, lv.getSelectionModel().getSelectedIndex());
     }
-    
+
     @Test public void test_rt17522_focusShouldMoveWhenItemAddedAtFocusIndex() {
         final ListView lv = new ListView();
         FocusModel fm = lv.getFocusModel();
         lv.getItems().add("row1");
         fm.focus(0);
         assertTrue(fm.isFocused(0));
-        
+
         lv.getItems().add(0, "row0");
         assertTrue(fm.isFocused(1));
     }
-    
+
     @Test public void test_rt17522_focusShouldMoveWhenItemAddedBeforeFocusIndex() {
         final ListView lv = new ListView();
         FocusModel fm = lv.getFocusModel();
@@ -285,13 +288,13 @@
         fm.focus(1);
         assertTrue(fm.isFocused(1));
         assertEquals("row2", fm.getFocusedItem());
-        
+
         lv.getItems().add(1, "row0");
         assertTrue(fm.isFocused(2));
         assertEquals("row2", fm.getFocusedItem());
         assertFalse(fm.isFocused(1));
     }
-    
+
     @Test public void test_rt17522_focusShouldNotMoveWhenItemAddedAfterFocusIndex() {
         final ListView lv = new ListView();
         FocusModel fm = lv.getFocusModel();
@@ -299,25 +302,25 @@
         fm.focus(0);
         assertTrue(fm.isFocused(0));
         assertEquals("row1", fm.getFocusedItem());
-        
+
         lv.getItems().add(1, "row2");
         assertTrue(fm.isFocused(0));
         assertEquals("row1", fm.getFocusedItem());
         assertFalse(fm.isFocused(1));
     }
-    
+
     @Test public void test_rt17522_focusShouldBeResetWhenFocusedItemIsRemoved() {
         final ListView lv = new ListView();
         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());
     }
-    
+
     @Test public void test_rt17522_focusShouldMoveWhenItemRemovedBeforeFocusIndex() {
         final ListView lv = new ListView();
         FocusModel fm = lv.getFocusModel();
@@ -325,12 +328,12 @@
         fm.focus(1);
         assertTrue(fm.isFocused(1));
         assertEquals("row2", fm.getFocusedItem());
-        
+
         lv.getItems().remove("row1");
         assertTrue(fm.isFocused(0));
         assertEquals("row2", fm.getFocusedItem());
     }
-    
+
     @Test public void test_rt17522_focusShouldNotMoveWhenItemRemovedAfterFocusIndex() {
         final ListView lv = new ListView();
         FocusModel fm = lv.getFocusModel();
@@ -338,12 +341,12 @@
         fm.focus(0);
         assertTrue(fm.isFocused(0));
         assertEquals("row1", fm.getFocusedItem());
-        
+
         lv.getItems().remove("row2");
         assertTrue(fm.isFocused(0));
         assertEquals("row1", fm.getFocusedItem());
     }
-    
+
     @Test public void test_rt18385() {
         listView.getItems().addAll("row1", "row2", "row3");
         sm.select(1);
@@ -351,47 +354,47 @@
         assertEquals(1, sm.getSelectedIndices().size());
         assertEquals(1, sm.getSelectedItems().size());
     }
-    
+
     @Test public void test_rt18339_onlyEditWhenListViewIsEditable_editableIsFalse() {
         listView.setEditable(false);
         listView.edit(1);
         assertEquals(-1, listView.getEditingIndex());
     }
-    
+
     @Test public void test_rt18339_onlyEditWhenListViewIsEditable_editableIsTrue() {
         listView.setEditable(true);
         listView.edit(1);
         assertEquals(1, listView.getEditingIndex());
     }
-    
+
     @Test public void test_rt14451() {
         listView.getItems().addAll("Apple", "Orange", "Banana");
         sm.setSelectionMode(SelectionMode.MULTIPLE);
         sm.selectRange(0, 2); // select from 0 (inclusive) to 2 (exclusive)
         assertEquals(2, sm.getSelectedIndices().size());
     }
-    
+
     private int rt_18969_hitCount = 0;
     @Test public void test_rt18969() {
         rt_18969_hitCount = 0;
         ObservableList<String> emptyModel = FXCollections.observableArrayList();
         listView.setItems(emptyModel);
         assertTrue(listView.getItems().isEmpty());
-        
+
         sm.selectedItemProperty().addListener(new ChangeListener<String>() {
             @Override public void changed(ObservableValue<? extends String> observable, String oldValue, final String newValue) {
                 rt_18969_hitCount++;
             }
         });
-        
+
         ObservableList<String> mod = FXCollections.observableArrayList();
         mod.add(System.currentTimeMillis()+"");
         listView.getItems().setAll(mod);
-        
+
         sm.select(0);
         assertTrue(sm.isSelected(0));
         assertEquals(1, rt_18969_hitCount);
-        
+
         // sleep for 100ms so that the currentTimeMillis is guaranteed to be
         // a different value than the first one
         try {
@@ -399,76 +402,76 @@
         } catch (InterruptedException ex) {
             ex.printStackTrace();
         }
-        
+
         // the list is totally changing (it is being cleared), so we should 
         // be nulling out the selection model state
         mod = FXCollections.observableArrayList();
         mod.add(System.currentTimeMillis()+"");
         listView.getItems().setAll(mod);
-        
+
         // it should be two, as there is no null event in between (although there
         // used to be, so the test used to be for three hits)
         assertEquals(2, rt_18969_hitCount);
     }
-    
+
     @Test public void test_rt21586() {
         listView.getItems().setAll("Apple", "Orange", "Banana");
         listView.getSelectionModel().select(1);
         assertEquals(1, listView.getSelectionModel().getSelectedIndex());
         assertEquals("Orange", listView.getSelectionModel().getSelectedItem());
-        
+
         listView.getItems().setAll("Kiwifruit", "Pineapple", "Grape");
         assertEquals(-1, listView.getSelectionModel().getSelectedIndex());
         assertNull(listView.getSelectionModel().getSelectedItem());
     }
-    
+
     @Test public void test_rt27820_1() {
         listView.getItems().setAll("Apple", "Orange");
         listView.getSelectionModel().select(0);
         assertEquals(1, listView.getSelectionModel().getSelectedItems().size());
         assertEquals("Apple", listView.getSelectionModel().getSelectedItem());
-        
+
         listView.getItems().clear();
         assertEquals(0, listView.getSelectionModel().getSelectedItems().size());
         assertNull(listView.getSelectionModel().getSelectedItem());
     }
-    
+
     @Test public void test_rt27820_2() {
         listView.getItems().setAll("Apple", "Orange");
         listView.getSelectionModel().select(1);
         assertEquals(1, listView.getSelectionModel().getSelectedItems().size());
         assertEquals("Orange", listView.getSelectionModel().getSelectedItem());
-        
+
         listView.getItems().clear();
         assertEquals(0, listView.getSelectionModel().getSelectedItems().size());
         assertNull(listView.getSelectionModel().getSelectedItem());
     }
-    
+
     @Test public void test_rt28534() {
         ListView<Person> list = new ListView<Person>();
         list.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")));
-        
+                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")));
+
         VirtualFlowTestUtils.assertRowsNotEmpty(list, 0, 5); // rows 0 - 5 should be filled
         VirtualFlowTestUtils.assertRowsEmpty(list, 5, -1); // rows 5+ should be empty
-        
+
         // now we replace the data and expect the cells that have no data
         // to be empty
         list.setItems(FXCollections.observableArrayList(
-            new Person("*_*Emma", "Jones", "emma.jones@example.com"),
-            new Person("_Michael", "Brown", "michael.brown@example.com")));
-        
+                new Person("*_*Emma", "Jones", "emma.jones@example.com"),
+                new Person("_Michael", "Brown", "michael.brown@example.com")));
+
         VirtualFlowTestUtils.assertRowsNotEmpty(list, 0, 2); // rows 0 - 2 should be filled
         VirtualFlowTestUtils.assertRowsEmpty(list, 2, -1); // rows 2+ should be empty
     }
-    
+
     @Test public void test_rt22463() {
         final ListView<RT_22463_Person> list = new ListView<RT_22463_Person>();
-        
+
         // before the change things display fine
         RT_22463_Person p1 = new RT_22463_Person();
         p1.setId(1l);
@@ -479,7 +482,7 @@
         list.setItems(FXCollections.observableArrayList(p1, p2));
         VirtualFlowTestUtils.assertCellTextEquals(list, 0, "name1");
         VirtualFlowTestUtils.assertCellTextEquals(list, 1, "name2");
-        
+
         // now we change the persons but they are still equal as the ID's don't
         // change - but the items list is cleared so the cells should update
         RT_22463_Person new_p1 = new RT_22463_Person();
@@ -493,31 +496,31 @@
         VirtualFlowTestUtils.assertCellTextEquals(list, 0, "updated name1");
         VirtualFlowTestUtils.assertCellTextEquals(list, 1, "updated name2");
     }
-    
+
     @Test public void test_rt28637() {
         ObservableList<String> items = FXCollections.observableArrayList("String1", "String2", "String3", "String4");
-        
+
         final ListView<String> listView = new ListView<String>();
         listView.setItems(items);
-        
+
         listView.getSelectionModel().select(0);
         assertEquals("String1", listView.getSelectionModel().getSelectedItem());
         assertEquals("String1", listView.getSelectionModel().getSelectedItems().get(0));
         assertEquals(0, listView.getSelectionModel().getSelectedIndex());
-        
+
         items.remove(listView.getSelectionModel().getSelectedItem());
         assertEquals("String2", listView.getSelectionModel().getSelectedItem());
         assertEquals("String2", listView.getSelectionModel().getSelectedItems().get(0));
         assertEquals(0, listView.getSelectionModel().getSelectedIndex());
     }
-    
+
     @Test public void test_rt28819_1() {
         ObservableList<String> emptyModel = FXCollections.observableArrayList();
-        
+
         final ListView<String> listView = new ListView<String>();
         listView.setItems(emptyModel);
         VirtualFlowTestUtils.assertRowsEmpty(listView, 0, 5);
-        
+
         ObservableList<String> mod = FXCollections.observableArrayList();
         String value = System.currentTimeMillis()+"";
         mod.add(value);
@@ -525,14 +528,14 @@
         VirtualFlowTestUtils.assertCellCount(listView, 1);
         VirtualFlowTestUtils.assertCellTextEquals(listView, 0, value);
     }
-    
+
     @Test public void test_rt28819_2() {
         ObservableList<String> emptyModel = FXCollections.observableArrayList();
-        
+
         final ListView<String> listView = new ListView<String>();
         listView.setItems(emptyModel);
         VirtualFlowTestUtils.assertRowsEmpty(listView, 0, 5);
-        
+
         ObservableList<String> mod1 = FXCollections.observableArrayList();
         String value1 = System.currentTimeMillis()+"";
         mod1.add(value1);
@@ -540,7 +543,7 @@
         VirtualFlowTestUtils.assertCellCount(listView, 1);
         VirtualFlowTestUtils.assertCellTextEquals(listView, 0, value1);
     }
-    
+
     @Test public void test_rt29390() {
         ObservableList<String> items = FXCollections.observableArrayList(
                 "String1", "String2", "String3", "String4",
@@ -548,21 +551,42 @@
                 "String1", "String2", "String3", "String4",
                 "String1", "String2", "String3", "String4"
         );
-        
+
         final ListView<String> listView = new ListView<String>(items);
         listView.setMaxHeight(50);
         listView.setPrefHeight(50);
-        
+
         // we want the vertical scrollbar
         VirtualScrollBar scrollBar = VirtualFlowTestUtils.getVirtualFlowVerticalScrollbar(listView);
-        
+
         assertNotNull(scrollBar);
         assertTrue(scrollBar.isVisible());
         assertTrue(scrollBar.getVisibleAmount() > 0.0);
         assertTrue(scrollBar.getVisibleAmount() < 1.0);
-        
+
         // this next test is likely to be brittle, but we'll see...If it is the
         // cause of failure then it can be commented out
         assertEquals(0.125, scrollBar.getVisibleAmount(), 0.0);
     }
+
+    @Test public void test_rt30400() {
+        // create a listview that'll render cells using the check box cell factory
+        ObservableList<String> items = FXCollections.observableArrayList("String1");
+        final ListView<String> listView = new ListView<String>(items);
+        listView.setMinHeight(100);
+        listView.setPrefHeight(100);
+        listView.setCellFactory(CheckBoxListCell.forListView(new Callback<String, ObservableValue<Boolean>>() {
+            public javafx.beans.value.ObservableValue<Boolean> call(String param) {
+                return new ReadOnlyBooleanWrapper(true);
+            }
+        }));
+
+        // because only the first row has data, all other rows should be 
+        // empty (and not contain check boxes - we just check the first four here)
+        VirtualFlowTestUtils.assertRowsNotEmpty(listView, 0, 1);
+        VirtualFlowTestUtils.assertCellNotEmpty(VirtualFlowTestUtils.getCell(listView, 0));
+        VirtualFlowTestUtils.assertCellEmpty(VirtualFlowTestUtils.getCell(listView, 1));
+        VirtualFlowTestUtils.assertCellEmpty(VirtualFlowTestUtils.getCell(listView, 2));
+        VirtualFlowTestUtils.assertCellEmpty(VirtualFlowTestUtils.getCell(listView, 3));
+    }
 }
--- a/javafx-ui-controls/test/javafx/scene/control/TableViewTest.java	Fri May 31 10:57:00 2013 +1200
+++ b/javafx-ui-controls/test/javafx/scene/control/TableViewTest.java	Fri May 31 11:44:05 2013 +1200
@@ -40,12 +40,14 @@
 import java.util.Random;
 
 import javafx.beans.property.ObjectProperty;
+import javafx.beans.property.ReadOnlyBooleanWrapper;
 import javafx.beans.property.ReadOnlyObjectWrapper;
 import javafx.beans.property.SimpleObjectProperty;
 import javafx.beans.value.ObservableValue;
 import javafx.collections.FXCollections;
 import javafx.collections.ObservableList;
 import javafx.event.EventHandler;
+import javafx.scene.control.cell.CheckBoxTableCell;
 import javafx.scene.control.cell.PropertyValueFactory;
 import javafx.util.Callback;
 
@@ -1296,4 +1298,31 @@
         // cause of failure then it can be commented out
         assertEquals(0.125, scrollBar.getVisibleAmount(), 0.0);
     }
+
+    @Test public void test_rt30400() {
+        // create a listview that'll render cells using the check box cell factory
+        final TableView<Person> tableView = new TableView<Person>();
+        tableView.setMinHeight(100);
+        tableView.setPrefHeight(100);
+        tableView.setItems(FXCollections.observableArrayList(
+                new Person("Jacob", "Smith", "jacob.smith@example.com")
+        ));
+
+        TableColumn firstNameCol = new TableColumn("First Name");
+        firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName"));
+        firstNameCol.setCellFactory(CheckBoxTableCell.forTableColumn(new Callback<Integer, ObservableValue<Boolean>>() {
+            public javafx.beans.value.ObservableValue<Boolean> call(Integer param) {
+                return new ReadOnlyBooleanWrapper(true);
+            }
+        }));
+        tableView.getColumns().add(firstNameCol);
+
+        // because only the first row has data, all other rows should be
+        // empty (and not contain check boxes - we just check the first four here)
+        VirtualFlowTestUtils.assertRowsNotEmpty(tableView, 0, 1);
+        VirtualFlowTestUtils.assertCellNotEmpty(VirtualFlowTestUtils.getCell(tableView, 0));
+        VirtualFlowTestUtils.assertCellEmpty(VirtualFlowTestUtils.getCell(tableView, 1));
+        VirtualFlowTestUtils.assertCellEmpty(VirtualFlowTestUtils.getCell(tableView, 2));
+        VirtualFlowTestUtils.assertCellEmpty(VirtualFlowTestUtils.getCell(tableView, 3));
+    }
 }
--- a/javafx-ui-controls/test/javafx/scene/control/TreeTableViewTest.java	Fri May 31 10:57:00 2013 +1200
+++ b/javafx-ui-controls/test/javafx/scene/control/TreeTableViewTest.java	Fri May 31 11:44:05 2013 +1200
@@ -44,6 +44,7 @@
 import javafx.beans.InvalidationListener;
 import javafx.beans.Observable;
 import javafx.beans.property.ObjectProperty;
+import javafx.beans.property.ReadOnlyBooleanWrapper;
 import javafx.beans.property.ReadOnlyObjectWrapper;
 import javafx.beans.property.ReadOnlyStringWrapper;
 import javafx.beans.property.SimpleObjectProperty;
@@ -56,6 +57,7 @@
 import javafx.scene.Node;
 import javafx.scene.Scene;
 import javafx.scene.control.TreeTableView.TreeTableViewFocusModel;
+import javafx.scene.control.cell.CheckBoxTreeTableCell;
 import javafx.scene.control.cell.PropertyValueFactory;
 import javafx.scene.control.cell.TreeItemPropertyValueFactory;
 import javafx.scene.layout.HBox;
@@ -2034,4 +2036,29 @@
         assertTrue(treeTableView.getFocusModel().isFocused(10));
         assertEquals(3, sm.getSelectedIndices().size());
     }
+
+    @Test public void test_rt30400() {
+        // create a treetableview that'll render cells using the check box cell factory
+        TreeItem<String> rootItem = new TreeItem<>("root");
+        final TreeTableView<String> tableView = new TreeTableView<String>(rootItem);
+        tableView.setMinHeight(100);
+        tableView.setPrefHeight(100);
+
+        TreeTableColumn firstNameCol = new TreeTableColumn("First Name");
+        firstNameCol.setCellValueFactory(new TreeItemPropertyValueFactory<Person, String>("firstName"));
+        firstNameCol.setCellFactory(CheckBoxTreeTableCell.forTreeTableColumn(new Callback<Integer, ObservableValue<Boolean>>() {
+            public javafx.beans.value.ObservableValue<Boolean> call(Integer param) {
+                return new ReadOnlyBooleanWrapper(true);
+            }
+        }));
+        tableView.getColumns().add(firstNameCol);
+
+        // because only the first row has data, all other rows should be
+        // empty (and not contain check boxes - we just check the first four here)
+        VirtualFlowTestUtils.assertRowsNotEmpty(tableView, 0, 1);
+        VirtualFlowTestUtils.assertCellNotEmpty(VirtualFlowTestUtils.getCell(tableView, 0));
+        VirtualFlowTestUtils.assertCellEmpty(VirtualFlowTestUtils.getCell(tableView, 1));
+        VirtualFlowTestUtils.assertCellEmpty(VirtualFlowTestUtils.getCell(tableView, 2));
+        VirtualFlowTestUtils.assertCellEmpty(VirtualFlowTestUtils.getCell(tableView, 3));
+    }
 }
--- a/javafx-ui-controls/test/javafx/scene/control/TreeViewTest.java	Fri May 31 10:57:00 2013 +1200
+++ b/javafx-ui-controls/test/javafx/scene/control/TreeViewTest.java	Fri May 31 11:44:05 2013 +1200
@@ -44,6 +44,7 @@
 import static com.sun.javafx.scene.control.infrastructure.ControlTestUtils.assertStyleClassContains;
 import static org.junit.Assert.*;
 import javafx.beans.property.ObjectProperty;
+import javafx.beans.property.ReadOnlyBooleanWrapper;
 import javafx.beans.property.SimpleObjectProperty;
 import javafx.beans.property.SimpleStringProperty;
 import javafx.beans.value.ChangeListener;
@@ -53,6 +54,7 @@
 import javafx.scene.Group;
 import javafx.scene.Node;
 import javafx.scene.Scene;
+import javafx.scene.control.cell.CheckBoxTreeCell;
 import javafx.scene.control.cell.PropertyValueFactory;
 import javafx.scene.control.cell.TreeItemPropertyValueFactory;
 import javafx.scene.layout.VBox;
@@ -999,4 +1001,25 @@
         assertTrue(treeView.getFocusModel().isFocused(10));
         assertEquals(3, sm.getSelectedIndices().size());
     }
+
+    @Test public void test_rt30400() {
+        // create a treeview that'll render cells using the check box cell factory
+        TreeItem<String> rootItem = new TreeItem<>("root");
+        treeView.setRoot(rootItem);
+        treeView.setMinHeight(100);
+        treeView.setPrefHeight(100);
+        treeView.setCellFactory(CheckBoxTreeCell.forTreeView(new Callback<TreeItem<String>, ObservableValue<Boolean>>() {
+            public javafx.beans.value.ObservableValue<Boolean> call(TreeItem<String> param) {
+                return new ReadOnlyBooleanWrapper(true);
+            }
+        }));
+
+        // because only the first row has data, all other rows should be
+        // empty (and not contain check boxes - we just check the first four here)
+        VirtualFlowTestUtils.assertRowsNotEmpty(treeView, 0, 1);
+        VirtualFlowTestUtils.assertCellNotEmpty(VirtualFlowTestUtils.getCell(treeView, 0));
+        VirtualFlowTestUtils.assertCellEmpty(VirtualFlowTestUtils.getCell(treeView, 1));
+        VirtualFlowTestUtils.assertCellEmpty(VirtualFlowTestUtils.getCell(treeView, 2));
+        VirtualFlowTestUtils.assertCellEmpty(VirtualFlowTestUtils.getCell(treeView, 3));
+    }
 }