changeset 2226:244420325878

Automated merge with ssh://jfxsrc.us.oracle.com//javafx/8.0/scrum/controls/jfx/rt
author jgiles
date Mon, 14 Jan 2013 15:16:41 +1300
parents c014fe9ac135 962890a91cb7
children b4ca866d4d03 16db5f0dcf7b
files
diffstat 38 files changed, 411 insertions(+), 386 deletions(-) [+]
line wrap: on
line diff
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/TreeTableRowBehavior.java	Fri Jan 11 18:42:21 2013 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/TreeTableRowBehavior.java	Mon Jan 14 15:16:41 2013 +1300
@@ -44,43 +44,26 @@
     @Override public void mouseReleased(MouseEvent e) {
         super.mouseReleased(e);
         
+        if (e.getButton() != MouseButton.PRIMARY) return;
+        
         TreeTableRow<T> treeTableRow = getControl();
-        TreeTableView<T> tv = treeTableRow.getTreeTableView();
         TreeItem treeItem = treeTableRow.getTreeItem();
-        int index = treeTableRow.getIndex();
-        MultipleSelectionModel sm = tv.getSelectionModel();
-        boolean isAlreadySelected = sm.isSelected(index);
-
+        if (treeItem == null) return;
+        
         // if the user has clicked on the disclosure node, we do nothing other
         // than expand/collapse the tree item (if applicable). We do not do editing!
         Node disclosureNode = treeTableRow.getDisclosureNode();
         if (disclosureNode != null) {
             if (disclosureNode.getBoundsInParent().contains(e.getX(), e.getY())) {
-                if (treeItem != null) {
-                    treeItem.setExpanded(! treeItem.isExpanded());
-                }
+                treeItem.setExpanded(! treeItem.isExpanded());
                 return;
             }
         }
         
-        tv.getSelectionModel().clearAndSelect(index);
-
         // handle editing, which only occurs with the primary mouse button
-        if (e.getButton() == MouseButton.PRIMARY) {
-            if (e.getClickCount() == 1 && isAlreadySelected) {
-                tv.edit(treeItem);
-            } else if (e.getClickCount() == 1) {
-                // cancel editing
-                tv.edit(null);
-            } else if (e.getClickCount() == 2/* && ! getControl().isEditable()*/) {
-                if (treeItem.isLeaf()) {
-                    // attempt to edit
-                    tv.edit(treeItem);
-                } else {
-                    // try to expand/collapse branch tree item
-                    treeItem.setExpanded(! treeItem.isExpanded());
-                }
-            }
+        if (e.getClickCount() == 2) {
+            // try to expand/collapse branch tree item
+            treeItem.setExpanded(! treeItem.isExpanded());
         }
     }
 }
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/BehaviorSkinBase.java	Fri Jan 11 18:42:21 2013 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/BehaviorSkinBase.java	Mon Jan 14 15:16:41 2013 +1300
@@ -25,12 +25,15 @@
 package com.sun.javafx.scene.control.skin;
 
 import com.sun.javafx.css.PseudoClass;
+import com.sun.javafx.scene.control.MultiplePropertyChangeListenerHandler;
 import com.sun.javafx.scene.control.behavior.BehaviorBase;
+import javafx.beans.value.ObservableValue;
 import javafx.event.EventHandler;
 import javafx.event.EventType;
 import javafx.scene.control.Control;
 import javafx.scene.control.SkinBase;
 import javafx.scene.input.MouseEvent;
+import javafx.util.Callback;
 
 /**
  *
@@ -54,6 +57,14 @@
      */
     private BB behavior;
     
+    /**
+     * This is part of the workaround introduced during delomboking. We probably will
+     * want to adjust the way listeners are added rather than continuing to use this
+     * map (although it doesn't really do much harm).
+     */
+    private MultiplePropertyChangeListenerHandler changeListenerHandler;
+    
+    
     
     /***************************************************************************
      *                                                                         *
@@ -130,6 +141,11 @@
 
     /** {@inheritDoc} */
     @Override public void dispose() { 
+        // unhook listeners
+        if (changeListenerHandler != null) {
+            changeListenerHandler.dispose();
+        }
+        
         C control = getSkinnable();
         control.removeEventHandler(MouseEvent.MOUSE_ENTERED, mouseHandler);
         control.removeEventHandler(MouseEvent.MOUSE_EXITED, mouseHandler);
@@ -146,6 +162,41 @@
     
     /***************************************************************************
      *                                                                         *
+     * Public API                                                              *
+     *                                                                         *
+     **************************************************************************/
+    
+    /**
+     * Subclasses can invoke this method to register that we want to listen to
+     * property change events for the given property.
+     *
+     * @param property
+     * @param reference
+     */
+    protected final void registerChangeListener(ObservableValue property, String reference) {
+        if (changeListenerHandler == null) {
+            changeListenerHandler = new MultiplePropertyChangeListenerHandler(new Callback<String, Void>() {
+                @Override public Void call(String p) {
+                    handleControlPropertyChanged(p);
+                    return null;
+                }
+            });
+        }
+        changeListenerHandler.registerChangeListener(property, reference);
+    }
+    
+    /**
+     * Skin subclasses will override this method to handle changes in corresponding
+     * control's properties.
+     */
+    protected void handleControlPropertyChanged(String propertyReference) {
+        // no-op
+    }
+    
+    
+    
+    /***************************************************************************
+     *                                                                         *
      * Specialization of CSS handling code                                     *
      *                                                                         *
      **************************************************************************/
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ListViewSkin.java	Fri Jan 11 18:42:21 2013 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ListViewSkin.java	Mon Jan 14 15:16:41 2013 +1300
@@ -27,6 +27,8 @@
 
 import javafx.collections.ListChangeListener;
 import javafx.collections.ObservableList;
+import javafx.collections.ObservableMap;
+import javafx.collections.WeakListChangeListener;
 import javafx.event.EventHandler;
 import javafx.geometry.Orientation;
 import javafx.scene.Node;
@@ -36,11 +38,8 @@
 import javafx.scene.control.ListView;
 import javafx.scene.control.SelectionModel;
 import javafx.scene.input.MouseEvent;
-
-import javafx.collections.WeakListChangeListener;
+import javafx.util.Callback;
 import com.sun.javafx.scene.control.behavior.ListViewBehavior;
-import javafx.collections.ObservableMap;
-import javafx.util.Callback;
 
 /**
  *
@@ -59,8 +58,8 @@
         flow.setPannable(false);
         flow.setVertical(getSkinnable().getOrientation() == Orientation.VERTICAL);
         flow.setFocusTraversable(getSkinnable().isFocusTraversable());
-        flow.setCreateCell(new Callback<VirtualFlow, ListCell>() {
-            @Override public ListCell call(VirtualFlow flow) {
+        flow.setCreateCell(new Callback<VirtualFlow, ListCell<T>>() {
+            @Override public ListCell<T> call(VirtualFlow flow) {
                 return ListViewSkin.this.createCell();
             }
         });
@@ -179,6 +178,9 @@
 //        return listViewItems == null ? 0 : listViewItems.size();
         return itemCount;
     }
+    
+    private boolean needCellsRebuilt = true;
+    private boolean needCellsReconfigured = false;
 
     void updateCellCount() {
         if (flow == null) return;
@@ -192,10 +194,16 @@
         flow.setCellCount(newCount);
         
         if (newCount != oldCount) {
-            flow.recreateCells();
+            flow.rebuildCells();
         } else {
             flow.reconfigureCells();
         }
+        
+        if (newCount != oldCount) {
+            needCellsRebuilt = true;
+        } else {
+            needCellsReconfigured = true;
+        }
     }
 
     @Override public ListCell<T> createCell() {
@@ -265,6 +273,15 @@
             itemCountDirty = false;
         }
         
+        if (needCellsRebuilt) {
+            flow.rebuildCells();
+        } else if (needCellsReconfigured) {
+            flow.reconfigureCells();
+        } 
+        
+        needCellsRebuilt = false;
+        needCellsReconfigured = false;
+        
         flow.resizeRelocate(x, y, w, h);
     }
     
@@ -312,7 +329,7 @@
         flow.show(pos);
 
         // Fix for RT-11299
-        IndexedCell cell = flow.getLastVisibleCell();
+        ListCell<T> cell = flow.getLastVisibleCell();
         if (cell == null || cell.getIndex() < pos) {
             flow.setPosition(pos / (double) getItemCount());
         }
@@ -338,7 +355,7 @@
      * if this is a horizontal container, then the scrolling will be to the right.
      */
     private int onScrollPageDown(int anchor) {
-        IndexedCell lastVisibleCell = flow.getLastVisibleCellWithinViewPort();
+        ListCell<T> lastVisibleCell = flow.getLastVisibleCellWithinViewPort();
         if (lastVisibleCell == null) return -1;
 
         int newSelectionIndex = -1;
@@ -366,7 +383,7 @@
      * if this is a horizontal container, then the scrolling will be to the left.
      */
     private int onScrollPageUp(int anchor) {
-        IndexedCell firstVisibleCell = flow.getFirstVisibleCellWithinViewPort();
+        ListCell<T> firstVisibleCell = flow.getFirstVisibleCellWithinViewPort();
         if (firstVisibleCell == null) return -1;
 
         int newSelectionIndex = -1;
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TableViewSkinBase.java	Fri Jan 11 18:42:21 2013 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TableViewSkinBase.java	Mon Jan 14 15:16:41 2013 +1300
@@ -64,7 +64,7 @@
 public abstract class TableViewSkinBase<S, C extends Control, B extends BehaviorBase<C>, I extends IndexedCell> extends VirtualContainerBase<C, B, I> {
     
     public static final String REFRESH = "tableRefreshKey";
-    public static final String RECREATE = "tableRecreateKey";
+    public static final String REBUILD = "tableRebuildKey";
     
 //    protected abstract void requestControlFocus(); // tableView.requestFocus();
     protected abstract TableSelectionModel getSelectionModel(); // tableView.getSelectionModel()
@@ -172,10 +172,10 @@
                 if (REFRESH.equals(c.getKey())) {
                     refreshView();
                     control.getProperties().remove(REFRESH);
-                } else if (RECREATE.equals(c.getKey())) {
-                    forceCellRecreation = true;
+                } else if (REBUILD.equals(c.getKey())) {
+                    forceCellRebuild = true;
                     refreshView();
-                    control.getProperties().remove(RECREATE);
+                    control.getProperties().remove(REBUILD);
                 }
             }
         });
@@ -202,10 +202,9 @@
         if ("ROW_FACTORY".equals(p)) {
             Callback<C, I> oldFactory = rowFactory;
             rowFactory = rowFactoryProperty().get();
-
-            // TODO tighten this up
             if (oldFactory != rowFactory) {
-                flow.recreateCells();
+                needCellsRebuilt = true;
+                getSkinnable().requestLayout();
             }
         } else if ("PLACEHOLDER".equals(p)) {
             updatePlaceholderRegionVisibility();
@@ -250,7 +249,8 @@
             // resizing occurs. It is not ideal, but will work for now.
             // FIXME this is very, very inefficient, but ensures we don't run
             // in to RT-13717.
-            flow.reconfigureCells();
+            needCellsRebuilt = true;
+            getSkinnable().requestLayout();
         }
     };
     
@@ -341,7 +341,7 @@
      * if this is a horizontal container, then the scrolling will be to the right.
      */
     public int onScrollPageDown() {
-        IndexedCell lastVisibleCell = flow.getLastVisibleCellWithinViewPort();
+        I lastVisibleCell = flow.getLastVisibleCellWithinViewPort();
         if (lastVisibleCell == null) return -1;
         
         int lastVisibleCellIndex = lastVisibleCell.getIndex();
@@ -368,7 +368,7 @@
      * if this is a horizontal container, then the scrolling will be to the left.
      */
     public int onScrollPageUp() {
-        IndexedCell firstVisibleCell = flow.getFirstVisibleCellWithinViewPort();
+        I firstVisibleCell = flow.getFirstVisibleCellWithinViewPort();
         if (firstVisibleCell == null) return -1;
         
         int firstVisibleCellIndex = firstVisibleCell.getIndex();
@@ -445,6 +445,9 @@
         return Math.max(pw, prefHeight * GOLDEN_RATIO_MULTIPLIER);
     }
     
+    private boolean needCellsRebuilt = true;
+    private boolean needCellsReconfigured = false;
+    
     /** {@inheritDoc} */
     @Override protected void layoutChildren(final double x, double y,
             final double w, final double h) {
@@ -453,6 +456,15 @@
             rowCountDirty = false;
         }
         
+        if (needCellsRebuilt) {
+            flow.rebuildCells();
+        } else if (needCellsReconfigured) {
+            flow.reconfigureCells();
+        } 
+        
+        needCellsRebuilt = false;
+        needCellsReconfigured = false;
+        
         final double baselineOffset = getSkinnable().getLayoutBounds().getHeight() / 2;
 
         // position the table header
@@ -563,7 +575,8 @@
         visibleColCount = getVisibleLeafColumns().size();
 
         updatePlaceholderRegionVisibility();
-        reconfigureCells();
+        needCellsRebuilt = true;
+        getSkinnable().requestLayout();
     }
     
     private void updateVisibleLeafColumnWidthListeners(
@@ -577,7 +590,8 @@
             TableColumnBase tc = added.get(i);
             tc.widthProperty().addListener(weakWidthListener);
         }
-        flow.reconfigureCells();
+        needCellsRebuilt = true;
+        getSkinnable().requestLayout();
     }
 
     private void updatePlaceholderRegionVisibility() {
@@ -640,11 +654,7 @@
         getSkinnable().requestLayout();
     }
 
-    private void reconfigureCells() {
-        flow.reconfigureCells();
-    }
-
-    private boolean forceCellRecreation = false;
+    private boolean forceCellRebuild = false;
     
     private void updateRowCount() {
         updatePlaceholderRegionVisibility();
@@ -657,14 +667,15 @@
         // optimised in the future when time permits.
         flow.setCellCount(newCount);
         
-        if (forceCellRecreation || newCount != oldCount) {
-            // FIXME updateRowCount is called _a lot_. Perhaps we can make recreateCells
+        if (forceCellRebuild || newCount != oldCount) {
+            // FIXME updateRowCount is called _a lot_. Perhaps we can make rebuildCells
             // smarter. Imagine if items has one million items added - do we really
-            // need to recreateCells a million times?
-            flow.recreateCells();
-            forceCellRecreation = false;
+            // need to rebuildCells a million times? Maybe this is better now that
+            // we do rebuildCells instead of recreateCells.
+            needCellsRebuilt = true;
+            forceCellRebuild = false;
         } else {
-            flow.reconfigureCells();
+            needCellsReconfigured = true;
         }
     }
 
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TreeViewSkin.java	Fri Jan 11 18:42:21 2013 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TreeViewSkin.java	Mon Jan 14 15:16:41 2013 +1300
@@ -52,8 +52,8 @@
         // init the VirtualFlow
         flow.setPannable(false);
         flow.setFocusTraversable(getSkinnable().isFocusTraversable());
-        flow.setCreateCell(new Callback<VirtualFlow, TreeCell>() {
-            @Override public TreeCell call(VirtualFlow flow) {
+        flow.setCreateCell(new Callback<VirtualFlow, TreeCell<T>>() {
+            @Override public TreeCell<T> call(VirtualFlow flow) {
                 return TreeViewSkin.this.createCell();
             }
         });
@@ -145,7 +145,7 @@
     }
     
     private boolean needItemCountUpdate = false;
-    private boolean needCellsRecreated = true;
+    private boolean needCellsRebuilt = true;
     private boolean needCellsReconfigured = false;
     
     private EventHandler<TreeModificationEvent> rootListener = new EventHandler<TreeModificationEvent>() {
@@ -160,7 +160,7 @@
                 getSkinnable().requestLayout();
             } else if (e.getEventType().equals(TreeItem.valueChangedEvent())) {
                 // Fix for RT-14971 and RT-15338. 
-                needCellsRecreated = true;
+                needCellsRebuilt = true;
                 getSkinnable().requestLayout();
             } else {
                 // Fix for RT-20090. We are checking to see if the event coming
@@ -220,7 +220,7 @@
         flow.setCellCount(newCount);
         
         if (newCount != oldCount) {
-            needCellsRecreated = true;
+            needCellsRebuilt = true;
         } else {
             needCellsReconfigured = true;
         }
@@ -313,15 +313,14 @@
             needItemCountUpdate = false;
         }
         
-        if (needCellsRecreated) {
-            flow.recreateCells();
-            needCellsRecreated = false;
+        if (needCellsRebuilt) {
+            flow.rebuildCells();
+        } else if (needCellsReconfigured) {
+            flow.reconfigureCells();
         } 
         
-        if (needCellsReconfigured) {
-            flow.reconfigureCells();
-            needCellsReconfigured = false;
-        } 
+        needCellsRebuilt = false;
+        needCellsReconfigured = false;
         
         flow.resizeRelocate(x, y, w, h);
     }
@@ -363,7 +362,7 @@
      * if this is a horizontal container, then the scrolling will be to the right.
      */
     public int onScrollPageDown(int anchor) {
-        IndexedCell lastVisibleCell = flow.getLastVisibleCellWithinViewPort();
+        TreeCell<T> lastVisibleCell = flow.getLastVisibleCellWithinViewPort();
         if (lastVisibleCell == null) return -1;
 
         int newSelectionIndex = -1;
@@ -391,7 +390,7 @@
      * if this is a horizontal container, then the scrolling will be to the left.
      */
     public int onScrollPageUp(int anchor) {
-        IndexedCell firstVisibleCell = flow.getFirstVisibleCellWithinViewPort();
+        TreeCell<T> firstVisibleCell = flow.getFirstVisibleCellWithinViewPort();
         if (firstVisibleCell == null) return -1;
 
         int newSelectionIndex = -1;
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/VirtualContainerBase.java	Fri Jan 11 18:42:21 2013 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/VirtualContainerBase.java	Mon Jan 14 15:16:41 2013 +1300
@@ -49,7 +49,7 @@
     public VirtualContainerBase(final C control, B behavior) {
         super(control, behavior);
         
-        flow = new VirtualFlow();
+        flow = new VirtualFlow<I>();
         handleControlProperties(control);
 
         control.getProperties().addListener(new MapChangeListener<Object, Object>() {
@@ -66,7 +66,7 @@
      * The virtualized container which handles the layout and scrolling of
      * all the cells.
      */
-    protected final VirtualFlow flow;
+    protected final VirtualFlow<I> flow;
 
     /**
      * Returns a Cell available to be used in the virtual flow. This means you
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/VirtualFlow.java	Fri Jan 11 18:42:21 2013 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/VirtualFlow.java	Mon Jan 14 15:16:41 2013 +1300
@@ -54,7 +54,7 @@
 /**
  * Implementation of a virtualized container using a cell based mechanism.
  */
-public class VirtualFlow extends Region {
+public class VirtualFlow<T extends IndexedCell> extends Region {
     /**
      * There are two main complicating factors in the implementation of the
      * VirtualFlow, which are made even more complicated due to the performance
@@ -264,9 +264,9 @@
      * IndexedCell. The VirtualFlow attempts to reuse cells whenever possible
      * and only creates the minimal number of cells necessary.
      */
-    private Callback<VirtualFlow, ? extends IndexedCell> createCell;
-    public Callback<VirtualFlow, ? extends IndexedCell> getCreateCell() { return createCell; }
-    protected void setCreateCell(Callback<VirtualFlow, ? extends IndexedCell> cc) {
+    private Callback<VirtualFlow, T> createCell;
+    public Callback<VirtualFlow, T> getCreateCell() { return createCell; }
+    protected void setCreateCell(Callback<VirtualFlow, T> cc) {
         this.createCell = cc;
 
         if (createCell != null) {
@@ -365,7 +365,7 @@
      * <p>
      * This is package private ONLY FOR TESTING
      */
-    final ArrayLinkedList<IndexedCell> cells = new ArrayLinkedList<IndexedCell>();
+    final ArrayLinkedList<T> cells = new ArrayLinkedList<T>();
 
     /**
      * A structure containing cells that can be reused later. These are cells
@@ -374,14 +374,14 @@
      * <p>
      * This is package private ONLY FOR TESTING
      */
-    final ArrayLinkedList<IndexedCell> pile = new ArrayLinkedList<IndexedCell>();
+    final ArrayLinkedList<T> pile = new ArrayLinkedList<T>();
 
     /**
      * A special cell used to accumulate bounds, such that we reduce object
      * churn. This cell must be recreated whenever the cell factory function
      * changes. This has package access ONLY for testing.
      */
-    IndexedCell accumCell;
+    T accumCell;
 
     /**
      * This group is used for holding the 'accumCell'. 'accumCell' must
@@ -762,18 +762,29 @@
 //            accumCell = null;
 //            accumCellParent.getChildren().clear();
             sheet.getChildren().clear();
+            for (int i = 0, max = cells.size(); i < max; i++) {
+                cells.get(i).updateIndex(-1);
+            }
             cells.clear();
             pile.clear();
-            needsRecreateCells = false;
-        } 
-        
-        if (needsReconfigureCells) {
+        } else if (needsRebuildCells) {
             maxPrefBreadth = -1;
             lastWidth = -1;
             lastHeight = -1;
-            numCellsVisibleOnScreen = -1;
-            needsReconfigureCells = false;
+            releaseCell(accumCell);
+            for (int i=0; i<cells.size(); i++) {
+                cells.get(i).updateIndex(-1);
+            }
+            addAllToPile();
+        } else if (needsReconfigureCells) {
+            maxPrefBreadth = -1;
+            lastWidth = -1;
+            lastHeight = -1;
         }
+       
+        needsRecreateCells = false;
+        needsReconfigureCells = false;
+        needsRebuildCells = false;
         
         if (needsCellsLayout) {
             for (int i = 0, max = cells.size(); i < max; i++) {
@@ -818,7 +829,7 @@
         }
         cell = null;
         
-        IndexedCell firstCell = getFirstVisibleCell();
+        T firstCell = getFirstVisibleCell();
 
         // If no cells need layout, we check other criteria to see if this 
         // layout call is even necessary. If it is found that no layout is 
@@ -1007,7 +1018,7 @@
         // offset is our indication of whether we can lay out additional
         // cells. If the offset is ever < 0, except in the case of the very
         // first cell, then we must quit.
-        IndexedCell cell = null;
+        T cell = null;
 
         while (index >= 0 && (offset > 0 || first)) {
             cell = getAvailableCell(index);
@@ -1065,7 +1076,7 @@
         // off the flow, so we will continue to create and add cells. When the
         // offset becomes greater than the width/height of the flow, then we
         // know we cannot add any more cells.
-        IndexedCell startCell = cells.getLast();
+        T startCell = cells.getLast();
         double offset = getCellPosition(startCell) + getCellLength(startCell);
         int index = startCell.getIndex() + 1;
         boolean filledWithNonEmpty = index <= cellCount;
@@ -1075,7 +1086,7 @@
                 if (offset < viewportLength) filledWithNonEmpty = false;
                 if (! fillEmptyCells) return filledWithNonEmpty;
             }
-            IndexedCell cell = getAvailableCell(index);
+            T cell = getAvailableCell(index);
             setCellIndex(cell, index);
             resizeCellSize(cell); // resize happens after config!
             cells.addLast(cell);
@@ -1096,9 +1107,9 @@
         // one at a time, until either the very last non-empty cells is aligned
         // with the bottom OR we have laid out cell index #0 at the first
         // position.
-        IndexedCell firstCell = cells.getFirst();
+        T firstCell = cells.getFirst();
         index = firstCell.getIndex();
-        IndexedCell lastNonEmptyCell = getLastVisibleCell();
+        T lastNonEmptyCell = getLastVisibleCell();
         double start = getCellPosition(firstCell);
         double end = getCellPosition(lastNonEmptyCell) + getCellLength(lastNonEmptyCell);
         if ((index != 0 || (index == 0 && start < 0)) && fillEmptyCells &&
@@ -1108,7 +1119,7 @@
             double distance = viewportLength - end;
             while (prospectiveEnd < viewportLength && index != 0 && (-start) < distance) {
                 index--;
-                IndexedCell cell = getAvailableCell(index);
+                T cell = getAvailableCell(index);
                 setCellIndex(cell, index);
                 resizeCellSize(cell); // resize must be after config
                 cells.addFirst(cell);
@@ -1129,7 +1140,7 @@
             }
             // Move things
             for (int i = 0; i < cells.size(); i++) {
-                IndexedCell cell = cells.get(i);
+                T cell = cells.get(i);
                 positionCell(cell, getCellPosition(cell) + delta);
             }
 
@@ -1240,7 +1251,7 @@
                     // exactly matches the number of cells laid out. In this case,
                     // we need to check the last cell's layout position + length
                     // to determine if we need the length bar
-                    IndexedCell lastCell = cells.getLast();
+                    T lastCell = cells.getLast();
                     lengthBar.setVisible((getCellPosition(lastCell) + getCellLength(lastCell)) > viewportLength);
                 }
                 
@@ -1268,7 +1279,7 @@
         if (numCellsVisibleOnScreen == -1) {
             numCellsVisibleOnScreen = 0;
             for (int i = 0, max = cells.size(); i < max; i++) {
-                IndexedCell cell = cells.get(i);
+                T cell = cells.get(i);
                 if (cell != null && ! cell.isEmpty()) {
                     sumCellLength += (isVertical ? cell.getHeight() : cell.getWidth());
                     if (sumCellLength > flowLength) {
@@ -1388,7 +1399,7 @@
 
     private void cull() {
         for (int i = cells.size() - 1; i >= 0; i--) {
-            IndexedCell cell = cells.get(i);
+            T cell = cells.get(i);
             double cellSize = getCellLength(cell);
             double cellStart = getCellPosition(cell);
             double cellEnd = cellStart + cellSize;
@@ -1410,18 +1421,18 @@
      * empty cell will be returned. The returned value should not be stored for
      * any reason.
      */
-    IndexedCell getCell(int index) {
+    T getCell(int index) {
         // If there are cells, then we will attempt to get an existing cell
         if (! cells.isEmpty()) {
             // First check the cells that have already been created and are
             // in use. If this call returns a value, then we can use it
-            IndexedCell cell = getVisibleCell(index);
+            T cell = getVisibleCell(index);
             if (cell != null) return cell;
         }
 
         // check the pile
         for (int i = 0; i < pile.size(); i++) {
-            IndexedCell cell = pile.get(i);
+            T cell = pile.get(i);
             if (cell != null && cell.getIndex() == index) {
                 // Note that we don't remove from the pile: if we do it leads
                 // to a severe performance decrease. This seems to be OK, as
@@ -1431,8 +1442,16 @@
             }
         }
 
+        if (pile.size() > 0) {
+            // TODO The above code checks for null values returned from the pile. Is that possible?
+            // TODO I would not have thought so, there should be an assert added to addToPile to
+            // TODO make sure we never add null to the pile (since it doesn't make sense to do so)
+            // TODO and then we can get rid of the cell != null check on line 1422 above.
+            return pile.get(0);
+        }
+
         // We need to use the accumCell and return that
-        Callback<VirtualFlow,? extends IndexedCell> createCell = getCreateCell();
+        Callback<VirtualFlow,T> createCell = getCreateCell();
         if (accumCell == null && createCell != null) {
             accumCell = createCell.call(this);
             accumCell.getProperties().put(NEW_CELL, null);
@@ -1446,7 +1465,7 @@
     /**
      * After using the accum cell, it needs to be released!
      */
-    private void releaseCell(IndexedCell cell) {
+    private void releaseCell(T cell) {
         if (accumCell != null && cell == accumCell) {
             accumCell.updateIndex(-1);
         }
@@ -1463,7 +1482,7 @@
     double getCellLength(int index) {
         if (fixedCellLength > 0) return fixedCellLength;
         
-        IndexedCell cell = getCell(index);
+        T cell = getCell(index);
         double length = getCellLength(cell);
         releaseCell(cell);
         return length;
@@ -1472,7 +1491,7 @@
     /**
      */
     double getCellBreadth(int index) {
-        IndexedCell cell = getCell(index);
+        T cell = getCell(index);
         double b = getCellBreadth(cell);
         releaseCell(cell);
         return b;
@@ -1481,7 +1500,7 @@
     /**
      * Gets the length of a specific cell
      */
-    private double getCellLength(IndexedCell cell) {
+    private double getCellLength(T cell) {
         if (cell == null) return 0;
         if (fixedCellLength > 0) return fixedCellLength;
 
@@ -1490,7 +1509,7 @@
             : cell.getLayoutBounds().getWidth();
     }
 
-//    private double getCellPrefLength(IndexedCell cell) {
+//    private double getCellPrefLength(T cell) {
 //        return isVertical() ?
 //            cell.prefHeight(-1)
 //            : cell.prefWidth(-1);
@@ -1508,7 +1527,7 @@
     /**
      * Gets the layout position of the cell along the length axis
      */
-    private double getCellPosition(IndexedCell cell) {
+    private double getCellPosition(T cell) {
         if (cell == null) return 0;
 
         return isVertical() ?
@@ -1516,7 +1535,7 @@
             : cell.getLayoutX();
     }
 
-    private void positionCell(IndexedCell cell, double position) {
+    private void positionCell(T cell, double position) {
         if (isVertical()) {
             cell.setLayoutX(0);
             cell.setLayoutY(snapSize(position));
@@ -1526,7 +1545,7 @@
         }
     }
 
-    private void resizeCellSize(IndexedCell cell) {
+    private void resizeCellSize(T cell) {
         if (cell == null) return;
         if (isVertical())
             cell.resize(cell.getWidth(), cell.prefHeight(-1));
@@ -1534,7 +1553,7 @@
             cell.resize(cell.prefWidth(-1), cell.getHeight());
     }
 
-    private void setCellIndex(IndexedCell cell, int index) {
+    private void setCellIndex(T cell, int index) {
         if (cell == null) return;
 
         cell.updateIndex(index);
@@ -1562,13 +1581,13 @@
      * cells from the pile where possible, and will create new cells when
      * necessary.
      */
-    private IndexedCell getAvailableCell(int prefIndex) {
-        IndexedCell cell = null;
+    private T getAvailableCell(int prefIndex) {
+        T cell = null;
         
         // Fix for RT-12822. We try to retrieve the cell from the pile rather
         // than just grab a random cell from the pile (or create another cell).
         for (int i = 0, max = pile.size(); i < max; i++) {
-            IndexedCell _cell = pile.get(i);
+            T _cell = pile.get(i);
             if (_cell != null && _cell.getIndex() == prefIndex) {
                 cell = _cell;
                 pile.remove(i);
@@ -1604,7 +1623,7 @@
      * Puts the given cell onto the pile. This is called whenever a cell has
      * fallen off the flow's start.
      */
-    private void addToPile(IndexedCell cell) {
+    private void addToPile(T cell) {
         cell.setVisible(false);
         cell.setManaged(false);
         pile.addLast(cell);
@@ -1617,16 +1636,16 @@
      * have been created and are in use vs. those that are in the pile or
      * not created.
      */
-    public IndexedCell getVisibleCell(int index) {
+    public T getVisibleCell(int index) {
         if (cells.isEmpty()) return null;
 
         // check the last index
-        IndexedCell lastCell = cells.getLast();
+        T lastCell = cells.getLast();
         int lastIndex = lastCell.getIndex();
         if (index == lastIndex) return lastCell;
 
         // check the first index
-        IndexedCell firstCell = cells.getFirst();
+        T firstCell = cells.getFirst();
         int firstIndex = firstCell.getIndex();
         if (index == firstIndex) return firstCell;
 
@@ -1644,10 +1663,10 @@
      * partially or completely visible. This function may return null if there
      * are no cells, or if the viewport length is 0.
      */
-    public IndexedCell getLastVisibleCell() {
+    public T getLastVisibleCell() {
         if (cells.isEmpty() || viewportLength <= 0) return null;
 
-        IndexedCell cell;
+        T cell;
         for (int i = cells.size() - 1; i >= 0; i--) {
             cell = cells.get(i);
             if (! cell.isEmpty()) {
@@ -1663,16 +1682,16 @@
      * completely visible. This really only ever returns null if there are no
      * cells or the viewport length is 0.
      */
-    public IndexedCell getFirstVisibleCell() {
+    public T getFirstVisibleCell() {
         if (cells.isEmpty() || viewportLength <= 0) return null;
-        IndexedCell cell = cells.getFirst();
+        T cell = cells.getFirst();
         return cell.isEmpty() ? null : cell;
     }
 
-    public IndexedCell getLastVisibleCellWithinViewPort() {
+    public T getLastVisibleCellWithinViewPort() {
         if (cells.isEmpty() || viewportLength <= 0) return null;
 
-        IndexedCell cell;
+        T cell;
         for (int i = cells.size() - 1; i >= 0; i--) {
             cell = cells.get(i);
             if (cell.isEmpty()) continue;
@@ -1685,11 +1704,11 @@
         return null;
     }
 
-    public IndexedCell getFirstVisibleCellWithinViewPort() {
+    public T getFirstVisibleCellWithinViewPort() {
         if (cells.isEmpty() || viewportLength <= 0) return null;
 
         final boolean isVertical = isVertical();
-        IndexedCell cell;
+        T cell;
         for (int i = 0; i < cells.size(); i++) {
             cell = cells.get(i);
             if (cell.isEmpty()) continue;
@@ -1709,7 +1728,7 @@
      * will be positioned at the start of the viewport. The given cell must
      * already be "live". This is bad public API!
      */
-    public void showAsFirst(IndexedCell firstCell) {
+    public void showAsFirst(T firstCell) {
         if (firstCell != null) {
             adjustPixels(getCellPosition(firstCell));
         }
@@ -1720,7 +1739,7 @@
      * will be positioned at the end of the viewport. The given cell must
      * already be "live". This is bad public API!
      */
-    public void showAsLast(IndexedCell lastCell) {
+    public void showAsLast(T lastCell) {
         if (lastCell != null) {
             adjustPixels(getCellPosition(lastCell) + getCellLength(lastCell) - viewportLength);
         }
@@ -1730,7 +1749,7 @@
      * Adjusts the cells such that the selected cell will be fully visible in
      * the viewport (but only just).
      */
-    public void show(IndexedCell cell) {
+    public void show(T cell) {
         if (cell != null) {
             double start = getCellPosition(cell);
             double length = getCellLength(cell);
@@ -1744,12 +1763,12 @@
     }
 
     public void show(int index) {
-        IndexedCell cell = getVisibleCell(index);
+        T cell = getVisibleCell(index);
         if (cell != null) {
             show(cell);
         } else {
             // See if the previous index is a visible cell
-            IndexedCell prev = getVisibleCell(index - 1);
+            T prev = getVisibleCell(index - 1);
             if (prev != null) {
                 // Need to add a new cell and then we can show it
 //                layingOut = true;
@@ -1765,7 +1784,7 @@
                 return;
             }
             // See if the next index is a visible cell
-            IndexedCell next = getVisibleCell(index + 1);
+            T next = getVisibleCell(index + 1);
             if (next != null) {
 //                layingOut = true;
                 cell = getAvailableCell(index);
@@ -1855,12 +1874,12 @@
         int cellsSize = cells.size();
         if (cellsSize > 0) {
             for (int i = 0; i < cellsSize; i++) {
-                IndexedCell cell = cells.get(i);
+                T cell = cells.get(i);
                 positionCell(cell, getCellPosition(cell) - delta);
             }
 
             // Add any necessary leading cells
-            IndexedCell firstCell = cells.getFirst();
+            T firstCell = cells.getFirst();
             int firstIndex = firstCell.getIndex();
             double prevIndexSize = getCellLength(firstIndex - 1);
             addLeadingCells(firstIndex - 1, getCellPosition(firstCell) - prevIndexSize);
@@ -1874,14 +1893,14 @@
                 // Reached the end, but not enough cells to fill up to
                 // the end. So, remove the trailing empty space, and translate
                 // the cells down
-                IndexedCell lastCell = getLastVisibleCell();
+                T lastCell = getLastVisibleCell();
                 double lastCellSize = getCellLength(lastCell);
                 double cellEnd = getCellPosition(lastCell) + lastCellSize;
                 if (cellEnd < viewportLength) {
                     // Reposition the nodes
                     double emptySize = viewportLength - cellEnd;
                     for (int i = 0; i < cells.size(); i++) {
-                        IndexedCell cell = cells.get(i);
+                        T cell = cells.get(i);
                         positionCell(cell, getCellPosition(cell) + emptySize);
                     }
                     adjustPosition(1.0f);
@@ -1900,8 +1919,9 @@
         return delta; // TODO fake
     }
 
-    private boolean needsReconfigureCells = false;
-    private boolean needsRecreateCells = false;
+    private boolean needsReconfigureCells = false; // when cell contents are the same
+    private boolean needsRecreateCells = false; // when cell factory changed
+    private boolean needsRebuildCells = false; // when cell contents have changed
     private boolean needsCellsLayout = false;
     
     public void reconfigureCells() {
@@ -1914,6 +1934,11 @@
         requestLayout();
     }
     
+    public void rebuildCells() {
+        needsRebuildCells = true;
+        requestLayout();
+    }
+
     public void requestCellLayout() {
         needsCellsLayout = true;
         requestLayout();
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/caspian/caspian.css	Fri Jan 11 18:42:21 2013 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/caspian/caspian.css	Mon Jan 14 15:16:41 2013 +1300
@@ -3113,17 +3113,17 @@
     -fx-background-radius: 0 5 5 0, 0 4 4 0, 0 3 3 0;
     -fx-padding: 0.5em 0.416667em 0.5em 0.416667em; /* 6 5 6 5  */
 }
-/*    -fx-background-color: null;
-    -fx-background-insets: 0, 1, 2;
-    -fx-background-radius: 0 5 5 0, 0 4 4 0, 0 3 3 0;
-    -fx-padding: 0.5em 0.416667em 0.5em 0.416667em;  6 5 6 5 
-}*/
-/*.combo-box-base.split-button .arrow-button {
+
+.combo-box-base:hover > .arrow-button {
     -fx-background-color: -fx-outer-border, -fx-inner-border, -fx-body-color;
     -fx-background-insets: 0, 1, 2;
     -fx-background-radius: 0 5 5 0, 0 4 4 0, 0 3 3 0;
-    -fx-padding: 0.5em 0.416667em 0.5em 0.416667em;  6 5 6 5 
-}*/
+    -fx-padding: 0.5em 0.416667em 0.5em 0.416667em; /* 6 5 6 5 */
+}
+
+.combo-box-base:showing > .arrow-button {
+    -fx-color: -fx-pressed-base;
+} 
 
 /* ------- ARROW* ------- */
 .combo-box-base > .arrow-button > .arrow,
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/caspian/embedded-qvga.css	Fri Jan 11 18:42:21 2013 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/caspian/embedded-qvga.css	Mon Jan 14 15:16:41 2013 +1300
@@ -34,7 +34,7 @@
 
 /*******************************************************************************
  *                                                                             *
- * TextField, PasswordField, TextArea                                          *
+ * TextField, PasswordField, TextArea                                                                   *
  *                                                                             *
  ******************************************************************************/
 
@@ -45,27 +45,3 @@
 .text-area .content {
     -fx-padding: 3 5 3 5; /* Restore values from caspian, as QVGA has no selection handles */
 }
-
-
-/*******************************************************************************
- *                                                                             *
- * ListView                                                                    *
- *                                                                             *
- ******************************************************************************/
-
-.list-cell {
-    -fx-padding: 0.82em; /** This seems outrageously big */
-}
-
-
-/*******************************************************************************
- *                                                                             *
- * TableView                                                                   *
- *                                                                             *
- ******************************************************************************/
-
-.table-cell {
-    -fx-padding: 0.82em; /** This seems outrageously big */
-}
-
-
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/caspian/embedded.css	Fri Jan 11 18:42:21 2013 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/caspian/embedded.css	Mon Jan 14 15:16:41 2013 +1300
@@ -31,17 +31,6 @@
  *                                                                             *
  ******************************************************************************/
 
-
-
-/*******************************************************************************
- *                                                                             *
- * Label                                                                       *
- *                                                                             *
- ******************************************************************************/
-.label {
-    -fx-font-size: 0.75em; /** 9pt */
-}
-
 /*******************************************************************************
  *                                                                             *
  * PopupMenu                                                                   *
@@ -254,97 +243,6 @@
 
 
 /*******************************************************************************
- *                                                                             *
- * ComboBox                                                                    *
- *                                                                             *
- ******************************************************************************/
-
-.combo-box:external-focus {
-    -fx-border-color: red; 
-    -fx-focus-color: red;
-    -fx-opacity: 0.8;
-}
-.combo-box:internal-focus {
-    -fx-border-color: null; 
-    -fx-focus-color: #0093ff;
-    -fx-opacity: 1.0;
-}
-
-/* Customie the ListCell that appears in the ComboBox button itself */
-.combo-box > .list-cell {
-    -fx-padding: 0.5em 0.725em 0.5em 0.725em;
-    -fx-cell-size: 2em; 
-}
-
-.combo-box-popup > .list-view > .virtual-flow > .clipped-container > .sheet > .list-cell {
-    -fx-cell-size: 2.182em;
-}
-
-
-/*******************************************************************************
- *                                                                             *
- * SplitPane                                                                   *
- *                                                                             *
- ******************************************************************************/
-.split-pane > .split-pane-divider {
-    -fx-padding: 0 0.2725em 0 0.2725em; 
-}
-
-.split-pane > .split-pane-divider > .horizontal-grabber {
-    -fx-padding: 0.636em 0.18em 0.636em 0.18em;
-}
-
-.split-pane > .split-pane-divider > .vertical-grabber {
-    -fx-padding: 0.205em 0.545em 0.205em 0.545em;
-}
-
-
-/*******************************************************************************
- *                                                                             *
- * TabPane                                                                     *
- *                                                                             *
- ******************************************************************************/
-.tab-pane {
-    -fx-tab-min-width: 2.725em;
-    -fx-tab-min-height: 2.725em; 
-    -fx-tab-max-height: 2.725em; 
-}
-
-.tab-pane > .tab-header-area > .headers-region > .tab > .tab-container > .tab-label {
-    -fx-font-size: 1em;
-    -fx-padding: 0 0.545em 0 0.545em;
-}
-
-
-/*******************************************************************************
- *                                                                             *
- * TitledPane                                                                  *
- *                                                                             *
- ******************************************************************************/
-
-
-/*******************************************************************************
- *                                                                             *
- * ListView                                                                    *
- *                                                                             *
- ******************************************************************************/
-.list-view:external-focus {
-    -fx-border-color: red; 
-    -fx-focus-color: red;
-    -fx-opacity: 0.8;
-}
-.list-view:internal-focus {
-    -fx-border-color: null; 
-    -fx-focus-color: #0093ff;
-    -fx-opacity: 1.0;
-}
-
-.list-cell {
-    -fx-cell-size: 2.364em;
-}
-
-
-/*******************************************************************************
  *
  * 2-level focus setting.
  * The visuals aren't ready yet, so currently these are just placeholders.
@@ -414,6 +312,17 @@
     -fx-opacity: 1.0;
 }
 
+.list-view:external-focus {
+    -fx-border-color: red; 
+    -fx-focus-color: red;
+    -fx-opacity: 0.8;
+}
+.list-view:internal-focus {
+    -fx-border-color: null; 
+    -fx-focus-color: #0093ff;
+    -fx-opacity: 1.0;
+}
+
 .table-view:external-focus {
     -fx-border-color: red; 
     -fx-focus-color: red;
@@ -425,4 +334,13 @@
     -fx-opacity: 1.0;
 }
 
-
+.combo-box:external-focus {
+    -fx-border-color: red; 
+    -fx-focus-color: red;
+    -fx-opacity: 0.8;
+}
+.combo-box:internal-focus {
+    -fx-border-color: null; 
+    -fx-focus-color: #0093ff;
+    -fx-opacity: 1.0;
+}
--- a/javafx-ui-controls/src/javafx/scene/control/Control.java	Fri Jan 11 18:42:21 2013 -0800
+++ b/javafx-ui-controls/src/javafx/scene/control/Control.java	Mon Jan 14 15:16:41 2013 +1300
@@ -737,22 +737,21 @@
     }
 
     /**
-     * @treatAsPrivate implementation detail
-     * @deprecated This is an experimental API that is not intended for general use and is subject to change in future versions
-     */
-    @Deprecated
-    protected List<CssMetaData> impl_getControlStyleableProperties() {
-        return getClassCssMetaData();
-    }
-
-    /**
-     * {@inheritDoc}
+     * This method returns a {@link List} containing all {@link CssMetaData} for 
+     * both this Control (returned from {@link #getControlCssMetaData()} and its 
+     * {@link Skin}, assuming the {@link #skinProperty() skin property} is a 
+     * {@link SkinBase}. 
+     * 
+     * <p>Developers who wish to provide custom CssMetaData are therefore 
+     * encouraged to override {@link Control#getControlCssMetaData()} or 
+     * {@link SkinBase#getCssMetaData()}, depending on where the CssMetaData 
+     * resides.
      */
     @Override
-    public List<CssMetaData> getCssMetaData() {
+    public final List<CssMetaData> getCssMetaData() {
         if (styleableProperties == null) {
             styleableProperties = new ArrayList<CssMetaData>();
-            styleableProperties.addAll(impl_getControlStyleableProperties());
+            styleableProperties.addAll(getControlCssMetaData());
             
             if (skinBase != null) {
                 styleableProperties.addAll(skinBase.getCssMetaData());
@@ -760,6 +759,13 @@
         }
         return styleableProperties;
     }
+    
+    /**
+     * @return unmodifiable list of the controls css styleable properties
+     */
+    protected List<CssMetaData> getControlCssMetaData() {
+        return getClassCssMetaData();
+    }
 
     /**
      * @treatAsPrivate implementation detail
--- a/javafx-ui-controls/src/javafx/scene/control/Labeled.java	Fri Jan 11 18:42:21 2013 -0800
+++ b/javafx-ui-controls/src/javafx/scene/control/Labeled.java	Mon Jan 14 15:16:41 2013 +1300
@@ -935,7 +935,7 @@
      * {@inheritDoc}
      */
     @Override
-    public List<CssMetaData> getCssMetaData() {
+    public List<CssMetaData> getControlCssMetaData() {
         return getClassCssMetaData();
     }
 
--- a/javafx-ui-controls/src/javafx/scene/control/ListCell.java	Fri Jan 11 18:42:21 2013 -0800
+++ b/javafx-ui-controls/src/javafx/scene/control/ListCell.java	Mon Jan 14 15:16:41 2013 +1300
@@ -141,7 +141,7 @@
      */
     private final ListChangeListener itemsListener = new ListChangeListener() {
         @Override public void onChanged(ListChangeListener.Change c) {
-            updateItem(); // TODO limit this to only those changes necessary
+            updateItem();
         }
     };
 
--- a/javafx-ui-controls/src/javafx/scene/control/ListView.java	Fri Jan 11 18:42:21 2013 -0800
+++ b/javafx-ui-controls/src/javafx/scene/control/ListView.java	Mon Jan 14 15:16:41 2013 +1300
@@ -802,7 +802,7 @@
      * {@inheritDoc}
      */
     @Override
-    public List<CssMetaData> getCssMetaData() {
+    public List<CssMetaData> getControlCssMetaData() {
         return getClassCssMetaData();
     }
 
--- a/javafx-ui-controls/src/javafx/scene/control/MenuBar.java	Fri Jan 11 18:42:21 2013 -0800
+++ b/javafx-ui-controls/src/javafx/scene/control/MenuBar.java	Mon Jan 14 15:16:41 2013 +1300
@@ -199,7 +199,7 @@
      * {@inheritDoc}
      */
     @Override
-    public List<CssMetaData> getCssMetaData() {
+    public List<CssMetaData> getControlCssMetaData() {
         return getClassCssMetaData();
     }
 
--- a/javafx-ui-controls/src/javafx/scene/control/Pagination.java	Fri Jan 11 18:42:21 2013 -0800
+++ b/javafx-ui-controls/src/javafx/scene/control/Pagination.java	Mon Jan 14 15:16:41 2013 +1300
@@ -379,7 +379,7 @@
      * {@inheritDoc}
      */
     @Override
-    public List<CssMetaData> getCssMetaData() {
+    public List<CssMetaData> getControlCssMetaData() {
         return getClassCssMetaData();
     }
 
--- a/javafx-ui-controls/src/javafx/scene/control/ScrollBar.java	Fri Jan 11 18:42:21 2013 -0800
+++ b/javafx-ui-controls/src/javafx/scene/control/ScrollBar.java	Mon Jan 14 15:16:41 2013 +1300
@@ -438,7 +438,7 @@
      * {@inheritDoc}
      */
     @Override
-    public List<CssMetaData> getCssMetaData() {
+    public List<CssMetaData> getControlCssMetaData() {
         return getClassCssMetaData();
     }
 
--- a/javafx-ui-controls/src/javafx/scene/control/ScrollPane.java	Fri Jan 11 18:42:21 2013 -0800
+++ b/javafx-ui-controls/src/javafx/scene/control/ScrollPane.java	Mon Jan 14 15:16:41 2013 +1300
@@ -703,7 +703,7 @@
      * {@inheritDoc}
      */
     @Override
-    public List<CssMetaData> getCssMetaData() {
+    public List<CssMetaData> getControlCssMetaData() {
         return getClassCssMetaData();
     }
 
--- a/javafx-ui-controls/src/javafx/scene/control/Separator.java	Fri Jan 11 18:42:21 2013 -0800
+++ b/javafx-ui-controls/src/javafx/scene/control/Separator.java	Mon Jan 14 15:16:41 2013 +1300
@@ -309,7 +309,7 @@
      * @deprecated This is an experimental API that is not intended for general use and is subject to change in future versions
      */
     @Deprecated
-    @Override protected List<CssMetaData> impl_getControlStyleableProperties() {
+    @Override protected List<CssMetaData> getControlCssMetaData() {
         return getClassCssMetaData();
     }
 
--- a/javafx-ui-controls/src/javafx/scene/control/SkinBase.java	Fri Jan 11 18:42:21 2013 -0800
+++ b/javafx-ui-controls/src/javafx/scene/control/SkinBase.java	Mon Jan 14 15:16:41 2013 +1300
@@ -65,12 +65,7 @@
      */
     private ObservableList<Node> children;
     
-    /**
-     * This is part of the workaround introduced during delomboking. We probably will
-     * want to adjust the way listeners are added rather than continuing to use this
-     * map (although it doesn't really do much harm).
-     */
-    private MultiplePropertyChangeListenerHandler changeListenerHandler;
+    
     
     /***************************************************************************
      *                                                                         *
@@ -93,6 +88,8 @@
         }
     };
     
+    
+    
     /***************************************************************************
      *                                                                         *
      * Constructor                                                             *
@@ -137,11 +134,6 @@
 
     /** {@inheritDoc} */
     @Override public void dispose() { 
-        // unhook listeners
-        if (changeListenerHandler != null) {
-            changeListenerHandler.dispose();
-        }
-
 //        control.removeEventHandler(ContextMenuEvent.CONTEXT_MENU_REQUESTED, contextMenuHandler);
 
         this.control = null;
@@ -175,33 +167,6 @@
     }
     
     /**
-     * Subclasses can invoke this method to register that we want to listen to
-     * property change events for the given property.
-     *
-     * @param property
-     * @param reference
-     */
-    protected final void registerChangeListener(ObservableValue property, String reference) {
-        if (changeListenerHandler == null) {
-            changeListenerHandler = new MultiplePropertyChangeListenerHandler(new Callback<String, Void>() {
-                @Override public Void call(String p) {
-                    handleControlPropertyChanged(p);
-                    return null;
-                }
-            });
-        }
-        changeListenerHandler.registerChangeListener(property, reference);
-    }
-    
-    /**
-     * Skin subclasses will override this method to handle changes in corresponding
-     * control's properties.
-     */
-    protected void handleControlPropertyChanged(String propertyReference) {
-        // no-op
-    }
-    
-    /**
      * Determines whether all mouse events should be automatically consumed.
      */
     protected final void consumeMouseEvents(boolean value) {
@@ -450,8 +415,7 @@
     /** 
      * @return The CssMetaData associated with this class, which may include the
      * CssMetaData of its super classes.
-     */
-    public static List<CssMetaData> getClassCssMetaData() {
+     */    public static List<CssMetaData> getClassCssMetaData() {
         return SkinBase.StyleableProperties.STYLEABLES;
     }
 
--- a/javafx-ui-controls/src/javafx/scene/control/Slider.java	Fri Jan 11 18:42:21 2013 -0800
+++ b/javafx-ui-controls/src/javafx/scene/control/Slider.java	Mon Jan 14 15:16:41 2013 +1300
@@ -791,7 +791,7 @@
      * @deprecated This is an experimental API that is not intended for general use and is subject to change in future versions
      */
     @Deprecated
-    @Override protected List<CssMetaData> impl_getControlStyleableProperties() {
+    @Override protected List<CssMetaData> getControlCssMetaData() {
         return getClassCssMetaData();
     }
 
--- a/javafx-ui-controls/src/javafx/scene/control/SplitPane.java	Fri Jan 11 18:42:21 2013 -0800
+++ b/javafx-ui-controls/src/javafx/scene/control/SplitPane.java	Mon Jan 14 15:16:41 2013 +1300
@@ -418,7 +418,7 @@
      * {@inheritDoc}
      */
     @Override
-    public List<CssMetaData> getCssMetaData() {
+    public List<CssMetaData> getControlCssMetaData() {
         return getClassCssMetaData();
     }
 
--- a/javafx-ui-controls/src/javafx/scene/control/TabPane.java	Fri Jan 11 18:42:21 2013 -0800
+++ b/javafx-ui-controls/src/javafx/scene/control/TabPane.java	Mon Jan 14 15:16:41 2013 +1300
@@ -580,7 +580,7 @@
      * {@inheritDoc}
      */
     @Override
-    public List<CssMetaData> getCssMetaData() {
+    public List<CssMetaData> getControlCssMetaData() {
         return getClassCssMetaData();
     }
 
--- a/javafx-ui-controls/src/javafx/scene/control/TableColumn.java	Fri Jan 11 18:42:21 2013 -0800
+++ b/javafx-ui-controls/src/javafx/scene/control/TableColumn.java	Mon Jan 14 15:16:41 2013 +1300
@@ -429,10 +429,10 @@
                     TableView table = getTableView();
                     if (table == null) return;
                     Map properties = table.getProperties();
-                    if (properties.containsKey(TableViewSkinBase.RECREATE)) {
-                        properties.remove(TableViewSkinBase.RECREATE);
+                    if (properties.containsKey(TableViewSkinBase.REBUILD)) {
+                        properties.remove(TableViewSkinBase.REBUILD);
                     }
-                    properties.put(TableViewSkinBase.RECREATE, Boolean.TRUE);
+                    properties.put(TableViewSkinBase.REBUILD, Boolean.TRUE);
                 }
             };
 
--- a/javafx-ui-controls/src/javafx/scene/control/TableRow.java	Fri Jan 11 18:42:21 2013 -0800
+++ b/javafx-ui-controls/src/javafx/scene/control/TableRow.java	Mon Jan 14 15:16:41 2013 +1300
@@ -170,18 +170,19 @@
                         weakTableViewRef = null;
                     }
 
-                    if (getTableView() != null) {
-                        sm = getTableView().getSelectionModel();
+                    TableView tableView = getTableView();
+                    if (tableView != null) {
+                        sm = tableView.getSelectionModel();
                         if (sm != null) {
                             sm.getSelectedCells().addListener(weakSelectedListener);
                         }
 
-                        fm = getTableView().getFocusModel();
+                        fm = tableView.getFocusModel();
                         if (fm != null) {
                             fm.focusedCellProperty().addListener(weakFocusedListener);
                         }
 
-                        getTableView().editingCellProperty().addListener(weakEditingListener);
+                        tableView.editingCellProperty().addListener(weakEditingListener);
                         
                         weakTableViewRef = new WeakReference<TableView<T>>(get());
                     }
--- a/javafx-ui-controls/src/javafx/scene/control/TextField.java	Fri Jan 11 18:42:21 2013 -0800
+++ b/javafx-ui-controls/src/javafx/scene/control/TextField.java	Mon Jan 14 15:16:41 2013 +1300
@@ -298,7 +298,7 @@
      * {@inheritDoc}
      */
     @Override
-    public List<CssMetaData> getCssMetaData() {
+    public List<CssMetaData> getControlCssMetaData() {
         return getClassCssMetaData();
     }
 }
--- a/javafx-ui-controls/src/javafx/scene/control/TitledPane.java	Fri Jan 11 18:42:21 2013 -0800
+++ b/javafx-ui-controls/src/javafx/scene/control/TitledPane.java	Mon Jan 14 15:16:41 2013 +1300
@@ -327,7 +327,7 @@
      * {@inheritDoc}
      */
     @Override
-    public List<CssMetaData> getCssMetaData() {
+    public List<CssMetaData> getControlCssMetaData() {
         return getClassCssMetaData();
     }
 
--- a/javafx-ui-controls/src/javafx/scene/control/ToolBar.java	Fri Jan 11 18:42:21 2013 -0800
+++ b/javafx-ui-controls/src/javafx/scene/control/ToolBar.java	Mon Jan 14 15:16:41 2013 +1300
@@ -238,7 +238,7 @@
      * {@inheritDoc}
      */
     @Override
-    public List<CssMetaData> getCssMetaData() {
+    public List<CssMetaData> getControlCssMetaData() {
         return getClassCssMetaData();
     }
 
--- a/javafx-ui-controls/src/javafx/scene/control/TreeCell.java	Fri Jan 11 18:42:21 2013 -0800
+++ b/javafx-ui-controls/src/javafx/scene/control/TreeCell.java	Mon Jan 14 15:16:41 2013 +1300
@@ -391,15 +391,21 @@
      *                                                                         *
      **************************************************************************/
     
+    private int index = -1;
+    private int oldIndex = -1;
+    private TreeItem<T> treeItemRef;
+    
     /** {@inheritDoc} */
     @Override void indexChanged() {
         super.indexChanged();
+        index = getIndex();
         
         // when the cell index changes, this may result in the cell
         // changing state to be selected and/or focused.
         updateItem();
         updateSelection();
         updateFocus();
+        oldIndex = index;
     }
     
     private void updateItem() {
@@ -407,23 +413,21 @@
         if (tv == null) return;
         
         // Compute whether the index for this cell is for a real item
-        boolean valid = getIndex() >=0 && getIndex() < tv.getExpandedItemCount();
+        boolean valid = index >=0 && index < tv.getExpandedItemCount();
 
         // Cause the cell to update itself
         if (valid) {
             // update the TreeCell state.
             // get the new treeItem that is about to go in to the TreeCell
-            TreeItem<T> _treeItem = tv.getTreeItem(getIndex());
+            treeItemRef = oldIndex != index ? tv.getTreeItem(index) : treeItemRef;
         
             // For the sake of RT-14279, it is important that the order of these
             // method calls is as shown below. If the order is switched, it is
             // likely that events will be fired where the item is null, even
             // though calling cell.getTreeItem().getValue() returns the value
             // as expected
-            if (_treeItem == null || ! _treeItem.equals(getTreeItem())) {
-                updateTreeItem(_treeItem);
-                updateItem(_treeItem == null ? null : _treeItem.getValue(), false);
-            }
+            updateTreeItem(treeItemRef);
+            updateItem(treeItemRef == null ? null : treeItemRef.getValue(), false);
         } else {
             updateTreeItem(null);
             updateItem(null, true);
@@ -432,20 +436,20 @@
 
     private void updateSelection() {
         if (isEmpty()) return;
-        if (getIndex() == -1 || getTreeView() == null) return;
+        if (index == -1 || getTreeView() == null) return;
         if (getTreeView().getSelectionModel() == null) return;
         
-        boolean isSelected = getTreeView().getSelectionModel().isSelected(getIndex());
+        boolean isSelected = getTreeView().getSelectionModel().isSelected(index);
         if (isSelected() == isSelected) return;
         
         updateSelected(isSelected);
     }
 
     private void updateFocus() {
-        if (getIndex() == -1 || getTreeView() == null) return;
+        if (index == -1 || getTreeView() == null) return;
         if (getTreeView().getFocusModel() == null) return;
         
-        setFocused(getTreeView().getFocusModel().isFocused(getIndex()));
+        setFocused(getTreeView().getFocusModel().isFocused(index));
     }
 
     private boolean updateEditingIndex = true;
--- a/javafx-ui-controls/src/javafx/scene/control/TreeTableColumn.java	Fri Jan 11 18:42:21 2013 -0800
+++ b/javafx-ui-controls/src/javafx/scene/control/TreeTableColumn.java	Mon Jan 14 15:16:41 2013 +1300
@@ -422,10 +422,10 @@
                     TreeTableView table = getTreeTableView();
                     if (table == null) return;
                     Map properties = table.getProperties();
-                    if (properties.containsKey(TableViewSkinBase.RECREATE)) {
-                        properties.remove(TableViewSkinBase.RECREATE);
+                    if (properties.containsKey(TableViewSkinBase.REBUILD)) {
+                        properties.remove(TableViewSkinBase.REBUILD);
                     }
-                    properties.put(TableViewSkinBase.RECREATE, Boolean.TRUE);
+                    properties.put(TableViewSkinBase.REBUILD, Boolean.TRUE);
                 }
             };
     public final void setCellFactory(Callback<TreeTableColumn<S,T>, TreeTableCell<S,T>> value) {
--- a/javafx-ui-controls/src/javafx/scene/control/TreeTableRow.java	Fri Jan 11 18:42:21 2013 -0800
+++ b/javafx-ui-controls/src/javafx/scene/control/TreeTableRow.java	Mon Jan 14 15:16:41 2013 +1300
@@ -84,14 +84,17 @@
     
     private final InvalidationListener indexListener = new InvalidationListener() {
         @Override public void invalidated(Observable valueModel) {
+            index = getIndex();
+        
             // when the cell index changes, this may result in the cell
             // changing state to be selected and/or focused.
             updateItem();
             updateSelection();
             updateFocus();
+            oldIndex = index;
         }
     };
-
+    
     private final ListChangeListener selectedListener = new ListChangeListener() {
         @Override public void onChanged(ListChangeListener.Change c) {
             updateSelection();
@@ -110,9 +113,22 @@
         }
     };
     
+    private final InvalidationListener leafListener = new InvalidationListener() {
+        @Override public void invalidated(Observable valueModel) {
+            // necessary to update the disclosure node in the skin when the
+            // leaf property changes
+            TreeItem treeItem = getTreeItem();
+            if (treeItem != null) {
+                requestLayout();
+            }
+        }
+    };
+    
     private final WeakListChangeListener weakSelectedListener = new WeakListChangeListener(selectedListener);
     private final WeakInvalidationListener weakFocusedListener = new WeakInvalidationListener(focusedListener);
     private final WeakInvalidationListener weakEditingListener = new WeakInvalidationListener(editingListener);
+    private final WeakInvalidationListener weakLeafListener = new WeakInvalidationListener(leafListener);
+    
     
     
     /***************************************************************************
@@ -209,6 +225,7 @@
                 weakTreeTableViewRef = new WeakReference<TreeTableView<T>>(get());
             }
 
+            updateItem();
             requestLayout();
         }
     };
@@ -320,26 +337,30 @@
      *                                                                         *
      **************************************************************************/
     
+    private int index = -1;
+    private int oldIndex = -1;
+    private TreeItem<T> treeItemRef;
+    
     private void updateItem() {
         TreeTableView<T> tv = getTreeTableView();
         if (tv == null) return;
         
         // Compute whether the index for this cell is for a real item
-        boolean valid = getIndex() >=0 && getIndex() < tv.getExpandedItemCount();
+        boolean valid = index >=0 && index < tv.getExpandedItemCount();
 
-        // get the new treeItem that is about to go in to the TreeCell
-        TreeItem<T> treeItem = valid ? tv.getTreeItem(getIndex()) : null;
-        
         // Cause the cell to update itself
-        if (valid && treeItem != null) {
+        if (valid) {
             // update the TreeCell state.
+            // get the new treeItem that is about to go in to the TreeCell
+            treeItemRef = oldIndex != index ? tv.getTreeItem(index) : treeItemRef;
+            
             // For the sake of RT-14279, it is important that the order of these
             // method calls is as shown below. If the order is switched, it is
             // likely that events will be fired where the item is null, even
             // though calling cell.getTreeItem().getValue() returns the value
             // as expected
-            updateTreeItem(treeItem);
-            updateItem(treeItem.getValue(), false);
+            updateTreeItem(treeItemRef);
+            updateItem(treeItemRef == null ? null : treeItemRef.getValue(), false);
         } else {
             updateTreeItem(null);
             updateItem(null, true);
@@ -347,10 +368,14 @@
     }
 
     private void updateSelection() {
-        if (getIndex() == -1 || getTreeTableView() == null) return;
+        if (isEmpty()) return;
+        if (index == -1 || getTreeTableView() == null) return;
         if (getTreeTableView().getSelectionModel() == null) return;
         
-        updateSelected(getTreeTableView().getSelectionModel().isSelected(getIndex()));
+        boolean isSelected = getTreeTableView().getSelectionModel().isSelected(index);
+        if (isSelected() == isSelected) return;
+        
+        updateSelected(isSelected);
     }
 
     private void updateFocus() {
@@ -402,7 +427,14 @@
      *      for developers or designers to access this function directly.
      */
     public final void updateTreeItem(TreeItem<T> treeItem) {
+        TreeItem _treeItem = getTreeItem();
+        if (_treeItem != null) {
+            _treeItem.leafProperty().removeListener(weakLeafListener);
+        }
         setTreeItem(treeItem);
+        if (treeItem != null) {
+            treeItem.leafProperty().addListener(weakLeafListener);
+        }
     }
 
 
--- a/javafx-ui-controls/src/javafx/scene/control/TreeUtil.java	Fri Jan 11 18:42:21 2013 -0800
+++ b/javafx-ui-controls/src/javafx/scene/control/TreeUtil.java	Mon Jan 14 15:16:41 2013 +1300
@@ -68,7 +68,7 @@
         int idx = itemIndex - 1;
 
         TreeItem child;
-        for (int i = 0; i < children.size(); i++) {
+        for (int i = 0, max = children.size(); i < max; i++) {
             child = children.get(i);
             if (idx == 0) return child;
             
@@ -82,8 +82,8 @@
                 idx -= expandedChildCount;
                 continue;
             }
-            
-            TreeItem<T> result = getItem(child, idx ,treeItemCountDirty);
+
+            TreeItem<T> result = getItem(child, idx, treeItemCountDirty);
             if (result != null) return result;
             idx--;
         }
--- a/javafx-ui-controls/src/javafx/scene/control/cell/CellUtils.java	Fri Jan 11 18:42:21 2013 -0800
+++ b/javafx-ui-controls/src/javafx/scene/control/cell/CellUtils.java	Mon Jan 14 15:16:41 2013 +1300
@@ -28,6 +28,7 @@
 import javafx.beans.value.ObservableValue;
 import javafx.collections.ObservableList;
 import javafx.event.EventHandler;
+import javafx.scene.Node;
 import javafx.scene.control.Cell;
 import javafx.scene.control.ChoiceBox;
 import javafx.scene.control.ComboBox;
@@ -107,6 +108,13 @@
     static <T> void updateItem(
             final Cell<T> cell, ChoiceBox<T> choiceBox, 
             final StringConverter<T> converter) {
+        updateItem(cell, choiceBox, converter, null);
+    }
+    
+    static <T> void updateItem(
+            final Cell<T> cell, ChoiceBox<T> choiceBox, 
+            final StringConverter<T> converter,
+            final Node graphic) {
         if (cell.isEmpty()) {
             cell.setText(null);
             cell.setGraphic(null);
@@ -119,7 +127,7 @@
                 cell.setGraphic(choiceBox);
             } else {
                 cell.setText(getItemText(cell, converter));
-                cell.setGraphic(null);
+                cell.setGraphic(graphic);
             }
         }
     };
@@ -149,6 +157,13 @@
      **************************************************************************/  
     
     static <T> void updateItem(Cell<T> cell, TextField textField, StringConverter<T> converter) {
+        updateItem(cell, textField, converter, null);
+    }
+    
+    static <T> void updateItem(final Cell<T> cell, 
+                               final TextField textField, 
+                               final StringConverter<T> converter,
+                               final Node graphic) {
         if (cell.isEmpty()) {
             cell.setText(null);
             cell.setGraphic(null);
@@ -161,7 +176,7 @@
                 cell.setGraphic(textField);
             } else {
                 cell.setText(getItemText(cell, converter));
-                cell.setGraphic(null);
+                cell.setGraphic(graphic);
             }
         }
     }
@@ -207,11 +222,18 @@
     
     /***************************************************************************
      *                                                                         *
-     * TextField convenience                                                   *
+     * ComboBox convenience                                                   *
      *                                                                         *
      **************************************************************************/ 
     
     static <T> void updateItem(Cell<T> cell, ComboBox<T> comboBox, StringConverter<T> converter) {
+        updateItem(cell, comboBox, converter, null);
+    }
+    
+    static <T> void updateItem(final Cell<T> cell, 
+                               final ComboBox<T> comboBox, 
+                               final StringConverter<T> converter,
+                               final Node graphic) {
         if (cell.isEmpty()) {
             cell.setText(null);
             cell.setGraphic(null);
@@ -224,7 +246,7 @@
                 cell.setGraphic(comboBox);
             } else {
                 cell.setText(getItemText(cell, converter));
-                cell.setGraphic(null);
+                cell.setGraphic(graphic);
             }
         }
     };
--- a/javafx-ui-controls/src/javafx/scene/control/cell/CheckBoxTreeCell.java	Fri Jan 11 18:42:21 2013 -0800
+++ b/javafx-ui-controls/src/javafx/scene/control/cell/CheckBoxTreeCell.java	Mon Jan 14 15:16:41 2013 +1300
@@ -501,8 +501,11 @@
             StringConverter c = getConverter();
             Callback<TreeItem<T>, ObservableValue<Boolean>> callback = getSelectedStateCallback();
             
+            TreeItem<T> treeItem = getTreeItem();
+            
             // update the node content
-            setText(c.toString(getTreeItem()));
+            setText(c.toString(treeItem));
+            checkBox.setGraphic(treeItem == null ? null : treeItem.getGraphic());
             setGraphic(checkBox);
             
             // uninstall bindings
@@ -515,15 +518,15 @@
 
             // install new bindings.
             // We special case things when the TreeItem is a CheckBoxTreeItem
-            if (getTreeItem() instanceof CheckBoxTreeItem) {
-                CheckBoxTreeItem<T> cbti = (CheckBoxTreeItem<T>) getTreeItem();
+            if (treeItem instanceof CheckBoxTreeItem) {
+                CheckBoxTreeItem<T> cbti = (CheckBoxTreeItem<T>) treeItem;
                 booleanProperty = cbti.selectedProperty();
                 checkBox.selectedProperty().bindBidirectional((BooleanProperty)booleanProperty);
                 
                 indeterminateProperty = cbti.indeterminateProperty();
                 checkBox.indeterminateProperty().bindBidirectional(indeterminateProperty);
             } else {
-                booleanProperty = callback.call(getTreeItem());
+                booleanProperty = callback.call(treeItem);
                 if (booleanProperty != null) {
                     checkBox.selectedProperty().bindBidirectional((BooleanProperty)booleanProperty);
                 }
--- a/javafx-ui-controls/src/javafx/scene/control/cell/ChoiceBoxTreeCell.java	Fri Jan 11 18:42:21 2013 -0800
+++ b/javafx-ui-controls/src/javafx/scene/control/cell/ChoiceBoxTreeCell.java	Mon Jan 14 15:16:41 2013 +1300
@@ -29,6 +29,7 @@
 import javafx.beans.property.SimpleObjectProperty;
 import javafx.collections.FXCollections;
 import javafx.collections.ObservableList;
+import javafx.scene.Node;
 import javafx.scene.control.*;
 import javafx.util.Callback;
 import javafx.util.StringConverter;
@@ -310,6 +311,9 @@
     /** {@inheritDoc} */
     @Override public void updateItem(T item, boolean empty) {
         super.updateItem(item, empty);
-        CellUtils.updateItem(this, choiceBox, getConverter());
+        
+        TreeItem<T> treeItem = getTreeItem();
+        Node graphic = treeItem == null ? null : treeItem.getGraphic();
+        CellUtils.updateItem(this, choiceBox, getConverter(), graphic);
     };
 }
\ No newline at end of file
--- a/javafx-ui-controls/src/javafx/scene/control/cell/ComboBoxTreeCell.java	Fri Jan 11 18:42:21 2013 -0800
+++ b/javafx-ui-controls/src/javafx/scene/control/cell/ComboBoxTreeCell.java	Mon Jan 14 15:16:41 2013 +1300
@@ -31,6 +31,7 @@
 import javafx.beans.property.SimpleObjectProperty;
 import javafx.collections.FXCollections;
 import javafx.collections.ObservableList;
+import javafx.scene.Node;
 import javafx.scene.control.*;
 import javafx.util.Callback;
 import javafx.util.StringConverter;
@@ -339,6 +340,9 @@
     /** {@inheritDoc} */
     @Override public void updateItem(T item, boolean empty) {
         super.updateItem(item, empty);
-        CellUtils.updateItem(this, comboBox, getConverter());
+        
+        TreeItem<T> treeItem = getTreeItem();
+        Node graphic = treeItem == null ? null : treeItem.getGraphic();
+        CellUtils.updateItem(this, comboBox, getConverter(), graphic);
     };
 }
\ No newline at end of file
--- a/javafx-ui-controls/src/javafx/scene/control/cell/TextFieldTreeCell.java	Fri Jan 11 18:42:21 2013 -0800
+++ b/javafx-ui-controls/src/javafx/scene/control/cell/TextFieldTreeCell.java	Mon Jan 14 15:16:41 2013 +1300
@@ -26,9 +26,11 @@
 
 import javafx.beans.property.ObjectProperty;
 import javafx.beans.property.SimpleObjectProperty;
+import javafx.scene.Node;
 import javafx.scene.control.Label;
 import javafx.scene.control.TextField;
 import javafx.scene.control.TreeCell;
+import javafx.scene.control.TreeItem;
 import javafx.scene.control.TreeView;
 import javafx.util.Callback;
 import javafx.util.StringConverter;
@@ -205,6 +207,9 @@
     /** {@inheritDoc} */
     @Override public void updateItem(T item, boolean empty) {
         super.updateItem(item, empty);
-        CellUtils.updateItem(this, textField, getConverter());
+        
+        TreeItem<T> treeItem = getTreeItem();
+        Node graphic = treeItem == null ? null : treeItem.getGraphic();
+        CellUtils.updateItem(this, textField, getConverter(), graphic);
     }
 }
\ No newline at end of file
--- a/javafx-ui-controls/test/com/sun/javafx/scene/control/skin/VirtualFlowTest.java	Fri Jan 11 18:42:21 2013 -0800
+++ b/javafx-ui-controls/test/com/sun/javafx/scene/control/skin/VirtualFlowTest.java	Mon Jan 14 15:16:41 2013 +1300
@@ -42,7 +42,7 @@
     // The VirtualFlow we are going to test. By default, there are 100 cells
     // and each cell is 100 wide and 25 tall, except for the 30th cell, which
     // is 200 wide and 100 tall.
-    private VirtualFlow flow;
+    private VirtualFlow<IndexedCell> flow;
 //    private Scene scene;
 
     @Before public void setUp() {
@@ -104,7 +104,7 @@
     /**
      * Asserts that only the minimal number of cells are used.
      */
-    public void assertMinimalNumberOfCellsAreUsed(VirtualFlow flow) {
+    public <T extends IndexedCell> void assertMinimalNumberOfCellsAreUsed(VirtualFlow<T> flow) {
         pulse();
         IndexedCell firstCell = flow.cells.getFirst();
         IndexedCell lastCell = flow.cells.getLast();