changeset 116:4970348dbafd 2.1-b04

Automated merge with ssh://jfxsrc.us.oracle.com//javafx/2.1/MASTER/jfx/rt
author David Grieve<david.grieve@oracle.com>
date Tue, 06 Dec 2011 10:01:57 -0500
parents d07657025137 2b29532ca4c9
children 8b6d03b2f545 1145eb73b1b1
files
diffstat 48 files changed, 877 insertions(+), 297 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.classpath	Tue Dec 06 10:01:57 2011 -0500
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="javafx-ui-controls/src"/>
+	<classpathentry kind="src" path="javafx-ui-controls/test"/>
+	<classpathentry kind="src" path="javafx-ui-controls/build/builders"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
+	<classpathentry kind="src" path="/rt-closed"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.project	Tue Dec 06 10:01:57 2011 -0500
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>rt</name>
+	<comment></comment>
+	<projects>
+	</projects>
+  <buildSpec>
+    <buildCommand>
+      <name>org.eclipse.jdt.core.javabuilder</name>
+      <arguments>
+      </arguments>
+    </buildCommand>
+  </buildSpec>
+  <natures>
+    <nature>org.eclipse.jdt.core.javanature</nature>
+  </natures>
+</projectDescription>
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/ComboBoxBaseBehavior.java	Thu Dec 01 10:13:04 2011 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/ComboBoxBaseBehavior.java	Tue Dec 06 10:01:57 2011 -0500
@@ -83,27 +83,27 @@
     private static final String PRESS_ACTION = "Press";
     private static final String RELEASE_ACTION = "Release";
 
-    protected static final List<KeyBinding> BUTTON_BINDINGS = new ArrayList<KeyBinding>();
+    protected static final List<KeyBinding> COMBO_BOX_BASE_BINDINGS = new ArrayList<KeyBinding>();
     static {
-        BUTTON_BINDINGS.add(new KeyBinding(F4, "togglePopup"));
-        BUTTON_BINDINGS.add(new KeyBinding(UP, "togglePopup").alt());
-        BUTTON_BINDINGS.add(new KeyBinding(DOWN, "togglePopup").alt());
+        COMBO_BOX_BASE_BINDINGS.add(new KeyBinding(F4, "togglePopup"));
+        COMBO_BOX_BASE_BINDINGS.add(new KeyBinding(UP, "togglePopup").alt());
+        COMBO_BOX_BASE_BINDINGS.add(new KeyBinding(DOWN, "togglePopup").alt());
         
         if (Utils.isWindows()) {
-            BUTTON_BINDINGS.add(new KeyBinding(ENTER, KEY_PRESSED, PRESS_ACTION));
-            BUTTON_BINDINGS.add(new KeyBinding(ENTER, KEY_RELEASED, RELEASE_ACTION));
-            BUTTON_BINDINGS.add(new KeyBinding(SPACE, KEY_PRESSED, PRESS_ACTION));
-            BUTTON_BINDINGS.add(new KeyBinding(SPACE, KEY_RELEASED, RELEASE_ACTION));
+            COMBO_BOX_BASE_BINDINGS.add(new KeyBinding(ENTER, KEY_PRESSED, PRESS_ACTION));
+            COMBO_BOX_BASE_BINDINGS.add(new KeyBinding(ENTER, KEY_RELEASED, RELEASE_ACTION));
+            COMBO_BOX_BASE_BINDINGS.add(new KeyBinding(SPACE, KEY_PRESSED, PRESS_ACTION));
+            COMBO_BOX_BASE_BINDINGS.add(new KeyBinding(SPACE, KEY_RELEASED, RELEASE_ACTION));
         } else {
-            BUTTON_BINDINGS.add(new KeyBinding(SPACE, KEY_PRESSED, PRESS_ACTION));
-            BUTTON_BINDINGS.add(new KeyBinding(SPACE, KEY_RELEASED, RELEASE_ACTION));
+            COMBO_BOX_BASE_BINDINGS.add(new KeyBinding(SPACE, KEY_PRESSED, PRESS_ACTION));
+            COMBO_BOX_BASE_BINDINGS.add(new KeyBinding(SPACE, KEY_RELEASED, RELEASE_ACTION));
         }
         
-        BUTTON_BINDINGS.addAll(TRAVERSAL_BINDINGS);
+        COMBO_BOX_BASE_BINDINGS.addAll(TRAVERSAL_BINDINGS);
     }
 
     @Override protected List<KeyBinding> createKeyBindings() {
-        return BUTTON_BINDINGS;
+        return COMBO_BOX_BASE_BINDINGS;
     }
 
     @Override protected void callAction(String name) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/ComboBoxListViewBehavior.java	Tue Dec 06 10:01:57 2011 -0500
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.javafx.scene.control.behavior;
+
+import com.javafx.preview.control.ComboBox;
+import com.javafx.preview.control.ComboBoxBase;
+import javafx.beans.Observable;
+import static javafx.scene.input.KeyCode.*;
+import static javafx.scene.input.KeyEvent.*;
+
+import com.sun.javafx.Utils;
+
+import javafx.scene.input.MouseEvent;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javafx.beans.InvalidationListener;
+import javafx.scene.control.SelectionModel;
+import javafx.scene.input.MouseButton;
+
+public class ComboBoxListViewBehavior<T> extends ComboBoxBaseBehavior<T> {
+
+    /***************************************************************************
+     *                                                                         *
+     * Constructors                                                            *
+     *                                                                         *
+     **************************************************************************/
+    
+    /**
+     * 
+     */
+    public ComboBoxListViewBehavior(final ComboBox<T> comboBox) {
+        super(comboBox);
+    }
+
+    /***************************************************************************
+     *                                                                         *
+     * Key event handling                                                      *
+     *                                                                         *
+     **************************************************************************/
+
+    protected static final List<KeyBinding> COMBO_BOX_BINDINGS = new ArrayList<KeyBinding>();
+    static {
+        COMBO_BOX_BINDINGS.add(new KeyBinding(UP, KEY_PRESSED, "selectPrevious"));
+        COMBO_BOX_BINDINGS.add(new KeyBinding(DOWN, "selectNext"));
+        COMBO_BOX_BINDINGS.addAll(COMBO_BOX_BASE_BINDINGS);
+    }
+
+    @Override protected List<KeyBinding> createKeyBindings() {
+        return COMBO_BOX_BINDINGS;
+    }
+
+    @Override protected void callAction(String name) {
+        if ("selectPrevious".equals(name)) {
+            selectPrevious();
+        } else if ("selectNext".equals(name)) {
+            selectNext();
+        } else {
+            super.callAction(name);
+        }
+    }
+    
+    private ComboBox<T> getComboBox() {
+        return (ComboBox<T>) getControl();
+    }
+
+    private void selectPrevious() {
+        SelectionModel sm = getComboBox().getSelectionModel();
+        if (sm == null) return;
+        sm.selectPrevious();
+    }
+    
+    private void selectNext() {
+        SelectionModel sm = getComboBox().getSelectionModel();
+        if (sm == null) return;
+        sm.selectNext();
+    }
+}
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/ListCellBehavior.java	Thu Dec 01 10:13:04 2011 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/ListCellBehavior.java	Tue Dec 06 10:01:57 2011 -0500
@@ -86,12 +86,10 @@
             latePress = false;
             doSelect(event);
         }
-        event.consume();
     }
     
     @Override public void mouseDragged(MouseEvent event) {
         latePress = false;
-        event.consume();
     }
     
     private void doSelect(MouseEvent e) {
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/TableCellBehavior.java	Thu Dec 01 10:13:04 2011 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/TableCellBehavior.java	Tue Dec 06 10:01:57 2011 -0500
@@ -81,12 +81,10 @@
             latePress = false;
             doSelect(event);
         }
-        event.consume();
     }
     
     @Override public void mouseDragged(MouseEvent event) {
         latePress = false;
-        event.consume();
     }
 
     private void doSelect(MouseEvent e) {
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/TextAreaBehavior.java	Thu Dec 01 10:13:04 2011 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/TextAreaBehavior.java	Tue Dec 06 10:01:57 2011 -0500
@@ -51,6 +51,8 @@
     static {
         TEXT_AREA_BINDINGS.add(new KeyBinding(TAB, KEY_PRESSED, "TraverseNext").ctrl());
         TEXT_AREA_BINDINGS.add(new KeyBinding(TAB, KEY_PRESSED, "TraversePrevious").ctrl().shift());
+        TEXT_AREA_BINDINGS.add(new KeyBinding(HOME, KEY_PRESSED, "LineStart")); // changed
+        TEXT_AREA_BINDINGS.add(new KeyBinding(END, KEY_PRESSED, "LineEnd")); // changed
         TEXT_AREA_BINDINGS.add(new KeyBinding(UP, KEY_PRESSED, "PreviousLine")); // changed
         TEXT_AREA_BINDINGS.add(new KeyBinding(KP_UP, KEY_PRESSED, "PreviousLine")); // changed
         TEXT_AREA_BINDINGS.add(new KeyBinding(DOWN, KEY_PRESSED, "NextLine")); // changed
@@ -60,6 +62,8 @@
         TEXT_AREA_BINDINGS.add(new KeyBinding(ENTER, KEY_PRESSED, "InsertNewLine")); // changed
         TEXT_AREA_BINDINGS.add(new KeyBinding(TAB, KEY_PRESSED, "InsertTab")); // changed
 
+        TEXT_AREA_BINDINGS.add(new KeyBinding(HOME, KEY_PRESSED, "SelectLineStart").shift()); // changed
+        TEXT_AREA_BINDINGS.add(new KeyBinding(END, KEY_PRESSED, "SelectLineEnd").shift()); // changed
         TEXT_AREA_BINDINGS.add(new KeyBinding(UP, KEY_PRESSED, "SelectPreviousLine").shift()); // changed
         TEXT_AREA_BINDINGS.add(new KeyBinding(KP_UP, KEY_PRESSED, "SelectPreviousLine").shift()); // changed
         TEXT_AREA_BINDINGS.add(new KeyBinding(DOWN, KEY_PRESSED, "SelectNextLine").shift()); // changed
@@ -86,11 +90,6 @@
             TEXT_AREA_BINDINGS.add(new KeyBinding(DOWN, KEY_PRESSED, "SelectParagraphEnd").meta().shift());
             TEXT_AREA_BINDINGS.add(new KeyBinding(KP_DOWN, KEY_PRESSED, "SelectParagraphEnd").meta().shift());
         } else {
-            TEXT_AREA_BINDINGS.add(new KeyBinding(HOME, KEY_PRESSED, "LineStart")); // changed
-            TEXT_AREA_BINDINGS.add(new KeyBinding(END, KEY_PRESSED, "LineEnd")); // changed
-            TEXT_AREA_BINDINGS.add(new KeyBinding(HOME, KEY_PRESSED, "SelectLineStart").shift()); // changed
-            TEXT_AREA_BINDINGS.add(new KeyBinding(END, KEY_PRESSED, "SelectLineEnd").shift()); // changed
-
             TEXT_AREA_BINDINGS.add(new KeyBinding(UP, KEY_PRESSED, "ParagraphStart").ctrl());
             TEXT_AREA_BINDINGS.add(new KeyBinding(KP_UP, KEY_PRESSED, "ParagraphStart").ctrl());
             TEXT_AREA_BINDINGS.add(new KeyBinding(DOWN, KEY_PRESSED, "ParagraphEnd").ctrl());
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/TextInputControlBehavior.java	Thu Dec 01 10:13:04 2011 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/TextInputControlBehavior.java	Tue Dec 06 10:01:57 2011 -0500
@@ -134,7 +134,6 @@
             else if ("Unselect".equals(name)) textInputControl.deselect();
             else if ("SelectHome".equals(name)) selectHome();
             else if ("SelectEnd".equals(name)) selectEnd();
-            else if ("ShowContextMenu".equals(name)) showContextMenu();
             else super.callAction(name);
             setCaretAnimating(true);
         } else if ("Copy".equals(name)) {
@@ -235,12 +234,6 @@
         }
     }
 
-    public void showContextMenu() {
-        if (getControl().getSkin() instanceof SkinBase) {
-            ((SkinBase)getControl().getSkin()).showContextMenu();
-        }
-    }
-
     private void selectEnd() {
         TextInputControl textInputControl = getControl();
         if (macOS) {
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/TextInputControlBindings.java	Thu Dec 01 10:13:04 2011 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/TextInputControlBindings.java	Tue Dec 06 10:01:57 2011 -0500
@@ -70,12 +70,11 @@
         BINDINGS.add(new KeyBinding(DOWN, KEY_PRESSED,        "SelectEnd").shift());
         BINDINGS.add(new KeyBinding(KP_DOWN, KEY_PRESSED,     "SelectEnd").shift());
         BINDINGS.add(new KeyBinding(END, KEY_PRESSED,         "SelectEnd").shift());
-        // context menu
-        BINDINGS.add(new KeyBinding(CONTEXT_MENU, KEY_PRESSED, "ShowContextMenu"));
-        BINDINGS.add(new KeyBinding(F10, KEY_PRESSED,          "ShowContextMenu").shift());
 
         // platform specific settings
         if (PlatformUtil.isMac()) {
+            BINDINGS.add(new KeyBinding(HOME, KEY_PRESSED,       "Home").meta());
+            BINDINGS.add(new KeyBinding(END, KEY_PRESSED,        "End").meta());
             BINDINGS.add(new KeyBinding(LEFT, KEY_PRESSED,       "Home").meta());
             BINDINGS.add(new KeyBinding(KP_LEFT, KEY_PRESSED,    "Home").meta());
             BINDINGS.add(new KeyBinding(RIGHT, KEY_PRESSED,      "End").meta());
@@ -88,6 +87,8 @@
             BINDINGS.add(new KeyBinding(C, KEY_PRESSED,          "Copy").meta());
             BINDINGS.add(new KeyBinding(INSERT, KEY_PRESSED,     "Copy").meta());
             BINDINGS.add(new KeyBinding(V, KEY_PRESSED,          "Paste").meta());
+            BINDINGS.add(new KeyBinding(HOME, KEY_PRESSED,       "SelectHome").shift().meta());
+            BINDINGS.add(new KeyBinding(END, KEY_PRESSED,        "SelectEnd").shift().meta());
             BINDINGS.add(new KeyBinding(LEFT, KEY_PRESSED,       "SelectHome").shift().meta());
             BINDINGS.add(new KeyBinding(KP_LEFT, KEY_PRESSED,    "SelectHome").shift().meta());
             BINDINGS.add(new KeyBinding(RIGHT, KEY_PRESSED,      "SelectEnd").shift().meta());
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/TreeCellBehavior.java	Thu Dec 01 10:13:04 2011 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/behavior/TreeCellBehavior.java	Tue Dec 06 10:01:57 2011 -0500
@@ -83,12 +83,10 @@
             latePress = false;
             doSelect(event);
         }
-        event.consume();
     }
     
     @Override public void mouseDragged(MouseEvent event) {
         latePress = false;
-        event.consume();
     }
     
     private void doSelect(MouseEvent event) {
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/CheckBoxSkin.java	Thu Dec 01 10:13:04 2011 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/CheckBoxSkin.java	Tue Dec 06 10:01:57 2011 -0500
@@ -59,12 +59,12 @@
     }
 
     @Override protected double computePrefWidth(double height) {
-        return super.computePrefWidth(height) + snapSize(box.prefWidth(height));
+        return super.computePrefWidth(height) + snapSize(box.prefWidth(-1));
     }
 
     @Override protected double computePrefHeight(double width) {
-        return Math.max(super.computePrefHeight(width),
-                        getInsets().getTop() + box.prefHeight(width) + getInsets().getBottom());
+        return Math.max(super.computePrefHeight(width - box.prefWidth(-1)),
+                        getInsets().getTop() + box.prefHeight(-1) + getInsets().getBottom());
     }
 
 
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ComboBoxBaseSkin.java	Thu Dec 01 10:13:04 2011 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ComboBoxBaseSkin.java	Tue Dec 06 10:01:57 2011 -0500
@@ -42,10 +42,10 @@
     protected StackPane arrowButton;
     protected StackPane arrow;
     
-    public ComboBoxBaseSkin(final ComboBoxBase<T> comboBox) {
+    public ComboBoxBaseSkin(final ComboBoxBase<T> comboBox, final ComboBoxBaseBehavior behavior) {
         // Call the super method with the button we were just given in the 
         // constructor, as well as an instance of the behavior class.
-        super(comboBox, new ComboBoxBaseBehavior(comboBox));
+        super(comboBox, behavior);//new ComboBoxBaseBehavior(comboBox));
         
         // open button / arrow
         arrow = new StackPane();
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ComboBoxListViewSkin.java	Thu Dec 01 10:13:04 2011 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ComboBoxListViewSkin.java	Tue Dec 06 10:01:57 2011 -0500
@@ -26,10 +26,12 @@
 package com.sun.javafx.scene.control.skin;
 
 import com.javafx.preview.control.ComboBox;
+import com.sun.javafx.scene.control.behavior.ComboBoxListViewBehavior;
 import javafx.beans.InvalidationListener;
 import javafx.beans.Observable;
 import javafx.beans.value.ChangeListener;
 import javafx.beans.value.ObservableValue;
+import javafx.collections.ObservableList;
 import javafx.event.EventHandler;
 import javafx.scene.Node;
 import javafx.scene.control.*;
@@ -49,7 +51,7 @@
     private final ListView<T> listView;
     
     public ComboBoxListViewSkin(final ComboBox<T> comboBox) {
-        super(comboBox);
+        super(comboBox, new ComboBoxListViewBehavior<T>(comboBox));
         this.comboBox = comboBox;
         this.listView = createListView();
         
@@ -62,8 +64,33 @@
             }
         });
         
+        updateItemsListener(null, comboBox.getItems());
+        comboBox.itemsProperty().addListener(new ChangeListener<ObservableList<T>>() {
+            @Override 
+            public void changed(ObservableValue<? extends ObservableList<T>> ov, ObservableList<T> t, ObservableList<T> t1) {
+                updateItemsListener(t, t1);
+            }
+        });
+        
         registerChangeListener(comboBox.promptTextProperty(), "PROMPT_TEXT");
     }
+    
+    private boolean itemCountDirty = false;
+    private InvalidationListener itemsListener = new InvalidationListener() {
+        @Override public void invalidated(Observable o) {
+            itemCountDirty = true;
+            requestLayout();
+        }
+    };
+    
+    private void updateItemsListener(ObservableList<T> oldList, ObservableList<T> newList) {
+        if (oldList != null) {
+            oldList.removeListener(itemsListener);
+        }
+        if (newList != null) {
+            newList.addListener(itemsListener);
+        }
+    }
 
     @Override protected void handleControlPropertyChanged(String p) {
         super.handleControlPropertyChanged(p);
@@ -150,8 +177,6 @@
         }
     }
     
-    
-    
     private ListCell<T> getListCellLabel() {
         if (listCellLabel != null) return listCellLabel;
         
@@ -173,28 +198,43 @@
     
     private ListView<T> createListView() {
         final ListView<T> listView = new ListView<T>() {
+            
+            @Override protected double computeMinHeight(double width) {
+                return 30;
+            }
+            
             @Override protected double computePrefWidth(double height) {
                 doCSSCheck();
                 
-                if (getSkin() instanceof VirtualContainerBase) {
-                    VirtualContainerBase skin = (VirtualContainerBase)getSkin();
-                    return skin.getVirtualFlowPreferredWidth(height) + 10;
+                double pw;
+                if (getSkin() instanceof ListViewSkin) {
+                    ListViewSkin skin = (ListViewSkin)getSkin();
+                    if (itemCountDirty) {
+                        skin.updateCellCount();
+                        itemCountDirty = false;
+                    }
+                    pw = skin.getVirtualFlowPreferredWidth(height) + 10;
                 } else {
-                    return Math.max(100, comboBox.getWidth());
+                    pw = Math.max(100, comboBox.getWidth());
                 }
+                
+                return Math.max(50, pw);
             }
 
             @Override protected double computePrefHeight(double width) {
                 doCSSCheck();
                 
+                double ph;
                 if (getSkin() instanceof VirtualContainerBase) {
                     int maxRows = comboBox.getVisibleRowCount();
                     VirtualContainerBase skin = (VirtualContainerBase)getSkin();
-                    return skin.getVirtualFlowPreferredHeight(maxRows);
+                    ph = skin.getVirtualFlowPreferredHeight(maxRows);
                 } else {
                     double ch = comboBox.getItems().size() * 25;
-                    return Math.min(ch, 200);
+                    ph = Math.min(ch, 200);
                 }
+                
+                return ph;
             }
             
             private void doCSSCheck() {
@@ -217,6 +257,12 @@
                 int index = listView.getSelectionModel().getSelectedIndex();
                 comboBox.getSelectionModel().select(index);
                 comboBox.setValue(listView.getSelectionModel().getSelectedItem());
+                updateDisplayNode();
+            }
+        });
+        
+        listView.addEventFilter(MouseEvent.MOUSE_RELEASED, new EventHandler<MouseEvent>() {
+            @Override public void handle(MouseEvent t) {
                 comboBox.hide();
             }
         });
@@ -238,4 +284,8 @@
     @Override protected double computePrefWidth(double height) {
         return listView.prefWidth(height);
     }
+    
+    @Override protected double computeMinWidth(double height) {
+        return 50;
+    }
 }
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ComboBoxPopupControl.java	Thu Dec 01 10:13:04 2011 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ComboBoxPopupControl.java	Tue Dec 06 10:01:57 2011 -0500
@@ -26,6 +26,7 @@
 package com.sun.javafx.scene.control.skin;
 
 import com.javafx.preview.control.ComboBoxBase;
+import com.sun.javafx.scene.control.behavior.ComboBoxBaseBehavior;
 import javafx.event.Event;
 import javafx.event.EventHandler;
 import javafx.geometry.HPos;
@@ -40,8 +41,8 @@
     
     private PopupControl popup;
 
-    public ComboBoxPopupControl(ComboBoxBase<T> comboBox) {
-        super(comboBox);
+    public ComboBoxPopupControl(ComboBoxBase<T> comboBox, final ComboBoxBaseBehavior behavior) {
+        super(comboBox, behavior);
     }
     
     /**
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/LabeledSkinBase.java	Thu Dec 01 10:13:04 2011 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/LabeledSkinBase.java	Tue Dec 06 10:01:57 2011 -0500
@@ -52,8 +52,8 @@
 import com.sun.javafx.scene.control.behavior.BehaviorBase;
 import com.sun.javafx.scene.control.behavior.TextBinding;
 
+import static javafx.scene.control.ContentDisplay.*;
 import static javafx.scene.control.OverrunStyle.*;
-import static com.sun.javafx.scene.control.skin.Utils.*;
 
 public abstract class LabeledSkinBase<C extends Labeled, B extends BehaviorBase<C>> extends SkinBase<C, B> {
 
@@ -385,10 +385,14 @@
             Insets padding = getInsets();
             Insets labelPadding = labeled.getLabelPadding();
 
+            double availableWidth = labeled.getWidth() - padding.getLeft() - padding.getRight() -
+                                    labelPadding.getLeft() - labelPadding.getRight();
+            availableWidth = Math.max(availableWidth, 0);
+
             if (w == -1) {
-                w = labeled.getWidth() - padding.getLeft() - padding.getRight() - labelPadding.getLeft() - labelPadding.getRight();
+                w = availableWidth;
             }
-            double minW = Math.min(minWidth(-1), labeled.getWidth());
+            double minW = Math.min(minWidth(-1), availableWidth);
             if (horizontalPosition && !isIgnoreGraphic()) {
                 double graphicW = (labeled.getGraphic().getLayoutBounds().getWidth() + labeled.getGraphicTextGap());
                 w -= graphicW;
@@ -400,10 +404,14 @@
                     (labeled.getContentDisplay() == ContentDisplay.TOP ||
                     labeled.getContentDisplay() == ContentDisplay.BOTTOM);
 
+            double availableHeight = labeled.getHeight() - padding.getTop() - padding.getBottom() -
+                                     labelPadding.getTop() - labelPadding.getBottom();
+            availableHeight = Math.max(availableHeight, 0);
+
             if (h == -1) {
-                h = labeled.getHeight() - padding.getTop() - padding.getBottom() - labelPadding.getTop() - labelPadding.getBottom();
+                h = availableHeight;
             }
-            double minH = minHeight(w);
+            double minH = Math.min(minHeight(w), availableHeight);
             if (verticalPosition && labeled.getGraphic() != null) {
                 double graphicH = labeled.getGraphic().getLayoutBounds().getHeight() + labeled.getGraphicTextGap();
                 h -= graphicH;
@@ -604,6 +612,13 @@
         OverrunStyle truncationStyle = labeled.getTextOverrun();
         final String string = labeled.getText();
         final boolean emptyText = string == null || string.isEmpty();
+        final ContentDisplay contentDisplay = labeled.getContentDisplay();
+        final double gap = labeled.getGraphicTextGap();
+        final Insets padding = getInsets();
+        final Insets labelPadding = labeled.getLabelPadding();
+        final double widthPadding = padding.getLeft() + padding.getRight() +
+                                    labelPadding.getLeft() + labelPadding.getRight();
+
         double minTextWidth = 0;
         if (!emptyText) {
             // We only want to recompute the full text width if the font or text changed
@@ -627,16 +642,18 @@
 
         // Now inspect the graphic and the hpos to determine the the minWidth
         final Node graphic = labeled.getGraphic();
+        double width;
         if (isIgnoreGraphic()) {
-            return minTextWidth;
+            width = minTextWidth;
         } else if (isIgnoreText()) {
-            return graphic.minWidth(-1);
-        } else if (labeled.getContentDisplay() == ContentDisplay.LEFT
-                || labeled.getContentDisplay() == ContentDisplay.RIGHT){
-            return (minTextWidth + graphic.minWidth(-1) + labeled.getGraphicTextGap());
+            width = graphic.minWidth(-1);
+        } else if (contentDisplay == LEFT || contentDisplay == RIGHT){
+            width = (minTextWidth + graphic.minWidth(-1) + gap);
         } else {
-            return Math.max(minTextWidth, graphic.minWidth(-1));
+            width = Math.max(minTextWidth, graphic.minWidth(-1));
         }
+
+        return width + widthPadding;
     }
 
     @Override protected double computeMinHeight(double width) {
@@ -701,6 +718,11 @@
     @Override protected double computePrefHeight(double width) {
         final Labeled labeled = getSkinnable();
         final Font font = text.getFont();
+        final ContentDisplay contentDisplay = labeled.getContentDisplay();
+        final double gap = labeled.getGraphicTextGap();
+        final Insets padding = getInsets();
+        final Insets labelPadding = labeled.getLabelPadding();
+        final double widthPadding = padding.getLeft() + padding.getRight() + labelPadding.getLeft() + labelPadding.getRight();
 
         String str = labeled.getText();
         if (str != null && str.endsWith("\n")) {
@@ -708,6 +730,13 @@
             str = str.substring(0, str.length() - 1);
         }
 
+        if (!isIgnoreGraphic() &&
+            (contentDisplay == LEFT || contentDisplay == RIGHT)) {
+            width -= (graphic.prefWidth(-1) + gap);
+        }
+
+        width -= widthPadding;
+
         // TODO figure out how to cache this effectively.
         final double textHeight = Utils.computeTextHeight(font, str,
                                                           labeled.isWrapText() ? width : 0);
@@ -716,16 +745,13 @@
         double h = textHeight;
         if (!isIgnoreGraphic()) {
             final Node graphic = labeled.getGraphic();
-            if (labeled.getContentDisplay() == ContentDisplay.TOP
-                || labeled.getContentDisplay() == ContentDisplay.BOTTOM) {
-                h = graphic.prefHeight(-1) + labeled.getGraphicTextGap() + textHeight;
+            if (contentDisplay == TOP || contentDisplay == BOTTOM) {
+                h = graphic.prefHeight(-1) + gap + textHeight;
             } else {
                 h = Math.max(textHeight, graphic.prefHeight(-1));
             }
         }
 
-        Insets padding = getInsets();
-        Insets labelPadding = labeled.getLabelPadding();
         return padding.getTop() + h + padding.getBottom() + labelPadding.getTop() + labelPadding.getBottom();
     }
 
@@ -854,14 +880,14 @@
             if (graphic.isResizable()) {
                 Orientation contentBias = graphic.getContentBias();
                 if (contentBias == Orientation.HORIZONTAL) {
-                    graphicWidth  = boundedSize(w, graphic.minWidth(-1), graphic.maxWidth(-1));
-                    graphicHeight = boundedSize(h, graphic.minHeight(graphicWidth), graphic.maxHeight(graphicWidth));
+                    graphicWidth  = Utils.boundedSize(w, graphic.minWidth(-1), graphic.maxWidth(-1));
+                    graphicHeight = Utils.boundedSize(h, graphic.minHeight(graphicWidth), graphic.maxHeight(graphicWidth));
                 } else if (contentBias == Orientation.VERTICAL) {
-                    graphicHeight = boundedSize(h, graphic.minHeight(-1), graphic.maxHeight(-1));
-                    graphicWidth  = boundedSize(w, graphic.minWidth(graphicHeight), graphic.maxHeight(graphicHeight));
+                    graphicHeight = Utils.boundedSize(h, graphic.minHeight(-1), graphic.maxHeight(-1));
+                    graphicWidth  = Utils.boundedSize(w, graphic.minWidth(graphicHeight), graphic.maxWidth(graphicHeight));
                 } else {
-                    graphicWidth  = boundedSize(w, graphic.minWidth(-1), graphic.maxWidth(-1));
-                    graphicHeight = boundedSize(h, graphic.minHeight(-1), graphic.maxHeight(-1));
+                    graphicWidth  = Utils.boundedSize(w, graphic.minWidth(-1), graphic.maxWidth(-1));
+                    graphicHeight = Utils.boundedSize(h, graphic.minHeight(-1), graphic.maxHeight(-1));
                 }
                 graphic.resize(graphicWidth, graphicHeight);
             } else {
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ListViewSkin.java	Thu Dec 01 10:13:04 2011 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ListViewSkin.java	Tue Dec 06 10:01:57 2011 -0500
@@ -161,26 +161,27 @@
             listViewItems.addListener(weakListViewItemsListener);
         }
 
-        updateCellCount();
+        itemCountDirty = true;
+        requestLayout();
     }
 
     @Override public int getItemCount() {
         return listViewItems == null ? 0 : listViewItems.size();
     }
 
-    private void updateCellCount() {
+    void updateCellCount() {
         if (flow == null) return;
         
-        // we're about to recreate all cells - but before that we detach them
-        // from the ListView, such that their listeners can be uninstalled.
-        // If we don't do this, we start to get multiple events firing when
-        // properties on the ListView trigger listeners in the cells.
-        for (int i = 0; i < flow.cells.size(); i++) {
-            ((ListCell)flow.cells.get(i)).updateListView(null);
-        }
+        int oldCount = flow.getCellCount();
+        int newCount = getItemCount();
         
         flow.setCellCount(getItemCount());
-        flow.recreateCells();
+        
+        if (newCount != oldCount) {
+            flow.recreateCells();
+        } else {
+            flow.reconfigureCells();
+        }
     }
 
     @Override public ListCell<T> createCell() {
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/RadioButtonSkin.java	Thu Dec 01 10:13:04 2011 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/RadioButtonSkin.java	Tue Dec 06 10:01:57 2011 -0500
@@ -77,12 +77,12 @@
      **************************************************************************/
 
     @Override protected double computePrefWidth(double height) {
-        return super.computePrefWidth(height) + snapSize(radio.prefWidth(height));
+        return super.computePrefWidth(height) + snapSize(radio.prefWidth(-1));
     }
 
     @Override protected double computePrefHeight(double width) {
-        return Math.max(snapSize(super.computePrefHeight(width)),
-                        getInsets().getTop() + radio.prefHeight(width) + getInsets().getBottom());
+        return Math.max(snapSize(super.computePrefHeight(width - radio.prefWidth(-1))),
+                        getInsets().getTop() + radio.prefHeight(-1) + getInsets().getBottom());
     }
 
     @Override protected void layoutChildren() {
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ScrollPaneSkin.java	Thu Dec 01 10:13:04 2011 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/ScrollPaneSkin.java	Tue Dec 06 10:01:57 2011 -0500
@@ -346,6 +346,11 @@
                        }
                    }
                }
+               /*
+               ** we need to consume drag events, as we don't want
+               ** the scrollpane itself to be dragged on every mouse click
+               */
+               e.consume();
            }
         });
 
@@ -423,8 +428,12 @@
         TraversalEngine traversalEngine = new TraversalEngine(this, false);
         traversalEngine.addTraverseListener(this);
         setImpl_traversalEngine(traversalEngine);
+
+        // ScrollPanes do not block all MouseEvents by default, unlike most other UI Controls.
+        consumeMouseEvents(false);
     }
 
+
     @Override protected void handleControlPropertyChanged(String p) {
         super.handleControlPropertyChanged(p);
         if (p == "NODE") {
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/SkinBase.java	Thu Dec 01 10:13:04 2011 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/SkinBase.java	Tue Dec 06 10:01:57 2011 -0500
@@ -34,7 +34,6 @@
 import javafx.beans.value.ChangeListener;
 import javafx.beans.value.ObservableValue;
 import javafx.beans.value.WeakChangeListener;
-import javafx.collections.ListChangeListener.Change;
 import javafx.event.EventHandler;
 import javafx.event.EventType;
 import javafx.scene.Node;
@@ -42,7 +41,7 @@
 import javafx.scene.control.ContextMenu;
 import javafx.scene.control.Control;
 import javafx.scene.control.Skin;
-import javafx.scene.input.MouseButton;
+import javafx.scene.input.ContextMenuEvent;
 import javafx.scene.input.MouseEvent;
 import javafx.scene.layout.StackPane;
 
@@ -136,6 +135,8 @@
         this.removeEventHandler(MouseEvent.MOUSE_PRESSED, mouseHandler);
         this.removeEventHandler(MouseEvent.MOUSE_RELEASED, mouseHandler);
         this.removeEventHandler(MouseEvent.MOUSE_DRAGGED, mouseHandler);
+        
+        control.removeEventHandler(ContextMenuEvent.CONTEXT_MENU_REQUESTED, contextMenuHandler);
 
         this.control = null;
         this.behavior = null;
@@ -172,15 +173,9 @@
         this.addEventHandler(MouseEvent.MOUSE_RELEASED, mouseHandler);
         this.addEventHandler(MouseEvent.MOUSE_DRAGGED, mouseHandler);
         
-        // we add a listener for mouse released events to show the context menu
+        // we add a listener for menu request events to show the context menu
         // that may be set on the Control
-        this.addEventHandler(MouseEvent.MOUSE_RELEASED, new EventHandler<MouseEvent>() {
-            @Override public void handle(MouseEvent event) {
-                if (event.getButton() == MouseButton.SECONDARY) {
-                    showContextMenu(event.getScreenX(), event.getScreenY());
-                }
-            }
-        });
+        control.addEventHandler(ContextMenuEvent.CONTEXT_MENU_REQUESTED, contextMenuHandler);
 
         // Default behavior for controls is to consume all mouse events
         consumeMouseEvents(true);
@@ -190,19 +185,21 @@
         return behavior;
     }
 
+    public ContextMenu getContextMenu() {
+        return getSkinnable().getContextMenu();
+    }
+    
     /**
      * Called for key events with no specific mouse location.
      *
-     * Subclasses override this to decide location and call showContextMenu(x, y).
+     * Subclasses override this to decide location and call show the context menu.
      */
-    public void showContextMenu() {
-    }
-
-    protected void showContextMenu(double x, double y) {
-        ContextMenu menu = getSkinnable().getContextMenu();
+    public boolean showContextMenu(ContextMenu menu, double x, double y, boolean isKeyboardTrigger) {
         if (menu != null) {
             menu.show(control, x, y);
+            return true;
         }
+        return false;
     }
 
 
@@ -333,4 +330,19 @@
             }
         }
     };
+    
+    /**
+     * Handles conext menu requests by popping up the menu.
+     * Note that we use this pattern to remove some of the anonymous inner
+     * classes which we'd otherwise have to create. When lambda expressions
+     * are supported, we could do it that way instead (or use MethodHandles).
+     */
+    private final EventHandler<ContextMenuEvent> contextMenuHandler = new EventHandler<ContextMenuEvent>() {
+        @Override public void handle(ContextMenuEvent event) {
+            // If a context menu was shown, consume the event to prevent multiple context menus
+            if (showContextMenu(getContextMenu (), event.getScreenX(), event.getScreenY(), event.isKeyboardTrigger())) {
+                event.consume();
+            }
+        }
+    };
 }
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TabPaneSkin.java	Thu Dec 01 10:13:04 2011 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TabPaneSkin.java	Tue Dec 06 10:01:57 2011 -0500
@@ -55,6 +55,7 @@
 import javafx.scene.control.Tooltip;
 import javafx.scene.effect.DropShadow;
 import javafx.scene.image.ImageView;
+import javafx.scene.input.ContextMenuEvent;
 import javafx.scene.input.MouseButton;
 import javafx.scene.input.MouseEvent;
 import javafx.scene.layout.Pane;
@@ -998,6 +999,14 @@
             getSkinnable().tabMinHeightProperty().addListener(controlListener);
             getSkinnable().tabMaxHeightProperty().addListener(controlListener);
 
+            setOnContextMenuRequested(new EventHandler<ContextMenuEvent>() {
+                @Override public void handle(ContextMenuEvent me) {
+                   if (getTab().getContextMenu() != null) {
+                        getTab().getContextMenu().show(inner, me.getScreenX(), me.getScreenY());
+                        me.consume();
+                    }
+                }
+            });
             setOnMouseReleased(new EventHandler<MouseEvent>() {
                 @Override public void handle(MouseEvent me) {
                     if (me.getButton().equals(MouseButton.MIDDLE)) {
@@ -1007,8 +1016,6 @@
                         }
                     } else if (me.getButton().equals(MouseButton.PRIMARY)) {
                         getBehavior().selectTab(getTab());
-                    } else if (me.getButton().equals(MouseButton.SECONDARY) && getTab().getContextMenu() != null) {
-                        getTab().getContextMenu().show(inner, me.getScreenX(), me.getScreenY());
                     }
                 }
             });
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TableColumnHeader.java	Thu Dec 01 10:13:04 2011 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TableColumnHeader.java	Tue Dec 06 10:01:57 2011 -0500
@@ -43,6 +43,7 @@
 import static javafx.scene.control.TableColumn.SortType.ASCENDING;
 import static javafx.scene.control.TableColumn.SortType.DESCENDING;
 import javafx.scene.control.TableView;
+import javafx.scene.input.ContextMenuEvent;
 import javafx.scene.input.MouseEvent;
 import javafx.scene.layout.GridPane;
 import javafx.scene.layout.HBox;
@@ -236,14 +237,21 @@
                 me.consume();
             }
         });
+        setOnContextMenuRequested(new EventHandler<ContextMenuEvent>() {
+            @Override public void handle(ContextMenuEvent me) {
+                 ContextMenu menu = getTableColumn().getContextMenu();
+                 if (menu != null) {
+                     menu.show(TableColumnHeader.this, me.getScreenX(), me.getScreenY());
+                     me.consume();
+                }
+            }
+        });
         setOnMouseReleased(new EventHandler<MouseEvent>() {
             @Override public void handle(MouseEvent me) {
-                if (MouseEvent.impl_getPopupTrigger(me)) {
-                    ContextMenu menu = getTableColumn().getContextMenu();
-                    if (menu != null) {
-                        menu.show(TableColumnHeader.this, me.getScreenX(), me.getScreenY());
-                    }
-                } else if (getTableHeaderRow().isReordering() && isColumnReorderingEnabled()) {
+                if (MouseEvent.impl_getPopupTrigger(me)) return;
+                ContextMenu menu = getTableColumn().getContextMenu();
+                if (menu != null && menu.isShowing()) return;
+                if (getTableHeaderRow().isReordering() && isColumnReorderingEnabled()) {
                     columnReorderingComplete(me);
                 } else {
                     sortColumn(getTableColumn(), me.isShiftDown());
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TableHeaderRow.java	Thu Dec 01 10:13:04 2011 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TableHeaderRow.java	Tue Dec 06 10:01:57 2011 -0500
@@ -45,6 +45,7 @@
 import javafx.scene.control.Label;
 import javafx.scene.control.TableColumn;
 import javafx.scene.control.TableView;
+import javafx.scene.input.ContextMenuEvent;
 import javafx.scene.input.MouseEvent;
 import javafx.scene.layout.Pane;
 import javafx.scene.layout.Region;
@@ -264,10 +265,11 @@
                 requestLayout();
             }
         });
-        cornerRegion.setOnMouseReleased(new EventHandler<MouseEvent>() {
-            @Override public void handle(MouseEvent me) {
+        cornerRegion.setOnContextMenuRequested(new EventHandler<ContextMenuEvent>() {
+            @Override public void handle(ContextMenuEvent me) {
                 // show a popupMenu which lists all columns
                 columnPopupMenu.show(cornerRegion, Side.BOTTOM, 0, 0);
+                me.consume();
             }
         });
 
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TableRowSkin.java	Thu Dec 01 10:13:04 2011 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TableRowSkin.java	Tue Dec 06 10:01:57 2011 -0500
@@ -90,8 +90,8 @@
 
         initBindings();
 
+        registerChangeListener(tableRow.itemProperty(), "ITEM");
         registerChangeListener(tableRow.editingProperty(), "EDITING");
-        registerChangeListener(tableRow.indexProperty(), "ROW");
         registerChangeListener(tableRow.tableViewProperty(), "TABLE_VIEW");
     }
 
@@ -105,9 +105,10 @@
 
         super.handleControlPropertyChanged(p);
 
-        if (p == "ROW") {
+        if (p == "ITEM") {
             updateCells = true;
             requestLayout();
+            layout();
         } else if (p == "TABLE_VIEW") {
             for (int i = 0; i < getChildren().size(); i++) {
                 Node n = getChildren().get(i);
@@ -162,8 +163,6 @@
         
         if (showColumns && ! table.getVisibleLeafColumns().isEmpty()) {
             // layout the individual column cells
-            TableColumn<T,?> col;
-            TableCell cell;
             double x = getInsets().getLeft();
             double width;
             double height;
@@ -172,10 +171,8 @@
             double verticalPadding = getInsets().getTop() + getInsets().getBottom();
             double horizontalPadding = getInsets().getLeft() + getInsets().getRight();
             
-            for (int i = 0; i < leafColumns.size(); i++) {
-                col = leafColumns.get(i);
-                cell = cellsMap.get(col);
-                if (cell == null) continue;
+            for (int i = 0; i < getChildren().size(); i++) {
+                TableCell cell = (TableCell) getChildren().get(i);
 
                 width = snapSize(cell.prefWidth(-1) - horizontalPadding);
                 height = Math.max(getHeight(), cell.prefHeight(-1));
@@ -222,9 +219,10 @@
             // we must create a TableCell for each table column
             TableCell cell = (TableCell) col.getCellFactory().call(col);
 
-            // we set it's TableColumn and TableView
+            // we set it's TableColumn, TableView and TableRow
             cell.updateTableColumn(col);
             cell.updateTableView(table);
+            cell.updateTableRow(getSkinnable());
 
             // and store this in our HashMap until needed
             cellsMap.put(col, cell);
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TableViewSkin.java	Thu Dec 01 10:13:04 2011 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TableViewSkin.java	Tue Dec 06 10:01:57 2011 -0500
@@ -523,7 +523,8 @@
             newList.addListener(weakRowCountListener);
         }
 
-        updateRowCount();
+        rowCountDirty = true;
+        requestLayout();
     }
 
     /**
@@ -602,7 +603,8 @@
     }
 
     private void refreshView() {
-        updateRowCount();
+        rowCountDirty = true;
+        requestLayout();
     }
 
     private void reconfigureCells() {
@@ -611,24 +613,23 @@
 
     private void updateRowCount() {
         updatePlaceholderRegionVisibility();
+
+        int oldCount = flow.getCellCount();
+        int newCount = getItemCount();
         
-        // we're about to recreate all cells - but before that we detach them
-        // from the TableView, such that their listeners can be uninstalled.
-        // If we don't do this, we start to get multiple events firing when
-        // properties on the TableView trigger listeners in the cells.
-        for (int i = 0; i < flow.cells.size(); i++) {
-            ((TableRow)flow.cells.get(i)).updateTableView(null);
-        }
-
         // if this is not called even when the count is the same, we get a 
         // memory leak in VirtualFlow.sheet.children. This can probably be 
         // optimised in the future when time permits.
-        flow.setCellCount(getItemCount());
+        flow.setCellCount(newCount);
         
-        // FIXME updateRowCount is called _a lot_. Perhaps we can make recreateCells
-        // smarter. Imagine if items has one million items added - do we really
-        // need to recreateCells a million times?
-        flow.recreateCells();
+        if (newCount != oldCount) {
+            // FIXME updateRowCount is called _a lot_. Perhaps we can make recreateCells
+            // smarter. Imagine if items has one million items added - do we really
+            // need to recreateCells a million times?
+            flow.recreateCells();
+        } else {
+            flow.reconfigureCells();
+        }
     }
 
     private void onFocusPreviousCell() {
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TextAreaSkin.java	Thu Dec 01 10:13:04 2011 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TextAreaSkin.java	Tue Dec 06 10:01:57 2011 -0500
@@ -48,6 +48,7 @@
 import javafx.geometry.VerticalDirection;
 import javafx.scene.Group;
 import javafx.scene.Node;
+import javafx.scene.control.ContextMenu;
 import javafx.scene.control.IndexRange;
 import javafx.scene.control.ScrollPane;
 import javafx.scene.control.TextArea;
@@ -681,11 +682,15 @@
         return new Rectangle2D(x, y, width, height);
     }
 
-    @Override public void showContextMenu() {
-        Bounds caretBounds = caretPath.getLayoutBounds();
-        Point2D p = Utils.pointRelativeTo(contentView, null, caretBounds.getMinX(),
-                                          caretBounds.getMaxY(), false);
-        showContextMenu(p.getX(), p.getY());
+    @Override public boolean showContextMenu(ContextMenu menu, double x, double y, boolean isKeyboardTrigger) {
+        if (isKeyboardTrigger) {
+            Bounds caretBounds = caretPath.getLayoutBounds();
+            Point2D p = Utils.pointRelativeTo(contentView, null, caretBounds.getMinX(),
+                                              caretBounds.getMaxY(), false);
+            x = p.getX();
+            y = p.getY();
+        }
+        return super.showContextMenu(menu, x, y, isKeyboardTrigger);
     }
 
     @Override public void scrollCharacterToVisible(final int index) {
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TextFieldSkin.java	Thu Dec 01 10:13:04 2011 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TextFieldSkin.java	Tue Dec 06 10:01:57 2011 -0500
@@ -47,6 +47,7 @@
 import javafx.geometry.Rectangle2D;
 import javafx.scene.Group;
 import javafx.scene.Node;
+import javafx.scene.control.ContextMenu;
 import javafx.scene.control.IndexRange;
 import javafx.scene.control.TextField;
 import javafx.scene.input.MouseEvent;
@@ -139,11 +140,15 @@
      */
     protected ObservableDoubleValue textRight;
 
-    @Override public void showContextMenu() {
-        Bounds caretBounds = caretPath.getLayoutBounds();
-        Point2D p = Utils.pointRelativeTo(textNode, null, caretBounds.getMinX(),
-                                          caretBounds.getMaxY(), false);
-        showContextMenu(p.getX(), p.getY());
+    @Override public boolean showContextMenu(ContextMenu menu, double x, double y, boolean isKeyboardTrigger) {
+        if (isKeyboardTrigger) {
+            Bounds caretBounds = caretPath.getLayoutBounds();
+            Point2D p = Utils.pointRelativeTo(textNode, null, caretBounds.getMinX(),
+                                              caretBounds.getMaxY(), false);
+            x = p.getX();
+            y = p.getY();
+        }
+        return super.showContextMenu(menu, x, y, isKeyboardTrigger);
     }
 
     /**
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/Utils.java	Thu Dec 01 10:13:04 2011 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/Utils.java	Tue Dec 06 10:01:57 2011 -0500
@@ -266,8 +266,9 @@
         int eLen = ellipsis.length();
         // Do this before using helper, as it's not reentrant.
         double eWidth = computeTextWidth(font, ellipsis, 0);
+        double eHeight = computeTextHeight(font, ellipsis, 0);
 
-        if (width < eWidth) {
+        if (width < eWidth || height < eHeight) {
             // The ellipsis doesn't fit.
             return "";
         }
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/VirtualFlow.java	Thu Dec 01 10:13:04 2011 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/VirtualFlow.java	Tue Dec 06 10:01:57 2011 -0500
@@ -173,12 +173,17 @@
     private int cellCount;
     public int getCellCount() { return cellCount; }
     public void setCellCount(int i) {
+        int oldCount = getCellCount();
         this.cellCount = i;
+        
+        boolean countChanged = oldCount != cellCount;
 
         // ensure that the virtual scrollbar adjusts in size based on the current
         // cell count.
-        VirtualScrollBar lengthBar = isVertical() ? vbar : hbar;
-        lengthBar.setMax(i);
+        if (countChanged) {
+            VirtualScrollBar lengthBar = isVertical() ? vbar : hbar;
+            lengthBar.setMax(i);
+        }
 
         // I decided *not* to reset maxPrefBreadth here for the following
         // situation. Suppose I have 30 cells and then I add 10 more. Just
@@ -196,7 +201,7 @@
         // was at its maximum position.
         // FIXME this should be only executed on the pulse, so this will likely
         // lead to performance degradation until it is handled properly.
-        layoutChildren();
+        if (countChanged) layoutChildren();
 
         // Fix for RT-13965: Without this line of code, the number of items in
         // the sheet would constantly grow, leaking memory for the life of the
@@ -204,8 +209,10 @@
         // cells changes - regardless of whether it became bigger or smaller.
         sheet.getChildren().clear();
 
-        Parent parent = getParent();
-        if (parent != null) parent.requestLayout();
+        if (countChanged) {
+            Parent parent = getParent();
+            if (parent != null) parent.requestLayout();
+        }
         // TODO suppose I had 100 cells and I added 100 more. Further
         // suppose I was scrolled to the bottom when that happened. I
         // actually want to update the position of the mapper such that
@@ -265,6 +272,7 @@
         this.createCell = cc;
 
         if (createCell != null) {
+            accumCell = null;
             setNeedsLayout(true);
             recreateCells();
             if (getParent() != null) getParent().requestLayout();
@@ -703,6 +711,25 @@
     }
 
     @Override protected void layoutChildren() {
+       if (needsRecreateCells) {
+            maxPrefBreadth = -1;
+            lastWidth = -1;
+            lastHeight = -1;
+            releaseCell(accumCell);
+            accumCell = null;
+            accumCellParent.getChildren().clear();
+            addAllToPile();
+            pile.clear();
+            needsRecreateCells = false;
+        } 
+        
+        if (needsReconfigureCells) {
+            maxPrefBreadth = -1;
+            lastWidth = -1;
+            lastHeight = -1;
+            needsReconfigureCells = false;
+        }
+
         // if the width and/or height is 0, then there is no point doing
         // any of this work. In particular, this can happen during startup
         if (getWidth() <= 0 || getHeight() <= 0) {
@@ -1433,12 +1460,10 @@
 
     private void setCellIndex(IndexedCell cell, int index) {
         if (cell == null) return;
-        int old = cell.getIndex();
 
-        if (old != index) {
-            cell.updateIndex(index);
+        cell.updateIndex(index);
+        if (cell.isNeedsLayout()) {
             cell.impl_processCSS(false);
-//            cell.layout();
         }
     }
 
@@ -1454,23 +1479,31 @@
      * necessary.
      */
     private IndexedCell getAvailableCell(int prefIndex) {
+        IndexedCell 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; i < pile.size(); i++) {
-            IndexedCell cell = pile.get(i);
-            if (cell != null && cell.getIndex() == prefIndex) {
+            IndexedCell _cell = pile.get(i);
+            if (_cell != null && _cell.getIndex() == prefIndex) {
                 pile.remove(i);
-                return cell;
+                cell = _cell;
             }
         }
 
-        if (pile.size() > 0) {
-            return pile.removeFirst();
-        } else {
-            IndexedCell cell = createCell.run();
+        if (cell == null) {
+            if (pile.size() > 0) {
+                cell = pile.removeFirst();
+            } else {
+                cell = createCell.run();
+            }
+        }
+        
+        if (! sheet.getChildren().contains(cell)) {
             sheet.getChildren().add(cell);
-            return cell;
         }
+        
+        return cell;
     }
 
     private void addAllToPile() {
@@ -1748,32 +1781,16 @@
         return delta; // TODO fake
     }
 
-//    // current *HACK* for the TreeView
-//    public void updateCount(int newCount, boolean stable) {
-//        // for the viewport to remain stable, we need to ...
-//        setCellCount(newCount);
-//        if (getPosition() == 1.0f) {
-//            mapper.adjustPosition(.9999f);
-//        }
-//        reconfigureCells();
-//    }
-
+    private boolean needsReconfigureCells = false;
+    private boolean needsRecreateCells = false;
+    
     public void reconfigureCells() {
-        maxPrefBreadth = -1;
-        lastWidth = -1;
-        lastHeight = -1;
+        needsReconfigureCells = true;
         requestLayout();
     }
 
     public void recreateCells() {
-        maxPrefBreadth = -1;
-        lastWidth = -1;
-        lastHeight = -1;
-        releaseCell(accumCell);
-        accumCell = null;
-        accumCellParent.getChildren().clear();
-        addAllToPile();
-        pile.clear();
+        needsRecreateCells = true;
         requestLayout();
     }
 
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/caspian/caspian.css	Thu Dec 01 10:13:04 2011 -0800
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/caspian/caspian.css	Tue Dec 06 10:01:57 2011 -0500
@@ -164,7 +164,7 @@
     -fx-text-box-border: ladder(
         -fx-background,
         black 10%,
-        derive(-fx-background, -15%)
+        derive(-fx-background, -15%) 30%
     );
 
     /* Typically lighter than -fx-background and used to provide a small
@@ -325,6 +325,8 @@
     
     /* The color to use in ListView/TreeView/TableView to indicate hover. */
     -fx-cell-hover-color: #cce3f4;
+    
+    -fx-cell-focus-inner-border: #85b9de;
 }
 
 .mnemonic-underline {
@@ -1696,19 +1698,19 @@
 }
 
 .list-view:focused .list-cell:focused {
-    -fx-background-color: -fx-focus-color, -fx-control-inner-background;
-    -fx-background-insets: 0, 1.4;
+    -fx-background-color: -fx-focus-color, -fx-cell-focus-inner-border, -fx-control-inner-background;
+    -fx-background-insets: 0, 1, 2;
 }
 
 .list-view:focused .list-cell:focused:odd {
-    -fx-background-color: -fx-focus-color, derive(-fx-control-inner-background,-5%);
-    -fx-background-insets: 0, 1.4;
+    -fx-background-color: -fx-focus-color, -fx-cell-focus-inner-border, derive(-fx-control-inner-background,-5%);
+    -fx-background-insets: 0, 1, 2;
 }
 
 /* When the list-cell is selected and focused */
 .list-view:focused .list-cell:filled:focused:selected {
-    -fx-background-color: -fx-focus-color, -fx-selection-bar;
-    -fx-background-insets: 0, 1.4;
+    -fx-background-color: -fx-focus-color, -fx-cell-focus-inner-border, -fx-selection-bar;
+    -fx-background-insets: 0, 1, 2;
     -fx-background: -fx-accent;
     -fx-text-fill: -fx-selection-bar-text;
 }
@@ -1721,8 +1723,8 @@
 
 .list-view:focused .list-cell:filled:focused:selected:hover {
     -fx-background: -fx-accent;
-    -fx-background-color: -fx-focus-color, -fx-selection-bar;
-    -fx-background-insets: 0, 1.4;
+    -fx-background-color: -fx-focus-color, -fx-cell-focus-inner-border, -fx-selection-bar;
+    -fx-background-insets: 0, 1, 2;
     -fx-text-fill: -fx-selection-bar-text;
 }
 
@@ -1742,8 +1744,8 @@
 }
 
 .list-view:focused .list-cell:filled:focused:hover {
-    -fx-background-color: -fx-focus-color, -fx-cell-hover-color;
-    -fx-background-insets: 0, 1.4;
+    -fx-background-color: -fx-focus-color, -fx-cell-focus-inner-border, -fx-cell-hover-color;
+    -fx-background-insets: 0, 1, 2;
     -fx-text-fill: -fx-text-inner-color;
 }
 
@@ -1809,28 +1811,33 @@
     -fx-padding: 0.0em 0.0em 0.0em 0.25em; /* 0 0 0 3 */
 }
 
-.tree-cell:focused {
-    -fx-background-color: -fx-focus-color, -fx-control-inner-background;
-    -fx-background-insets: 0, 1.4;
-}
-
-/*
-.tree-cell:odd {
-    -fx-background-color: derive(-fx-control-inner-background,-5%);
-}
-
-.tree-cell:focused:odd {
-    -fx-background-color: -fx-focus-color, derive(-fx-control-inner-background,-5%);
-    -fx-background-insets: 0, 1.4;
-}
-*/
-
-.tree-view:focused .tree-cell:filled:selected:focused, .tree-view:focused .tree-cell:filled:selected, .tree-view:focused .tree-cell:filled:selected:hover {
+
+
+.tree-view:focused .tree-cell:focused {
+    -fx-background-color: -fx-focus-color, -fx-cell-focus-inner-border, -fx-control-inner-background;
+    -fx-background-insets: 0, 1, 2;
+}
+
+.tree-view:focused .tree-cell:filled:focused:selected {
+    -fx-background-color: -fx-focus-color, -fx-cell-focus-inner-border, -fx-selection-bar;
+    -fx-background-insets: 0, 1, 2;
+    -fx-background: -fx-accent;
+    -fx-text-fill: -fx-selection-bar-text;
+}
+
+.tree-view:focused .tree-cell:filled:selected, .tree-view:focused .tree-cell:filled:selected:hover {
     -fx-background: -fx-accent;
     -fx-background-color: -fx-selection-bar;
     -fx-text-fill: -fx-selection-bar-text;
 }
 
+.tree-view:focused .tree-cell:filled:focused:selected:hover {
+    -fx-background: -fx-accent;
+    -fx-background-color: -fx-focus-color, -fx-cell-focus-inner-border, -fx-selection-bar;
+    -fx-background-insets: 0, 1, 2;
+    -fx-text-fill: -fx-selection-bar-text;
+}
+
 /* When the TreeView is _not_ focused, we show alternate selection colors */
 .tree-cell:filled:selected:focused, .tree-cell:filled:selected {
     -fx-background-color: lightgray;
@@ -1874,6 +1881,12 @@
     -fx-background-color: -fx-mark-color;
 }
 
+.tree-view:focused .tree-cell:filled:focused:hover {
+    -fx-background-color: -fx-focus-color, -fx-cell-focus-inner-border, -fx-cell-hover-color;
+    -fx-background-insets: 0, 1, 2;
+    -fx-text-fill: -fx-text-inner-color;
+}
+
 .tree-cell:filled:selected:hover .tree-disclosure-node .arrow {
     -fx-background-color: -fx-selection-bar-text;
 }
@@ -2286,12 +2299,37 @@
     -fx-background-insets: 0, 0 0 1 0;
 }
 
-.table-view:focused .table-row-cell:selected:focused, .table-view:focused .table-row-cell:selected, .table-view:row-selection .table-row-cell:filled:hover:selected {
+.table-row-cell:focused {
+    -fx-background-color: -fx-focus-color, -fx-cell-focus-inner-border, -fx-control-inner-background;
+    -fx-background-insets: 0, 1, 2;
+}
+
+.table-row-cell:focused:odd {
+    -fx-background-color: -fx-focus-color, -fx-cell-focus-inner-border, derive(-fx-control-inner-background,-5%);
+    -fx-background-insets: 0, 1, 2;
+}
+
+/* When the table-row-cell is selected and focused */
+.table-view:focused .table-row-cell:filled:focused:selected {
+    -fx-background-color: -fx-focus-color, -fx-cell-focus-inner-border, -fx-selection-bar;
+    -fx-background-insets: 0, 1, 2;
+    -fx-background: -fx-accent;
+    -fx-text-fill: -fx-selection-bar-text;
+}
+
+.table-view:focused .table-row-cell:filled:selected, .table-view:row-selection .table-row-cell:filled:hover:selected {
     -fx-background: -fx-accent;
     -fx-background-color: -fx-selection-bar;
     -fx-text-fill: -fx-selection-bar-text;
 }
 
+.table-view:focused .table-row-cell:filled:focused:selected:hover {
+    -fx-background: -fx-accent;
+    -fx-background-color: -fx-focus-color, -fx-cell-focus-inner-border, -fx-selection-bar;
+    -fx-background-insets: 0, 1, 2;
+    -fx-text-fill: -fx-selection-bar-text;
+}
+
 /* When the TableView is _not_ focused, we show alternate selection colors */
 .table-row-cell:filled:selected:focused, .table-row-cell:filled:selected {
     -fx-background-color: lightgray;
@@ -2302,17 +2340,18 @@
     -fx-opacity: -fx-disabled-opacity;
 }
 
-.table-row-cell:focused {
-    -fx-background-color: -fx-focus-color, -fx-control-inner-background;
-    -fx-background-insets: 0, 1.4;
-}
-
 .table-view:row-selection .table-row-cell:filled:hover { 
     -fx-background-color: -fx-table-cell-border-color, -fx-cell-hover-color;
     -fx-background-insets: 0, 0 0 1 0;
     -fx-text-fill: -fx-text-inner-color;
 }
 
+.table-view:row-selection .table-row-cell:filled:focused:hover { 
+    -fx-background-color: -fx-table-cell-border-color, -fx-focus-color, -fx-cell-focus-inner-border, -fx-cell-hover-color;
+    -fx-background-insets: 0, 0 0 1 0, 1 1 2 1, 2 2 3 2, 3 3 4 3;
+    -fx-text-fill: -fx-text-inner-color;
+}
+
 .table-cell {
     -fx-skin: "com.sun.javafx.scene.control.skin.TableCellSkin";
     -fx-padding: 0.166667em; /* 2px, plus border adds 1px */
@@ -2343,14 +2382,34 @@
     -fx-border-insets: 0 1 1 1, 0 0 0 0;
 }
 
-.table-view:focused .table-cell:selected:focused, .table-view:focused .table-cell:selected, .table-view:cell-selection .table-cell:filled:hover:selected {
+.table-view:focused .table-cell:focused {
+    -fx-background-color: -fx-focus-color, -fx-cell-focus-inner-border, -fx-control-inner-background;
+    -fx-background-insets: 0 1 0 0, 1 2 1 1, 2 3 2 2;
+}
+
+.table-view:focused .table-row-cell:filled .table-cell:focused:selected {
+    -fx-background-color: -fx-focus-color, -fx-cell-focus-inner-border, -fx-selection-bar;
+    -fx-background-insets: 0 1 0 0, 1 2 1 1, 2 3 2 2;
+    -fx-background: -fx-accent;
+    -fx-text-fill: -fx-selection-bar-text;
+}
+
+.table-view:focused .table-row-cell:filled .table-cell:selected, .table-view:cell-selection .table-row-cell:filled .table-cell:hover:selected {
     -fx-background: -fx-accent;
     -fx-background-color: -fx-selection-bar;
     -fx-text-fill: -fx-selection-bar-text;
+    -fx-background-insets: 0 0 1 0;
+}
+
+.table-view:focused .table-row-cell:filled .table-cell:focused:selected:hover {
+    -fx-background: -fx-accent;
+    -fx-background-color: -fx-focus-color, -fx-cell-focus-inner-border, -fx-selection-bar;
+    -fx-background-insets: 0 1 0 0, 1 2 1 1, 2 3 2 2;
+    -fx-text-fill: -fx-selection-bar-text;
 }
 
 /* When the TableView is _not_ focused, we show alternate selection colors */
-.table-cell:filled:selected:focused, .table-cell:filled:selected {
+ .table-row-cell:filled .table-cell:selected:focused,  .table-row-cell:filled .table-cell:selected {
     -fx-background-color: lightgray;
     -fx-text-fill: -fx-selection-bar-text;
 }
@@ -2359,14 +2418,21 @@
     -fx-opacity: -fx-disabled-opacity;
 }
 
-.table-cell:focused {
+/*.table-cell:focused {
     -fx-background-color: -fx-focus-color, -fx-control-inner-background;
     -fx-background-insets: 0, 1.4;
-}
-
-.table-view:cell-selection .table-cell:filled:hover {
+}*/
+
+.table-view:cell-selection  .table-row-cell:filled .table-cell:hover {
     -fx-background-color: -fx-cell-hover-color;
     -fx-text-fill: -fx-text-inner-color;
+    -fx-background-insets: 0 0 1 0;
+}
+
+.table-view:cell-selection .table-row-cell:filled .table-cell:focused:hover {
+    -fx-background-color: -fx-focus-color, -fx-cell-focus-inner-border, -fx-cell-hover-color;
+    -fx-background-insets: 0 1 0 0, 1 2 1 1, 2 3 2 2;
+    -fx-text-fill: -fx-text-inner-color;
 }
 
 /* The column-resize-line is shown when the user is attempting to resize a column. */
--- a/javafx-ui-controls/src/javafx/scene/control/Cell.java	Thu Dec 01 10:13:04 2011 -0800
+++ b/javafx-ui-controls/src/javafx/scene/control/Cell.java	Tue Dec 06 10:01:57 2011 -0500
@@ -398,7 +398,7 @@
      */
     public final ReadOnlyBooleanProperty selectedProperty() { return selected.getReadOnlyProperty(); }
 
-    private void setSelected(boolean value) { selected.set(value); }
+    void setSelected(boolean value) { selected.set(value); }
     
     /**
      * Returns whether this cell is currently selected or not.
--- a/javafx-ui-controls/src/javafx/scene/control/IndexedCell.java	Thu Dec 01 10:13:04 2011 -0800
+++ b/javafx-ui-controls/src/javafx/scene/control/IndexedCell.java	Tue Dec 06 10:01:57 2011 -0500
@@ -110,6 +110,11 @@
      */
     public void updateIndex(int i) { 
         index.set(i);
+        indexChanged();
+    }
+    
+    void indexChanged() { 
+        // no-op
     }
     
     /* *************************************************************************
--- a/javafx-ui-controls/src/javafx/scene/control/Labeled.java	Thu Dec 01 10:13:04 2011 -0800
+++ b/javafx-ui-controls/src/javafx/scene/control/Labeled.java	Tue Dec 06 10:01:57 2011 -0500
@@ -51,6 +51,7 @@
 
 import com.sun.javafx.css.Styleable;
 import com.sun.javafx.css.StyleableProperty;
+import javafx.beans.DefaultProperty;
 import javafx.beans.property.ReadOnlyObjectProperty;
 import javafx.beans.property.ReadOnlyObjectWrapper;
 
@@ -78,6 +79,7 @@
  * @see Label
  * @see ToggleButton
  */
+@DefaultProperty("text")
 public abstract class Labeled extends Control {
 
     /***************************************************************************
--- a/javafx-ui-controls/src/javafx/scene/control/ListCell.java	Thu Dec 01 10:13:04 2011 -0800
+++ b/javafx-ui-controls/src/javafx/scene/control/ListCell.java	Tue Dec 06 10:01:57 2011 -0500
@@ -105,11 +105,15 @@
      */
     private InvalidationListener indexListener = new InvalidationListener() {
         @Override public void invalidated(Observable valueModel) {
-            updateItem();
-            updateSelection();
-            updateFocus();
-        }
-    };
+            indexChanged();
+         }
+     };
+    
+    @Override void indexChanged() {
+        updateItem();
+        updateSelection();
+        updateFocus();
+    }
 
     /**
      * Listens to the editing index on the ListView. It is possible for the developer
--- a/javafx-ui-controls/src/javafx/scene/control/ListView.java	Thu Dec 01 10:13:04 2011 -0800
+++ b/javafx-ui-controls/src/javafx/scene/control/ListView.java	Tue Dec 06 10:01:57 2011 -0500
@@ -52,6 +52,7 @@
 import com.sun.javafx.scene.control.WeakListChangeListener;
 import com.sun.javafx.scene.control.skin.ListViewSkin;
 import com.sun.javafx.scene.control.skin.VirtualContainerBase;
+import javafx.beans.DefaultProperty;
 import javafx.beans.property.ReadOnlyIntegerProperty;
 import javafx.beans.property.ReadOnlyIntegerWrapper;
 import javafx.beans.property.BooleanProperty;
@@ -131,6 +132,7 @@
  *          and {@link #focusModelProperty() focus model}.
  */
 // TODO add code examples
+@DefaultProperty("items")
 public class ListView<T> extends Control {
     
     /***************************************************************************
--- a/javafx-ui-controls/src/javafx/scene/control/Menu.java	Thu Dec 01 10:13:04 2011 -0800
+++ b/javafx-ui-controls/src/javafx/scene/control/Menu.java	Tue Dec 06 10:01:57 2011 -0500
@@ -39,6 +39,7 @@
 import com.sun.javafx.collections.TrackableObservableList;
 import com.sun.javafx.event.EventHandlerManager;
 import com.sun.javafx.scene.control.Logging;
+import javafx.beans.DefaultProperty;
 import javafx.beans.property.ReadOnlyBooleanProperty;
 import javafx.beans.property.ReadOnlyBooleanWrapper;
 
@@ -80,6 +81,7 @@
  * @see MenuBar
  * @see MenuItem
  */
+@DefaultProperty("items")
 public class Menu extends MenuItem {
 
     /**
--- a/javafx-ui-controls/src/javafx/scene/control/MenuBar.java	Thu Dec 01 10:13:04 2011 -0800
+++ b/javafx-ui-controls/src/javafx/scene/control/MenuBar.java	Tue Dec 06 10:01:57 2011 -0500
@@ -25,6 +25,7 @@
 
 package javafx.scene.control;
 
+import javafx.beans.DefaultProperty;
 import javafx.collections.FXCollections;
 import javafx.collections.ObservableList;
 
@@ -54,6 +55,7 @@
  * @see Menu
  * @see MenuItem
  */
+@DefaultProperty("menus")
 public class MenuBar extends Control {
 
     /***************************************************************************
--- a/javafx-ui-controls/src/javafx/scene/control/ScrollPane.java	Thu Dec 01 10:13:04 2011 -0800
+++ b/javafx-ui-controls/src/javafx/scene/control/ScrollPane.java	Tue Dec 06 10:01:57 2011 -0500
@@ -44,6 +44,7 @@
 import com.sun.javafx.css.Styleable;
 import com.sun.javafx.css.StyleManager;
 import com.sun.javafx.css.StyleableProperty;
+import javafx.beans.DefaultProperty;
 
 /**
  * A Control that provides a scrolled, clipped viewport of its contents. It
@@ -81,6 +82,7 @@
  *
  * Implementation of ScrollPane According to JavaFX UI Control API Specification
  */
+@DefaultProperty("content")
 public class ScrollPane extends Control {
 
     /***************************************************************************
--- a/javafx-ui-controls/src/javafx/scene/control/TabPane.java	Thu Dec 01 10:13:04 2011 -0800
+++ b/javafx-ui-controls/src/javafx/scene/control/TabPane.java	Tue Dec 06 10:01:57 2011 -0500
@@ -43,6 +43,7 @@
 import com.sun.javafx.css.Styleable;
 import com.sun.javafx.css.StyleManager;
 import com.sun.javafx.css.StyleableProperty;
+import javafx.beans.DefaultProperty;
 
 /**
  * <p>A control that allows switching between a group of {@link Tab Tabs}.  Only one tab
@@ -75,6 +76,7 @@
  *
  * @see Tab
  */
+@DefaultProperty("tabs")
 public class TabPane extends Control {
     private static final double DEFAULT_TAB_MIN_WIDTH = 0;
 
--- a/javafx-ui-controls/src/javafx/scene/control/TableCell.java	Thu Dec 01 10:13:04 2011 -0800
+++ b/javafx-ui-controls/src/javafx/scene/control/TableCell.java	Tue Dec 06 10:01:57 2011 -0500
@@ -92,13 +92,20 @@
      *                                                                         *
      **************************************************************************/
     
+    private boolean itemDirty = false;
+    
     private InvalidationListener indexListener = new InvalidationListener() {
         @Override public void invalidated(Observable valueModel) {
-            updateItem();
+            indexChanged();
             updateSelection();
             updateFocus();
         }
     };
+    
+    @Override void indexChanged() {
+        itemDirty = true;
+        requestLayout();
+    }
 
     /*
      * This is the list observer we use to keep an eye on the SelectedCells
@@ -122,7 +129,8 @@
     // same as above, but for for changes to the properties on TableRow
     private final InvalidationListener tableRowUpdateObserver = new InvalidationListener() {
         @Override public void invalidated(Observable value) {
-            updateItem();
+            itemDirty = true;
+            requestLayout();
         }
     };
 
@@ -369,7 +377,16 @@
      * Overriding methods                                                      *
      *                                                                         *
      **************************************************************************/
-    
+
+    /** {@inheritDoc} */
+    @Override public void updateSelected(boolean selected) {
+        // copied from Cell, with the first conditional clause below commented 
+        // out, as it is valid for an empty TableCell to be selected, as long 
+        // as the parent TableRow is not empty (see RT-15529).
+        /*if (selected && isEmpty()) return;*/
+        if (getTableRow() == null || getTableRow().isEmpty()) return;
+        setSelected(selected);
+    }
 
 
     /* *************************************************************************
@@ -520,6 +537,15 @@
         observableValue.addListener(weaktableRowUpdateObserver);
     }
 
+    @Override protected void layoutChildren() {
+        if (itemDirty) {
+            updateItem();
+            itemDirty = false;
+        }
+        super.layoutChildren();
+    }
+
+    
 
 
     /***************************************************************************
--- a/javafx-ui-controls/src/javafx/scene/control/TableRow.java	Thu Dec 01 10:13:04 2011 -0800
+++ b/javafx-ui-controls/src/javafx/scene/control/TableRow.java	Tue Dec 06 10:01:57 2011 -0500
@@ -82,12 +82,16 @@
 
     private InvalidationListener indexInvalidationListener = new InvalidationListener() {
         @Override public void invalidated(Observable valueModel) {
-            updateItem();
+            indexChanged();
             updateSelection();
             updateFocus();
         }
     };
     
+    @Override void indexChanged() {
+        updateItem();
+    }
+    
 
     /***************************************************************************
      *                                                                         *
@@ -230,7 +234,7 @@
         List<T> items = tv.getItems();
 
         // Compute whether the index for this cell is for a real item
-        boolean valid = getIndex() >=0 && getIndex() < items.size();
+        boolean valid = getIndex() >= 0 && getIndex() < items.size();
 
         // Cause the cell to update itself
         if (valid) {
--- a/javafx-ui-controls/src/javafx/scene/control/TableView.java	Thu Dec 01 10:13:04 2011 -0800
+++ b/javafx-ui-controls/src/javafx/scene/control/TableView.java	Tue Dec 06 10:01:57 2011 -0500
@@ -61,6 +61,7 @@
 import com.sun.javafx.scene.control.skin.TableViewSkin;
 import com.sun.javafx.scene.control.skin.VirtualContainerBase;
 import java.util.HashMap;
+import javafx.beans.DefaultProperty;
 import javafx.beans.WeakInvalidationListener;
 import javafx.beans.property.ReadOnlyObjectProperty;
 import javafx.beans.property.ReadOnlyObjectWrapper;
@@ -200,6 +201,7 @@
  * @see TablePosition
  * @param <S> The type of the objects contained within the TableView items list.
  */
+@DefaultProperty("items")
 public class TableView<S> extends Control {
     
     /***************************************************************************
--- a/javafx-ui-controls/src/javafx/scene/control/TextInputControl.java	Thu Dec 01 10:13:04 2011 -0800
+++ b/javafx-ui-controls/src/javafx/scene/control/TextInputControl.java	Tue Dec 06 10:01:57 2011 -0500
@@ -25,6 +25,7 @@
 
 package javafx.scene.control;
 
+import javafx.beans.DefaultProperty;
 import javafx.beans.InvalidationListener;
 import javafx.beans.Observable;
 import javafx.beans.binding.IntegerBinding;
@@ -47,10 +48,12 @@
 
 import com.sun.javafx.Utils;
 import com.sun.javafx.binding.ExpressionHelper;
+import com.sun.javafx.css.StyleManager;
 
 /**
  * Abstract base class for text input controls.
  */
+@DefaultProperty("text")
 public abstract class TextInputControl extends Control {
     /**
      * Interface representing a text input's content. Since it is an ObservableStringValue,
@@ -172,7 +175,11 @@
     /**
      * Indicates whether this TextInputControl can be edited by the user.
      */
-    private BooleanProperty editable = new SimpleBooleanProperty(this, "editable", true);
+    private BooleanProperty editable = new SimpleBooleanProperty(this, "editable", true) {
+        @Override protected void invalidated() {
+            impl_pseudoClassStateChanged(PSEUDO_CLASS_READONLY);
+        }
+    };
     public final boolean isEditable() { return editable.getValue(); }
     public final void setEditable(boolean value) { editable.setValue(value); }
     public final BooleanProperty editableProperty() { return editable; }
@@ -1020,4 +1027,27 @@
             }
         }
     }
+
+    /***************************************************************************
+     *                                                                         *
+     * Stylesheet Handling                                                     *
+     *                                                                         *
+     **************************************************************************/
+
+    private static final String PSEUDO_CLASS_READONLY = "readonly";
+
+    private static final long PSEUDO_CLASS_READONLY_MASK
+            = StyleManager.getInstance().getPseudoclassMask(PSEUDO_CLASS_READONLY);
+
+    /**
+     * @treatasprivate implementation detail
+     * @deprecated This is an internal API that is not intended for use and will be removed in the next version
+     */
+    @Deprecated @Override public long impl_getPseudoClassState() {
+        long mask = super.impl_getPseudoClassState();
+
+        if (!isEditable()) mask |= PSEUDO_CLASS_READONLY_MASK;
+
+        return mask;
+    }
 }
--- a/javafx-ui-controls/src/javafx/scene/control/TitledPane.java	Thu Dec 01 10:13:04 2011 -0800
+++ b/javafx-ui-controls/src/javafx/scene/control/TitledPane.java	Tue Dec 06 10:01:57 2011 -0500
@@ -39,6 +39,7 @@
 import com.sun.javafx.css.Styleable;
 import com.sun.javafx.css.StyleManager;
 import com.sun.javafx.css.StyleableProperty;
+import javafx.beans.DefaultProperty;
 
 /**
  * <p>A TitledPane is a panel with a title that can be opened and closed.</p>
@@ -57,7 +58,7 @@
  * </code></pre>
  *
  */
-
+@DefaultProperty("content")
 public class TitledPane extends Labeled {
 
     /***************************************************************************
--- a/javafx-ui-controls/src/javafx/scene/control/TreeView.java	Thu Dec 01 10:13:04 2011 -0800
+++ b/javafx-ui-controls/src/javafx/scene/control/TreeView.java	Tue Dec 06 10:01:57 2011 -0500
@@ -47,6 +47,7 @@
 import com.sun.javafx.scene.control.WeakEventHandler;
 import com.sun.javafx.scene.control.skin.VirtualContainerBase;
 import java.lang.ref.WeakReference;
+import javafx.beans.DefaultProperty;
 import javafx.beans.property.SimpleBooleanProperty;
 import javafx.beans.property.ReadOnlyObjectProperty;
 import javafx.beans.property.ReadOnlyObjectWrapper;
@@ -94,6 +95,7 @@
  * @param <T> The type of the item contained within the {@link TreeItem} value
  *      property for all tree items in this TreeView.
  */
+@DefaultProperty("root")
 public class TreeView<T> extends Control {
     
     /***************************************************************************
@@ -1250,7 +1252,7 @@
                         TreeItem item = e.getAddedChildren().get(i);
                         row = treeView.getRow(item);
                         
-                        if (row <= getFocusedIndex()) {
+                        if (item != null && row <= getFocusedIndex()) {
 //                            shift = e.getTreeItem().isExpanded() ? e.getAddedSize() : 0;
                             shift += item.getExpandedDescendentCount();
                         }
--- a/javafx-ui-controls/src/javafx/scene/control/UAStylesheetLoader.java	Thu Dec 01 10:13:04 2011 -0800
+++ b/javafx-ui-controls/src/javafx/scene/control/UAStylesheetLoader.java	Tue Dec 06 10:01:57 2011 -0500
@@ -1,6 +1,26 @@
 /*
- * To change this template, choose Tools | Templates and open the template in
- * the editor.
+ * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
 package javafx.scene.control;
 
@@ -11,10 +31,12 @@
 import java.security.PrivilegedAction;
 
 /**
- *
- * @author paru
+ * 
+ * Class to load caspian User Agent Stylesheet when either a control or a 
+ * popup control is first created. This is a package private class intended for 
+ * internal use only.
  */
-public class UAStylesheetLoader {
+class UAStylesheetLoader {
     
     private static class Holder {
         private static UAStylesheetLoader stylesheetLoader = new UAStylesheetLoader();
--- a/javafx-ui-controls/test/com/sun/javafx/scene/control/skin/LabelSkinTest.java	Thu Dec 01 10:13:04 2011 -0800
+++ b/javafx-ui-controls/test/com/sun/javafx/scene/control/skin/LabelSkinTest.java	Tue Dec 06 10:01:57 2011 -0500
@@ -50,11 +50,13 @@
      *                                                                          *
      ***************************************************************************/
     
-    @Test public void widthChangesOnLabelShouldInvoke_handleControlPropertyChanged() {
+    @Test public void sizeChangesOnLabelShouldInvoke_handleControlPropertyChanged() {
         assertFalse(skin.propertyChanged); // sanity check
         label.resize(500, label.getHeight());
         assertTrue(skin.propertyChanged);
         assertEquals(1, skin.propertyChangeCount); // sanity check
+        label.resize(label.getWidth(), label.prefHeight(label.getWidth()));
+        assertEquals(2, skin.propertyChangeCount); // sanity check
     }
     
     @Test public void textFillChangesOnLabelShouldInvoke_handleControlPropertyChanged() {
@@ -157,7 +159,8 @@
         // wider than the label's available width.
         label.setText("A long line which is wider than 100 pixels.");
         label.setWrapText(true);
-        label.layout();
+        label.autosize();
+        //label.layout();
         skin.updateDisplayedText();
         
         final double oldWrappingWidth = text.getWrappingWidth();
@@ -290,215 +293,239 @@
      ***************************************************************************/
 
     @Test public void whenTextIsNullAndNoGraphic_computeMinWidth_ReturnsZero() {
+        skin.setPadding(new Insets(7, 7, 7, 7));
         label.setText(null);
-        assertEquals(0.0, label.minWidth(-1), 0);
+        assertEquals(0.0 + 14, label.minWidth(-1), 0);
     }
     
     @Test public void whenTextIsEmptyAndNoGraphic_computeMinWidth_ReturnsZero() {
+        skin.setPadding(new Insets(7, 7, 7, 7));
         label.setText("");
-        assertEquals(0.0, label.minWidth(-1), 0);
+        assertEquals(0.0 + 14, label.minWidth(-1), 0);
     }
     
     @Test public void whenTextIsShorterThanEllipsisAndNoGraphic_computeMinWidth_ReturnsTextWidth() {
+        skin.setPadding(new Insets(7, 7, 7, 7));
         label.setText(".");
         assertTrue(label.minWidth(-1) >= 0);
-        assertEquals(skin.textWidth, label.minWidth(-1), 0);
+        assertEquals(skin.textWidth + 14, label.minWidth(-1), 0);
     }
 
     @Test public void whenTextIsGreaterThanEllipsisAndNoGraphic_computeMinWidth_ReturnsEllipsisWidth() {
+        skin.setPadding(new Insets(7, 7, 7, 7));
         label.setText("These are the times that try men's souls.");
         assertTrue(label.minWidth(-1) >= 0);
-        assertEquals(skin.ellipsisWidth, label.minWidth(-1), 0);
+        assertEquals(skin.ellipsisWidth + 14, label.minWidth(-1), 0);
     }
 
     @Test public void whenTextIsNullAndGraphicIsUnmanaged_computeMinWidth_ReturnsZero() {
+        skin.setPadding(new Insets(7, 7, 7, 7));
         Rectangle r = new Rectangle(23, 500);
         r.setManaged(false);
         label.setGraphic(r);
         label.setText(null);
-        assertEquals(0.0, label.minWidth(-1), 0);
+        assertEquals(0.0 + 14, label.minWidth(-1), 0);
     }
     
     @Test public void whenTextIsEmptyAndGraphicIsUnmanaged_computeMinWidth_ReturnsZero() {
+        skin.setPadding(new Insets(7, 7, 7, 7));
         Rectangle r = new Rectangle(23, 500);
         r.setManaged(false);
         label.setGraphic(r);
         label.setText("");
-        assertEquals(0.0, label.minWidth(-1), 0);
+        assertEquals(0.0 + 14, label.minWidth(-1), 0);
     }
     
     @Test public void whenTextIsShorterThanEllipsisAndGraphicIsUnmanaged_computeMinWidth_ReturnsTextWidth() {
+        skin.setPadding(new Insets(7, 7, 7, 7));
         Rectangle r = new Rectangle(23, 500);
         r.setManaged(false);
         label.setGraphic(r);
         label.setText(".");
         assertTrue(label.minWidth(-1) >= 0);
-        assertEquals(skin.textWidth, label.minWidth(-1), 0);
+        assertEquals(skin.textWidth + 14, label.minWidth(-1), 0);
     }
 
     @Test public void whenTextIsGreaterThanEllipsisAndGraphicIsUnmanaged_computeMinWidth_ReturnsEllipsisWidth() {
+        skin.setPadding(new Insets(7, 7, 7, 7));
         Rectangle r = new Rectangle(23, 500);
         r.setManaged(false);
         label.setGraphic(r);
         label.setText("These are the times that try men's souls.");
         assertTrue(label.minWidth(-1) >= 0);
-        assertEquals(skin.ellipsisWidth, label.minWidth(-1), 0);
+        assertEquals(skin.ellipsisWidth + 14, label.minWidth(-1), 0);
     }
 
     @Test public void whenTextIsNullAndGraphicIsSet_computeMinWidth_ReturnsGraphicWidth() {
+        skin.setPadding(new Insets(7, 7, 7, 7));
         Rectangle r = new Rectangle(23, 23);
         label.setGraphic(r);
         label.setText(null);
         assertTrue(label.minWidth(-1) >= 0);
-        assertEquals(23, label.minWidth(-1), 0);
+        assertEquals(23 + 14, label.minWidth(-1), 0);
     }
     
     @Test public void whenTextIsEmptyAndGraphicIsSet_computeMinWidth_ReturnsGraphicWidth() {
+        skin.setPadding(new Insets(7, 7, 7, 7));
         Rectangle r = new Rectangle(23, 23);
         label.setGraphic(r);
         label.setText("");
         assertTrue(label.minWidth(-1) >= 0);
-        assertEquals(23, label.minWidth(-1), 0);
+        assertEquals(23 + 14, label.minWidth(-1), 0);
     }
 
     @Test public void whenTextIsShorterThanEllipsisAndGraphicIsSetAndContentDisplayIsLEFT_computeMinWidth_ReturnsGraphicWidthPlusGraphicTextGapPlusTextWidth() {
+        skin.setPadding(new Insets(7, 7, 7, 7));
         Rectangle r = new Rectangle(23, 23);
         label.setGraphicTextGap(2);
         label.setGraphic(r);
         label.setContentDisplay(ContentDisplay.LEFT);
         label.setText(".");
         assertTrue(label.minWidth(-1) >= 0);
-        assertEquals(23 + 2 + skin.textWidth, label.minWidth(-1), 0);
+        assertEquals(23 + 2 + skin.textWidth + 14, label.minWidth(-1), 0);
     }
 
     @Test public void whenTextIsLongThanEllipsisAndGraphicIsSetAndContentDisplayIsLEFT_computeMinWidth_ReturnsGraphicWidthPlusGraphicTextGapPlusEllipsisWidth() {
+        skin.setPadding(new Insets(7, 7, 7, 7));
         Rectangle r = new Rectangle(23, 23);
         label.setGraphicTextGap(2);
         label.setGraphic(r);
         label.setContentDisplay(ContentDisplay.LEFT);
         label.setText("Wherefore art thou Romeo?");
         assertTrue(label.minWidth(-1) >= 0);
-        assertEquals(23 + 2 + skin.ellipsisWidth, label.minWidth(-1), 0);
+        assertEquals(23 + 2 + skin.ellipsisWidth + 14, label.minWidth(-1), 0);
     }
 
     @Test public void whenTextIsShorterThanEllipsisAndGraphicIsSetAndContentDisplayIsRIGHT_computeMinWidth_ReturnsGraphicWidthPlusGraphicTextGapPlusTextWidth() {
+        skin.setPadding(new Insets(7, 7, 7, 7));
         Rectangle r = new Rectangle(23, 23);
         label.setGraphicTextGap(2);
         label.setGraphic(r);
         label.setContentDisplay(ContentDisplay.RIGHT);
         label.setText(".");
         assertTrue(label.minWidth(-1) >= 0);
-        assertEquals(23 + 2 + skin.textWidth, label.minWidth(-1), 0);
+        assertEquals(23 + 2 + skin.textWidth + 14, label.minWidth(-1), 0);
     }
 
     @Test public void whenTextIsLongThanEllipsisAndGraphicIsSetAndContentDisplayIsRIGHT_computeMinWidth_ReturnsGraphicWidthPlusGraphicTextGapPlusEllipsisWidth() {
+        skin.setPadding(new Insets(7, 7, 7, 7));
         Rectangle r = new Rectangle(23, 23);
         label.setGraphicTextGap(2);
         label.setGraphic(r);
         label.setContentDisplay(ContentDisplay.RIGHT);
         label.setText("Wherefore art thou Romeo?");
         assertTrue(label.minWidth(-1) >= 0);
-        assertEquals(23 + 2 + skin.ellipsisWidth, label.minWidth(-1), 0);
+        assertEquals(23 + 2 + skin.ellipsisWidth + 14, label.minWidth(-1), 0);
     }
 
     @Test public void whenTextIsShorterThanEllipsisAndGraphicIsSetAndContentDisplayIsCENTER_computeMinWidth_ReturnsRightAnswer() {
+        skin.setPadding(new Insets(7, 7, 7, 7));
         Rectangle r = new Rectangle(23, 23);
         label.setGraphicTextGap(2);
         label.setGraphic(r);
         label.setContentDisplay(ContentDisplay.CENTER);
         label.setText(".");
         assertTrue(label.minWidth(-1) >= 0);
-        assertEquals(Math.max(23, skin.textWidth), label.minWidth(-1), 0);
+        assertEquals(Math.max(23, skin.textWidth) + 14, label.minWidth(-1), 0);
     }
 
     @Test public void whenTextIsLongThanEllipsisAndGraphicIsSetAndContentDisplayIsCENTER_computeMinWidth_ReturnsRightAnswer() {
+        skin.setPadding(new Insets(7, 7, 7, 7));
         Rectangle r = new Rectangle(23, 23);
         label.setGraphicTextGap(2);
         label.setGraphic(r);
         label.setContentDisplay(ContentDisplay.CENTER);
         label.setText("Wherefore art thou Romeo?");
         assertTrue(label.minWidth(-1) >= 0);
-        assertEquals(Math.max(23, skin.ellipsisWidth), label.minWidth(-1), 0);
+        assertEquals(Math.max(23, skin.ellipsisWidth) + 14, label.minWidth(-1), 0);
     }
 
     @Test public void whenTextIsShorterThanEllipsisAndGraphicIsSetAndContentDisplayIsTOP_computeMinWidth_ReturnsRightAnswer() {
+        skin.setPadding(new Insets(7, 7, 7, 7));
         Rectangle r = new Rectangle(23, 23);
         label.setGraphicTextGap(2);
         label.setGraphic(r);
         label.setContentDisplay(ContentDisplay.TOP);
         label.setText(".");
         assertTrue(label.minWidth(-1) >= 0);
-        assertEquals(Math.max(23, skin.textWidth), label.minWidth(-1), 0);
+        assertEquals(Math.max(23, skin.textWidth) + 14, label.minWidth(-1), 0);
     }
 
     @Test public void whenTextIsLongThanEllipsisAndGraphicIsSetAndContentDisplayIsTOP_computeMinWidth_ReturnsRightAnswer() {
+        skin.setPadding(new Insets(7, 7, 7, 7));
         Rectangle r = new Rectangle(23, 23);
         label.setGraphicTextGap(2);
         label.setGraphic(r);
         label.setContentDisplay(ContentDisplay.TOP);
         label.setText("Wherefore art thou Romeo?");
         assertTrue(label.minWidth(-1) >= 0);
-        assertEquals(Math.max(23, skin.ellipsisWidth), label.minWidth(-1), 0);
+        assertEquals(Math.max(23, skin.ellipsisWidth) + 14, label.minWidth(-1), 0);
     }
 
     @Test public void whenTextIsShorterThanEllipsisAndGraphicIsSetAndContentDisplayIsBOTTOM_computeMinWidth_ReturnsRightAnswer() {
+        skin.setPadding(new Insets(7, 7, 7, 7));
         Rectangle r = new Rectangle(23, 23);
         label.setGraphicTextGap(2);
         label.setGraphic(r);
         label.setContentDisplay(ContentDisplay.BOTTOM);
         label.setText(".");
         assertTrue(label.minWidth(-1) >= 0);
-        assertEquals(Math.max(23, skin.textWidth), label.minWidth(-1), 0);
+        assertEquals(Math.max(23, skin.textWidth) + 14, label.minWidth(-1), 0);
     }
 
     @Test public void whenTextIsLongThanEllipsisAndGraphicIsSetAndContentDisplayIsBOTTOM_computeMinWidth_ReturnsRightAnswer() {
+        skin.setPadding(new Insets(7, 7, 7, 7));
         Rectangle r = new Rectangle(23, 23);
         label.setGraphicTextGap(2);
         label.setGraphic(r);
         label.setContentDisplay(ContentDisplay.BOTTOM);
         label.setText("Wherefore art thou Romeo?");
         assertTrue(label.minWidth(-1) >= 0);
-        assertEquals(Math.max(23, skin.ellipsisWidth), label.minWidth(-1), 0);
+        assertEquals(Math.max(23, skin.ellipsisWidth) + 14, label.minWidth(-1), 0);
     }
 
     @Test public void whenTextIsShorterThanEllipsisAndGraphicIsSetAndContentDisplayIsGRAPHIC_ONLY_computeMinWidth_ReturnsRightAnswer() {
+        skin.setPadding(new Insets(7, 7, 7, 7));
         Rectangle r = new Rectangle(3, 3);
         label.setGraphicTextGap(2);
         label.setGraphic(r);
         label.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
         label.setText(".");
         assertTrue(label.minWidth(-1) >= 0);
-        assertEquals(3, label.minWidth(-1), 0);
+        assertEquals(3 + 14, label.minWidth(-1), 0);
     }
 
     @Test public void whenTextIsLongThanEllipsisAndGraphicIsSetAndContentDisplayIsGRAPHIC_ONLY_computeMinWidth_ReturnsRightAnswer() {
+        skin.setPadding(new Insets(7, 7, 7, 7));
         Rectangle r = new Rectangle(3, 3);
         label.setGraphicTextGap(2);
         label.setGraphic(r);
         label.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
         label.setText("Wherefore art thou Romeo?");
         assertTrue(label.minWidth(-1) >= 0);
-        assertEquals(3, label.minWidth(-1), 0);
+        assertEquals(3 + 14, label.minWidth(-1), 0);
     }
 
     @Test public void whenTextIsShorterThanEllipsisAndGraphicIsSetAndContentDisplayIsTEXT_ONLY_computeMinWidth_ReturnsRightAnswer() {
+        skin.setPadding(new Insets(7, 7, 7, 7));
         Rectangle r = new Rectangle(230, 230);
         label.setGraphicTextGap(2);
         label.setGraphic(r);
         label.setContentDisplay(ContentDisplay.TEXT_ONLY);
         label.setText(".");
         assertTrue(label.minWidth(-1) >= 0);
-        assertEquals(skin.textWidth, label.minWidth(-1), 0);
+        assertEquals(skin.textWidth + 14, label.minWidth(-1), 0);
     }
 
     @Test public void whenTextIsLongThanEllipsisAndGraphicIsSetAndContentDisplayIsTEXT_ONLY_computeMinWidth_ReturnsRightAnswer() {
+        skin.setPadding(new Insets(7, 7, 7, 7));
         Rectangle r = new Rectangle(230, 230);
         label.setGraphicTextGap(2);
         label.setGraphic(r);
         label.setContentDisplay(ContentDisplay.TEXT_ONLY);
         label.setText("Wherefore art thou Romeo?");
         assertTrue(label.minWidth(-1) >= 0);
-        assertEquals(skin.ellipsisWidth, label.minWidth(-1), 0);
+        assertEquals(skin.ellipsisWidth + 14, label.minWidth(-1), 0);
     }
 
     /****************************************************************************
@@ -863,24 +890,22 @@
         assertEquals(14 + textWidth, label.prefWidth(-1), 0);
     }
 
-    @Ignore ("Need to decide whether the gap should be included here or not")
-    @Test public void whenTextIsNullAndGraphicIsSetWithRIGHTContentDisplay_computePrefWidth_ReturnsGraphicPlusGapPlusPadding() {
+    @Test public void whenTextIsNullAndGraphicIsSetWithRIGHTContentDisplay_computePrefWidth_ReturnsGraphicPlusPaddingNotIncludingGap() {
         label.setText(null);
         label.setGraphic(new Rectangle(0, 0, 20, 20));
         label.setGraphicTextGap(6.5);
         label.setContentDisplay(ContentDisplay.RIGHT);
         skin.setPadding(new Insets(7, 7, 7, 7));
-        assertEquals(14 + 6.5 + 20, label.prefWidth(-1), 0);
+        assertEquals(20 + 14, label.prefWidth(-1), 0);
     }
-    
-    @Ignore ("Need to decide whether the gap should be included here or not")
-    @Test public void whenTextIsEmptyAndGraphicIsSetWithRIGHTContentDisplay_computePrefWidth_ReturnsGraphicPlusGapPlusPadding() {
+
+    @Test public void whenTextIsEmptyAndGraphicIsSetWithRIGHTContentDisplay_computePrefWidth_ReturnsGraphicPlusPaddingNotIncludingGap() {
         label.setText("");
         label.setGraphic(new Rectangle(0, 0, 20, 20));
         label.setGraphicTextGap(6.5);
         label.setContentDisplay(ContentDisplay.RIGHT);
         skin.setPadding(new Insets(7, 7, 7, 7));
-        assertEquals(14 + 6.5 + 20, label.prefWidth(-1), 0);
+        assertEquals(20 + 14, label.prefWidth(-1), 0);
     }
     
     @Test public void whenTextIsSetAndGraphicIsSetWithRIGHTContentDisplay_computePrefWidth_ReturnsTextWidthPlusGraphicWidthPlusGapPlusPadding() {
@@ -930,24 +955,22 @@
         assertEquals(14 + textWidth, label.prefWidth(-1), 0);
     }
 
-    @Ignore ("Need to decide whether the gap should be included here or not")
-    @Test public void whenTextIsNullAndGraphicIsSetWithLEFTContentDisplay_computePrefWidth_ReturnsGraphicPlusGapPlusPadding() {
+    @Test public void whenTextIsNullAndGraphicIsSetWithLEFTContentDisplay_computePrefWidth_ReturnsGraphicPlusPaddingNotIncludingGap() {
         label.setText(null);
         label.setGraphic(new Rectangle(0, 0, 20, 20));
         label.setGraphicTextGap(6.5);
         label.setContentDisplay(ContentDisplay.LEFT);
         skin.setPadding(new Insets(7, 7, 7, 7));
-        assertEquals(14 + 6.5 + 20, label.prefWidth(-1), 0);
+        assertEquals(20 + 14, label.prefWidth(-1), 0);
     }
-    
-    @Ignore ("Need to decide whether the gap should be included here or not")
-    @Test public void whenTextIsEmptyAndGraphicIsSetWithLEFTContentDisplay_computePrefWidth_ReturnsGraphicPlusGapPlusPadding() {
+
+    @Test public void whenTextIsEmptyAndGraphicIsSetWithLEFTContentDisplay_computePrefWidth_ReturnsGraphicPlusPaddingNotIncludingGap() {
         label.setText("");
         label.setGraphic(new Rectangle(0, 0, 20, 20));
         label.setGraphicTextGap(6.5);
         label.setContentDisplay(ContentDisplay.LEFT);
         skin.setPadding(new Insets(7, 7, 7, 7));
-        assertEquals(14 + 6.5 + 20, label.prefWidth(-1), 0);
+        assertEquals(20 + 14, label.prefWidth(-1), 0);
     }
     
     @Test public void whenTextIsSetAndGraphicIsSetWithLEFTContentDisplay_computePrefWidth_ReturnsTextWidthPlusGraphicWidthPlusGapPlusPadding() {
@@ -1442,24 +1465,22 @@
         assertEquals(14 + textWidth, label.maxWidth(-1), 0);
     }
 
-    @Ignore ("Need to decide whether the gap should be included here or not")
-    @Test public void whenTextIsNullAndGraphicIsSetWithRIGHTContentDisplay_computeMaxWidth_ReturnsGraphicPlusGapPlusPadding() {
+    @Test public void whenTextIsNullAndGraphicIsSetWithRIGHTContentDisplay_computeMaxWidth_ReturnsGraphicPlusPaddingNotIncludingGap() {
         label.setText(null);
         label.setGraphic(new Rectangle(0, 0, 20, 20));
         label.setGraphicTextGap(6.5);
         label.setContentDisplay(ContentDisplay.RIGHT);
         skin.setPadding(new Insets(7, 7, 7, 7));
-        assertEquals(14 + 6.5 + 20, label.maxWidth(-1), 0);
+        assertEquals(20 + 14, label.maxWidth(-1), 0);
     }
-    
-    @Ignore ("Need to decide whether the gap should be included here or not")
-    @Test public void whenTextIsEmptyAndGraphicIsSetWithRIGHTContentDisplay_computeMaxWidth_ReturnsGraphicPlusGapPlusPadding() {
+
+    @Test public void whenTextIsEmptyAndGraphicIsSetWithRIGHTContentDisplay_computeMaxWidth_ReturnsGraphicPlusPaddingNotIncludingGap() {
         label.setText("");
         label.setGraphic(new Rectangle(0, 0, 20, 20));
         label.setGraphicTextGap(6.5);
         label.setContentDisplay(ContentDisplay.RIGHT);
         skin.setPadding(new Insets(7, 7, 7, 7));
-        assertEquals(14 + 6.5 + 20, label.maxWidth(-1), 0);
+        assertEquals(20 + 14, label.maxWidth(-1), 0);
     }
     
     @Test public void whenTextIsSetAndGraphicIsSetWithRIGHTContentDisplay_computeMaxWidth_ReturnsTextWidthPlusGraphicWidthPlusGapPlusPadding() {
@@ -1509,24 +1530,22 @@
         assertEquals(14 + textWidth, label.maxWidth(-1), 0);
     }
 
-    @Ignore ("Need to decide whether the gap should be included here or not")
-    @Test public void whenTextIsNullAndGraphicIsSetWithLEFTContentDisplay_computeMaxWidth_ReturnsGraphicPlusGapPlusPadding() {
+    @Test public void whenTextIsNullAndGraphicIsSetWithLEFTContentDisplay_computeMaxWidth_ReturnsGraphicPlusPaddingNotIncludingGap() {
         label.setText(null);
         label.setGraphic(new Rectangle(0, 0, 20, 20));
         label.setGraphicTextGap(6.5);
         label.setContentDisplay(ContentDisplay.LEFT);
         skin.setPadding(new Insets(7, 7, 7, 7));
-        assertEquals(14 + 6.5 + 20, label.maxWidth(-1), 0);
+        assertEquals(20 + 14, label.maxWidth(-1), 0);
     }
-    
-    @Ignore ("Need to decide whether the gap should be included here or not")
-    @Test public void whenTextIsEmptyAndGraphicIsSetWithLEFTContentDisplay_computeMaxWidth_ReturnsGraphicPlusGapPlusPadding() {
+
+    @Test public void whenTextIsEmptyAndGraphicIsSetWithLEFTContentDisplay_computeMaxWidth_ReturnsGraphicPlusPaddingNotIncludingGap() {
         label.setText("");
         label.setGraphic(new Rectangle(0, 0, 20, 20));
         label.setGraphicTextGap(6.5);
         label.setContentDisplay(ContentDisplay.LEFT);
         skin.setPadding(new Insets(7, 7, 7, 7));
-        assertEquals(14 + 6.5 + 20, label.maxWidth(-1), 0);
+        assertEquals(20 + 14, label.maxWidth(-1), 0);
     }
     
     @Test public void whenTextIsSetAndGraphicIsSetWithLEFTContentDisplay_computeMaxWidth_ReturnsTextWidthPlusGraphicWidthPlusGapPlusPadding() {
--- a/javafx-ui-controls/test/com/sun/javafx/scene/control/skin/ScrollPaneSkinTest.java	Thu Dec 01 10:13:04 2011 -0800
+++ b/javafx-ui-controls/test/com/sun/javafx/scene/control/skin/ScrollPaneSkinTest.java	Tue Dec 06 10:01:57 2011 -0500
@@ -19,8 +19,20 @@
 import javafx.stage.Stage;
 
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 
+import com.sun.javafx.pgstub.StubScene;
+import javafx.event.EventHandler;
+import javafx.scene.Group;
+import javafx.scene.Scene;
+import javafx.scene.shape.Rectangle;
+import javafx.stage.Stage;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+import javafx.scene.input.ScrollEvent;
+
 /**
  * @author mickf
  */
@@ -223,8 +235,115 @@
     }
     
     
+    private boolean scrolled;
+    /*
+    ** check if scrollPane content Horizontal position compensates for content size change
+    */
+    @Test public void checkIfScrollPaneWithinScrollPaneGetsScrollEvents() {
+
+        scrolled = false;
+
+        Rectangle rect = new Rectangle(100, 100, 100, 100);
+        rect.setOnScroll(new EventHandler<ScrollEvent>() {
+            @Override public void handle(ScrollEvent event) {
+                scrolled = true;
+            }
+        });
+        
+        final ScrollPane scrollPaneInner = new ScrollPane();
+        scrollPaneInner.setSkin(new com.sun.javafx.scene.control.skin.ScrollPaneSkin(scrollPaneInner));
+        scrollPaneInner.setHbarPolicy(ScrollPane.ScrollBarPolicy.ALWAYS);
+        scrollPaneInner.setVbarPolicy(ScrollPane.ScrollBarPolicy.ALWAYS);
+        scrollPaneInner.setPrefWidth(100);
+        scrollPaneInner.setPrefHeight(100);
+        scrollPaneInner.setPannable(true);
+        scrollPaneInner.setContent(rect);
+  
+        Pane pOuter = new Pane();
+        pOuter.setPrefWidth(600);
+        pOuter.setPrefHeight(600);
+        pOuter.getChildren().add(scrollPaneInner);
+        
+        final ScrollPane scrollPaneOuter = new ScrollPane();
+        scrollPaneOuter.setSkin(new com.sun.javafx.scene.control.skin.ScrollPaneSkin(scrollPaneOuter));
+        scrollPaneOuter.setHbarPolicy(ScrollPane.ScrollBarPolicy.ALWAYS);
+        scrollPaneOuter.setVbarPolicy(ScrollPane.ScrollBarPolicy.ALWAYS);
+        scrollPaneOuter.setPrefWidth(500);
+        scrollPaneOuter.setPrefHeight(500);
+        scrollPaneOuter.setPannable(true);
+        scrollPaneOuter.setOnScroll(new EventHandler<ScrollEvent>() {
+            @Override public void handle(ScrollEvent event) {
+                scrolled = true;
+            }
+        });
+        scrollPaneOuter.setContent(pOuter);
+                
+        Scene scene = new Scene(new Group(), 700, 700);
+        ((Group) scene.getRoot()).getChildren().clear();
+        ((Group) scene.getRoot()).getChildren().add(scrollPaneOuter);
+        scrolled = false;
+
+        Stage stage = new Stage();
+        stage.setScene(scene);
+        stage.show();
+ 
+        Event.fireEvent(rect, 
+              ScrollEvent.impl_scrollEvent(
+                          0.0, -50.0,
+                          ScrollEvent.HorizontalTextScrollUnits.NONE, 10.0,
+                          ScrollEvent.VerticalTextScrollUnits.NONE, 10.0,
+                          50, 50,
+                          50, 50,
+                          false, false, false, false));
+
+        /*
+        ** did it work?
+        */
+        assertTrue(scrollPaneInner.getVvalue() > 0.0);
+    }
     
-    
+
+    boolean sceneClicked = false;
+    /*
+    ** check if unconsumed MouseClicked events on a scrollPane reach it's parent.
+    */
+    @Test public void checkIfScrollPaneConsumesMouseClickedEvents() {
+        ScrollPane scrollPaneInner = new ScrollPane();
+        scrollPaneInner.setSkin(new com.sun.javafx.scene.control.skin.ScrollPaneSkin(scrollPaneInner));
+        scrollPaneInner.setHbarPolicy(ScrollPane.ScrollBarPolicy.ALWAYS);
+        scrollPaneInner.setVbarPolicy(ScrollPane.ScrollBarPolicy.ALWAYS);
+        scrollPaneInner.setTranslateX(70);
+        scrollPaneInner.setTranslateY(30);
+        scrollPaneInner.setPrefWidth(100);
+        scrollPaneInner.setPrefHeight(100);
+        scrollPaneInner.setPannable(true);     
+
+        Scene scene = new Scene(new Group(), 400, 400);
+        scene.setOnMouseClicked(new EventHandler<MouseEvent>() {
+            public void handle(MouseEvent me) {
+                sceneClicked = true;
+            }
+        });
+        
+        ((Group) scene.getRoot()).getChildren().clear();
+        ((Group) scene.getRoot()).getChildren().add(scrollPaneInner);
+
+        Stage stage = new Stage();
+        stage.setScene(scene);     
+        stage.show();
+
+        Event.fireEvent(scrollPaneInner,
+              MouseEvent.impl_mouseEvent(50.0, 50.0, 50.0, 50.0,
+                         MouseButton.PRIMARY, 1,
+                         false, false, false, false, false,
+                         true, false, false,
+                         MouseEvent.MOUSE_CLICKED));
+
+        /*
+        ** did it work?
+        */
+        assertTrue(sceneClicked == true);
+    }
     
     public static final class ScrollPaneSkinMock extends ScrollPaneSkin {
         boolean propertyChanged = false;
--- a/javafx-ui-controls/test/javafx/scene/control/CellTest.java	Thu Dec 01 10:13:04 2011 -0800
+++ b/javafx-ui-controls/test/javafx/scene/control/CellTest.java	Tue Dec 06 10:01:57 2011 -0500
@@ -43,6 +43,15 @@
 
     @Before public void setup() throws Exception {
         cell = (Cell<String>) type.newInstance();
+        
+        // Empty TableCells can be selected, as long as the row they exist in
+        // is not empty, so here we set a TableRow to ensure testing works 
+        // properly
+        if (cell instanceof TableCell) {
+            TableRow tableRow = new TableRow();
+            tableRow.updateItem("TableRow", false);
+            ((TableCell)cell).updateTableRow(tableRow);
+        }
     }
 
     /*********************************************************************